leocad/common/camera.cpp

1315 lines
38 KiB
C++
Raw Normal View History

#include "lc_global.h"
2012-03-29 03:10:55 +02:00
#include "lc_math.h"
#include "lc_colors.h"
2011-09-07 23:06:51 +02:00
#include <stdlib.h>
#include <string.h>
#include <math.h>
2013-01-27 02:22:37 +01:00
#include <float.h>
#include "lc_file.h"
2011-09-07 23:06:51 +02:00
#include "camera.h"
2014-04-14 05:20:16 +02:00
#include "lc_application.h"
#include "lc_context.h"
2011-09-07 23:06:51 +02:00
2014-11-24 01:43:13 +01:00
#define LC_CAMERA_POSITION_EDGE 7.5f
#define LC_CAMERA_TARGET_EDGE 7.5f
2014-08-30 21:48:36 +02:00
#define LC_CAMERA_SAVE_VERSION 7 // LeoCAD 0.80
2011-09-07 23:06:51 +02:00
2014-05-01 20:42:11 +02:00
lcCamera::lcCamera(bool Simple)
2020-04-19 04:45:21 +02:00
: lcObject(lcObjectType::Camera)
2011-09-07 23:06:51 +02:00
{
2012-08-20 06:05:56 +02:00
Initialize();
if (Simple)
mState |= LC_CAMERA_SIMPLE;
2012-08-23 20:47:37 +02:00
else
{
mPosition.SetValue(lcVector3(-250.0f, -250.0f, 75.0f));
mTargetPosition.SetValue(lcVector3(0.0f, 0.0f, 0.0f));
mUpVector.SetValue(lcVector3(-0.2357f, -0.2357f, 0.94281f));
2012-08-23 20:47:37 +02:00
2014-01-30 04:13:34 +01:00
UpdatePosition(1);
2012-08-23 20:47:37 +02:00
}
2011-09-07 23:06:51 +02:00
}
2014-05-01 20:42:11 +02:00
lcCamera::lcCamera(float ex, float ey, float ez, float tx, float ty, float tz)
2020-04-19 04:45:21 +02:00
: lcObject(lcObjectType::Camera)
2011-09-07 23:06:51 +02:00
{
2012-08-22 03:13:32 +02:00
// Fix the up vector
lcVector3 UpVector(0, 0, 1), FrontVector(ex - tx, ey - ty, ez - tz), SideVector;
FrontVector.Normalize();
if (FrontVector == UpVector)
SideVector = lcVector3(1, 0, 0);
else
SideVector = lcCross(FrontVector, UpVector);
UpVector = lcCross(SideVector, FrontVector);
UpVector.Normalize();
Initialize();
mPosition.SetValue(lcVector3(ex, ey, ez));
mTargetPosition.SetValue(lcVector3(tx, ty, tz));
mUpVector.SetValue(UpVector);
2012-08-22 03:13:32 +02:00
2014-01-30 04:13:34 +01:00
UpdatePosition(1);
2011-09-07 23:06:51 +02:00
}
2014-05-01 20:42:11 +02:00
lcCamera::~lcCamera()
2011-09-07 23:06:51 +02:00
{
}
QString lcCamera::GetCameraTypeString(lcCameraType CameraType)
{
switch (CameraType)
{
case lcCameraType::Perspective:
return QT_TRANSLATE_NOOP("Camera Type", "Perspective");
case lcCameraType::Orthographic:
return QT_TRANSLATE_NOOP("Camera Type", "Orthographic");
case lcCameraType::Count:
break;
}
return QString();
}
QStringList lcCamera::GetCameraTypeStrings()
{
QStringList CameraType;
for (int CameraTypeIndex = 0; CameraTypeIndex < static_cast<int>(lcCameraType::Count); CameraTypeIndex++)
CameraType.push_back(GetCameraTypeString(static_cast<lcCameraType>(CameraTypeIndex)));
return CameraType;
}
2021-01-02 00:04:27 +01:00
lcViewpoint lcCamera::GetViewpoint(const QString& ViewpointName)
{
const QLatin1String ViewpointNames[] =
{
QLatin1String("front"),
QLatin1String("back"),
QLatin1String("top"),
QLatin1String("bottom"),
QLatin1String("left"),
QLatin1String("right"),
QLatin1String("home")
};
LC_ARRAY_SIZE_CHECK(ViewpointNames, lcViewpoint::Count);
for (int ViewpointIndex = 0; ViewpointIndex < static_cast<int>(lcViewpoint::Count); ViewpointIndex++)
if (ViewpointNames[ViewpointIndex] == ViewpointName)
return static_cast<lcViewpoint>(ViewpointIndex);
return lcViewpoint::Count;
}
2014-05-01 20:42:11 +02:00
void lcCamera::Initialize()
2011-09-07 23:06:51 +02:00
{
2012-08-23 20:47:37 +02:00
m_fovy = 30.0f;
2014-08-30 21:48:36 +02:00
m_zNear = 25.0f;
m_zFar = 50000.0f;
mState = 0;
2020-12-14 01:27:21 +01:00
}
2024-02-20 02:38:04 +01:00
bool lcCamera::SetName(const QString& Name)
2020-12-14 01:27:21 +01:00
{
2024-02-20 02:38:04 +01:00
if (mName == Name)
return false;
2020-12-14 01:27:21 +01:00
mName = Name;
2024-02-20 02:38:04 +01:00
return true;
2011-09-07 23:06:51 +02:00
}
2024-06-04 18:34:38 +02:00
void lcCamera::CreateName(const std::vector<std::unique_ptr<lcCamera>>& Cameras)
2012-08-22 03:13:32 +02:00
{
2020-12-14 01:27:21 +01:00
if (!mName.isEmpty())
{
bool Found = false;
2020-12-14 01:27:21 +01:00
2024-06-04 18:34:38 +02:00
for (const std::unique_ptr<lcCamera>& Camera : Cameras)
{
2020-12-14 01:27:21 +01:00
if (Camera->GetName() == mName)
{
Found = true;
break;
}
}
if (!Found)
return;
}
2020-12-14 01:27:21 +01:00
int MaxCameraNumber = 0;
const QLatin1String Prefix("Camera ");
2024-06-04 18:34:38 +02:00
for (const std::unique_ptr<lcCamera>& Camera : Cameras)
2020-12-14 01:27:21 +01:00
{
QString CameraName = Camera->GetName();
if (CameraName.startsWith(Prefix))
{
bool Ok = false;
2021-07-06 02:07:24 +02:00
int CameraNumber = CameraName.mid(Prefix.size()).toInt(&Ok);
2012-08-22 03:13:32 +02:00
2020-12-14 01:27:21 +01:00
if (Ok && CameraNumber > MaxCameraNumber)
MaxCameraNumber = CameraNumber;
}
}
2012-08-22 03:13:32 +02:00
2020-12-14 01:27:21 +01:00
mName = Prefix + QString::number(MaxCameraNumber + 1);
2012-08-22 03:13:32 +02:00
}
bool lcCamera::SetCameraType(lcCameraType CameraType)
{
if (static_cast<int>(CameraType) < 0 || CameraType >= lcCameraType::Count)
return false;
if (GetCameraType() == CameraType)
return false;
SetOrtho(CameraType == lcCameraType::Orthographic);
return true;
}
2014-09-05 02:24:28 +02:00
void lcCamera::SaveLDraw(QTextStream& Stream) const
{
2021-11-15 03:34:24 +01:00
const QLatin1String LineEnding("\r\n");
2014-09-08 21:42:20 +02:00
Stream << QLatin1String("0 !LEOCAD CAMERA FOV ") << m_fovy << QLatin1String(" ZNEAR ") << m_zNear << QLatin1String(" ZFAR ") << m_zFar << LineEnding;
mPosition.Save(Stream, "CAMERA", "POSITION", true);
mTargetPosition.Save(Stream, "CAMERA", "TARGET_POSITION", true);
mUpVector.Save(Stream, "CAMERA", "UP_VECTOR", true);
2014-09-08 21:42:20 +02:00
Stream << QLatin1String("0 !LEOCAD CAMERA ");
if (IsHidden())
Stream << QLatin1String("HIDDEN");
if (IsOrtho())
Stream << QLatin1String("ORTHOGRAPHIC ");
2020-12-14 01:27:21 +01:00
Stream << QLatin1String("NAME ") << mName << LineEnding;
}
2014-09-03 16:34:53 +02:00
bool lcCamera::ParseLDrawLine(QTextStream& Stream)
{
2014-09-08 21:42:20 +02:00
while (!Stream.atEnd())
{
2014-09-08 21:42:20 +02:00
QString Token;
Stream >> Token;
if (Token == QLatin1String("HIDDEN"))
2023-10-02 01:24:42 +02:00
SetHidden(true);
2014-09-08 21:42:20 +02:00
else if (Token == QLatin1String("ORTHOGRAPHIC"))
SetOrtho(true);
else if (Token == QLatin1String("FOV"))
Stream >> m_fovy;
else if (Token == QLatin1String("ZNEAR"))
Stream >> m_zNear;
else if (Token == QLatin1String("ZFAR"))
Stream >> m_zFar;
2023-12-28 20:32:25 +01:00
else if (mPosition.Load(Stream, Token, "POSITION"))
2023-10-02 01:24:42 +02:00
continue;
2023-12-28 20:32:25 +01:00
else if (mTargetPosition.Load(Stream, Token, "TARGET_POSITION"))
2023-10-02 01:24:42 +02:00
continue;
2023-12-28 20:32:25 +01:00
else if (mUpVector.Load(Stream, Token, "UP_VECTOR"))
2023-10-02 01:24:42 +02:00
continue;
2014-09-08 21:42:20 +02:00
else if (Token == QLatin1String("NAME"))
{
2020-12-14 01:27:21 +01:00
mName = Stream.readAll().trimmed();
2014-09-08 21:42:20 +02:00
return true;
}
}
return false;
}
2011-09-07 23:06:51 +02:00
/////////////////////////////////////////////////////////////////////////////
// Camera save/load
2014-05-01 20:42:11 +02:00
bool lcCamera::FileLoad(lcFile& file)
2011-09-07 23:06:51 +02:00
{
2017-12-02 21:22:04 +01:00
quint8 version, ch;
2012-08-23 20:47:37 +02:00
version = file.ReadU8();
if (version > LC_CAMERA_SAVE_VERSION)
return false;
if (version > 5)
2014-08-31 02:53:12 +02:00
{
if (file.ReadU8() != 1)
2012-08-23 20:47:37 +02:00
return false;
2017-12-02 21:22:04 +01:00
quint16 time;
2014-08-31 02:53:12 +02:00
float param[4];
2017-12-02 21:22:04 +01:00
quint8 type;
quint32 n;
2014-08-31 02:53:12 +02:00
file.ReadU32(&n, 1);
while (n--)
{
file.ReadU16(&time, 1);
file.ReadFloats(param, 4);
file.ReadU8(&type, 1);
}
file.ReadU32(&n, 1);
while (n--)
{
file.ReadU16(&time, 1);
file.ReadFloats(param, 4);
file.ReadU8(&type, 1);
}
}
2012-08-23 20:47:37 +02:00
if (version == 4)
{
2020-12-14 01:27:21 +01:00
char Name[81];
file.ReadBuffer(Name, 80);
2012-08-23 20:47:37 +02:00
}
else
{
ch = file.ReadU8();
if (ch == 0xFF)
return false;
2020-12-14 01:27:21 +01:00
char Name[81];
file.ReadBuffer(Name, ch);
2012-08-23 20:47:37 +02:00
}
if (version < 3)
{
double d[3];
file.ReadDoubles(d, 3);
file.ReadDoubles(d, 3);
file.ReadDoubles(d, 3);
}
if (version == 3)
{
ch = file.ReadU8();
while (ch--)
{
2017-12-02 21:22:04 +01:00
quint8 step;
2012-08-23 20:47:37 +02:00
double eye[3], target[3], up[3];
file.ReadDoubles(eye, 3);
file.ReadDoubles(target, 3);
file.ReadDoubles(up, 3);
file.ReadU8(&step, 1);
file.ReadS32(); // snapshot
file.ReadS32(); // cam
}
}
if (version < 4)
{
file.ReadDouble(); // m_fovy
file.ReadDouble(); // m_zFar
file.ReadDouble(); // m_zNear
2012-08-23 20:47:37 +02:00
}
else
{
2017-12-02 21:22:04 +01:00
qint32 n;
2012-08-23 20:47:37 +02:00
if (version < 6)
{
2017-12-02 21:22:04 +01:00
quint16 time;
2012-08-23 20:47:37 +02:00
float param[4];
2017-12-02 21:22:04 +01:00
quint8 type;
2012-08-23 20:47:37 +02:00
n = file.ReadS32();
while (n--)
{
file.ReadU16(&time, 1);
file.ReadFloats(param, 3);
file.ReadU8(&type, 1);
}
n = file.ReadS32();
while (n--)
{
file.ReadU16(&time, 1);
file.ReadFloats(param, 3);
file.ReadU8(&type, 1);
}
}
float f;
file.ReadFloats(&f, 1); // m_fovy
file.ReadFloats(&f, 1); // m_zFar
file.ReadFloats(&f, 1); // m_zNear
2012-08-23 20:47:37 +02:00
if (version < 5)
{
n = file.ReadS32();
}
else
{
ch = file.ReadU8();
2015-01-16 03:07:31 +01:00
file.ReadU8();
2012-08-23 20:47:37 +02:00
}
}
if ((version > 1) && (version < 4))
{
2017-12-02 21:22:04 +01:00
quint32 show;
qint32 user;
2012-08-23 20:47:37 +02:00
2013-01-06 20:24:25 +01:00
file.ReadU32(&show, 1);
2012-08-23 20:47:37 +02:00
// if (version > 2)
2013-01-06 20:24:25 +01:00
file.ReadS32(&user, 1);
2014-08-30 21:48:36 +02:00
}
2012-08-23 20:47:37 +02:00
return true;
2011-09-07 23:06:51 +02:00
}
2016-02-19 18:53:54 +01:00
void lcCamera::CompareBoundingBox(lcVector3& Min, lcVector3& Max)
2014-11-10 01:06:11 +01:00
{
const lcVector3 Points[2] =
{
mPosition, mTargetPosition
};
for (int i = 0; i < 2; i++)
{
const lcVector3& Point = Points[i];
2016-02-19 18:53:54 +01:00
// TODO: this should check the entire mesh
Min = lcMin(Point, Min);
Max = lcMax(Point, Max);
2014-11-10 01:06:11 +01:00
}
}
2011-09-07 23:06:51 +02:00
void lcCamera::MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance)
2011-09-07 23:06:51 +02:00
{
if (IsSimple())
2014-06-22 19:39:15 +02:00
AddKey = false;
if (IsSelected(LC_CAMERA_SECTION_POSITION))
2012-05-29 01:33:22 +02:00
{
2023-12-28 20:32:25 +01:00
mPosition.ChangeKey(mPosition + Distance, Step, AddKey);
2012-08-20 06:05:56 +02:00
}
2011-09-07 23:06:51 +02:00
if (IsSelected(LC_CAMERA_SECTION_TARGET))
2012-08-20 06:05:56 +02:00
{
2023-12-28 20:32:25 +01:00
mTargetPosition.ChangeKey(mTargetPosition + Distance, Step, AddKey);
2012-08-20 06:05:56 +02:00
}
2014-08-31 02:53:12 +02:00
else if (IsSelected(LC_CAMERA_SECTION_UPVECTOR))
2012-08-23 20:47:37 +02:00
{
2023-12-28 20:32:25 +01:00
mUpVector.ChangeKey(lcNormalize(mUpVector + Distance), Step, AddKey);
2012-08-23 20:47:37 +02:00
}
2011-09-07 23:06:51 +02:00
}
void lcCamera::MoveRelative(const lcVector3& Distance, lcStep Step, bool AddKey)
{
if (IsSimple())
AddKey = false;
2021-11-15 03:34:24 +01:00
const lcVector3 Relative = lcMul30(Distance, lcMatrix44Transpose(mWorldView)) * 5.0f;
2023-12-28 20:32:25 +01:00
mPosition.ChangeKey(mPosition + Relative, Step, AddKey);
mTargetPosition.ChangeKey(mTargetPosition + Relative, Step, AddKey);
UpdatePosition(Step);
}
2014-07-06 08:04:09 +02:00
void lcCamera::UpdatePosition(lcStep Step)
2011-09-07 23:06:51 +02:00
{
2023-12-28 20:32:25 +01:00
mPosition.Update(Step);
mTargetPosition.Update(Step);
mUpVector.Update(Step);
2012-05-29 01:33:22 +02:00
2021-11-15 03:34:24 +01:00
const lcVector3 FrontVector(mPosition - mTargetPosition);
const lcVector3 SideVector = lcCross(FrontVector, mUpVector);
2023-12-28 20:32:25 +01:00
const lcVector3 UpVector = lcNormalize(lcCross(SideVector, FrontVector));
2012-05-29 01:33:22 +02:00
2023-12-28 20:32:25 +01:00
mWorldView = lcMatrix44LookAt(mPosition, mTargetPosition, UpVector);
2011-09-07 23:06:51 +02:00
}
void lcCamera::CopyPosition(const lcCamera* Camera)
{
m_fovy = Camera->m_fovy;
m_zNear = Camera->m_zNear;
m_zFar = Camera->m_zFar;
mWorldView = Camera->mWorldView;
mPosition = Camera->mPosition;
mTargetPosition = Camera->mTargetPosition;
mUpVector = Camera->mUpVector;
mState |= (Camera->mState & LC_CAMERA_ORTHO);
}
void lcCamera::CopySettings(const lcCamera* camera)
2012-08-20 06:05:56 +02:00
{
m_fovy = camera->m_fovy;
m_zNear = camera->m_zNear;
m_zFar = camera->m_zFar;
mState |= (camera->mState & LC_CAMERA_ORTHO);
2012-08-20 06:05:56 +02:00
}
void lcCamera::DrawInterface(lcContext* Context, const lcScene& Scene) const
2011-09-07 23:06:51 +02:00
{
Q_UNUSED(Scene);
2020-03-22 21:44:20 +01:00
Context->SetMaterial(lcMaterialType::UnlitColor);
2015-04-19 03:10:01 +02:00
lcMatrix44 ViewWorldMatrix = lcMatrix44AffineInverse(mWorldView);
ViewWorldMatrix.SetTranslation(lcVector3(0, 0, 0));
2021-11-15 03:34:24 +01:00
const lcMatrix44 CameraViewMatrix = lcMul(ViewWorldMatrix, lcMatrix44Translation(mPosition));
2015-05-17 01:04:35 +02:00
Context->SetWorldMatrix(CameraViewMatrix);
2015-04-19 03:10:01 +02:00
float Verts[(12 + 8 + 8 + 3 + 4) * 3];
float* CurVert = Verts;
float Length = lcLength(mPosition - mTargetPosition);
*CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = LC_CAMERA_POSITION_EDGE;
*CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = LC_CAMERA_POSITION_EDGE;
*CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = LC_CAMERA_POSITION_EDGE;
*CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = LC_CAMERA_POSITION_EDGE;
*CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE;
*CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE;
*CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE;
*CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE;
*CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE * 2;
*CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE * 2;
*CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE * 2;
*CurVert++ = LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE; *CurVert++ = -LC_CAMERA_POSITION_EDGE * 2;
*CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE - Length;
*CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE - Length;
*CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE - Length;
*CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE - Length;
*CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE - Length;
*CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE - Length;
*CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE - Length;
*CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE - Length;
*CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE + 25.0f; *CurVert++ = LC_CAMERA_TARGET_EDGE;
*CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE + 25.0f; *CurVert++ = LC_CAMERA_TARGET_EDGE;
*CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE + 25.0f; *CurVert++ = LC_CAMERA_TARGET_EDGE;
*CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE + 25.0f; *CurVert++ = LC_CAMERA_TARGET_EDGE;
*CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE + 25.0f; *CurVert++ = -LC_CAMERA_TARGET_EDGE;
*CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = LC_CAMERA_TARGET_EDGE + 25.0f; *CurVert++ = -LC_CAMERA_TARGET_EDGE;
*CurVert++ = -LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE + 25.0f; *CurVert++ = -LC_CAMERA_TARGET_EDGE;
*CurVert++ = LC_CAMERA_TARGET_EDGE; *CurVert++ = -LC_CAMERA_TARGET_EDGE + 25.0f; *CurVert++ = -LC_CAMERA_TARGET_EDGE;
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = 0.0f;
*CurVert++ = 0.0f; *CurVert++ = 0.0f; *CurVert++ = -Length;
*CurVert++ = 0.0f; *CurVert++ = 25.0f; *CurVert++ = 0.0f;
const GLushort Indices[40 + 24 + 24 + 4 + 16] =
2012-05-29 01:33:22 +02:00
{
2015-04-19 03:10:01 +02:00
0, 1, 1, 2, 2, 3, 3, 0,
4, 5, 5, 6, 6, 7, 7, 4,
0, 4, 1, 5, 2, 6, 3, 7,
8, 9, 9, 10, 10, 11, 11, 8,
8, 28, 9, 28, 10, 28, 11, 28,
12, 13, 13, 14, 14, 15, 15, 12,
16, 17, 17, 18, 18, 19, 19, 16,
12, 16, 13, 17, 14, 18, 15, 19,
20, 21, 21, 22, 22, 23, 23, 20,
24, 25, 25, 26, 26, 27, 27, 24,
20, 24, 21, 25, 22, 26, 23, 27,
28, 29, 28, 30,
31, 32, 32, 33, 33, 34, 34, 31,
28, 31, 28, 32, 28, 33, 28, 34
2012-05-29 01:33:22 +02:00
};
2015-04-19 03:10:01 +02:00
Context->SetVertexBufferPointer(Verts);
2017-03-24 17:34:53 +01:00
Context->SetVertexFormatPosition(3);
2015-05-17 01:04:35 +02:00
Context->SetIndexBufferPointer(Indices);
2021-11-25 00:20:08 +01:00
const lcPreferences& Preferences = lcGetPreferences();
const float LineWidth = Preferences.mLineWidth;
const lcVector4 SelectedColor = lcVector4FromColor(Preferences.mObjectSelectedColor);
const lcVector4 FocusedColor = lcVector4FromColor(Preferences.mObjectFocusedColor);
const lcVector4 CameraColor = lcVector4FromColor(Preferences.mCameraColor);
2015-04-19 03:10:01 +02:00
if (!IsSelected())
2012-08-23 20:47:37 +02:00
{
2014-04-14 05:20:16 +02:00
Context->SetLineWidth(LineWidth);
2021-11-25 00:20:08 +01:00
Context->SetColor(CameraColor);
2012-08-23 20:47:37 +02:00
2015-05-17 01:04:35 +02:00
Context->DrawIndexedPrimitives(GL_LINES, 40 + 24 + 24 + 4, GL_UNSIGNED_SHORT, 0);
2012-08-23 20:47:37 +02:00
}
else
{
2015-04-19 03:10:01 +02:00
if (IsSelected(LC_CAMERA_SECTION_POSITION))
{
Context->SetLineWidth(2.0f * LineWidth);
if (IsFocused(LC_CAMERA_SECTION_POSITION))
2021-11-25 00:20:08 +01:00
Context->SetColor(FocusedColor);
2015-04-19 03:10:01 +02:00
else
2021-11-25 00:20:08 +01:00
Context->SetColor(SelectedColor);
2015-04-19 03:10:01 +02:00
}
else
{
Context->SetLineWidth(LineWidth);
2021-11-25 00:20:08 +01:00
Context->SetColor(CameraColor);
2015-04-19 03:10:01 +02:00
}
2014-02-16 08:23:55 +01:00
2015-05-17 01:04:35 +02:00
Context->DrawIndexedPrimitives(GL_LINES, 40, GL_UNSIGNED_SHORT, 0);
2012-08-23 20:47:37 +02:00
2015-04-19 03:10:01 +02:00
if (IsSelected(LC_CAMERA_SECTION_TARGET))
{
Context->SetLineWidth(2.0f * LineWidth);
if (IsFocused(LC_CAMERA_SECTION_TARGET))
2021-11-25 00:20:08 +01:00
Context->SetColor(FocusedColor);
2015-04-19 03:10:01 +02:00
else
2021-11-25 00:20:08 +01:00
Context->SetColor(SelectedColor);
2015-04-19 03:10:01 +02:00
}
else
2015-04-19 03:10:01 +02:00
{
Context->SetLineWidth(LineWidth);
2021-11-25 00:20:08 +01:00
Context->SetColor(CameraColor);
2015-04-19 03:10:01 +02:00
}
2012-08-23 20:47:37 +02:00
2015-05-17 01:04:35 +02:00
Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, 40 * 2);
2015-04-19 03:10:01 +02:00
if (IsSelected(LC_CAMERA_SECTION_UPVECTOR))
{
Context->SetLineWidth(2.0f * LineWidth);
if (IsFocused(LC_CAMERA_SECTION_UPVECTOR))
2021-11-25 00:20:08 +01:00
Context->SetColor(FocusedColor);
2015-04-19 03:10:01 +02:00
else
2021-11-25 00:20:08 +01:00
Context->SetColor(SelectedColor);
2015-04-19 03:10:01 +02:00
}
else
{
Context->SetLineWidth(LineWidth);
2021-11-25 00:20:08 +01:00
Context->SetColor(CameraColor);
2015-04-19 03:10:01 +02:00
}
2015-05-17 01:04:35 +02:00
Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, (40 + 24) * 2);
2021-11-25 00:20:08 +01:00
Context->SetColor(CameraColor);
2015-04-19 03:10:01 +02:00
Context->SetLineWidth(LineWidth);
2012-08-23 20:47:37 +02:00
2015-04-19 03:10:01 +02:00
float SizeY = tanf(LC_DTOR * m_fovy / 2) * Length;
float SizeX = SizeY * 1.333f;
*CurVert++ = SizeX; *CurVert++ = SizeY; *CurVert++ = -Length;
*CurVert++ = -SizeX; *CurVert++ = SizeY; *CurVert++ = -Length;
*CurVert++ = -SizeX; *CurVert++ = -SizeY; *CurVert++ = -Length;
*CurVert++ = SizeX; *CurVert++ = -SizeY; *CurVert++ = -Length;
2012-05-29 01:33:22 +02:00
2015-05-17 01:04:35 +02:00
Context->DrawIndexedPrimitives(GL_LINES, 4 + 16, GL_UNSIGNED_SHORT, (40 + 24 + 24) * 2);
2011-09-07 23:06:51 +02:00
}
}
2024-02-19 23:54:45 +01:00
QVariant lcCamera::GetPropertyValue(lcObjectPropertyId PropertyId) const
{
switch (PropertyId)
{
case lcObjectPropertyId::PieceId:
case lcObjectPropertyId::PieceColor:
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
break;
2024-02-20 02:38:04 +01:00
case lcObjectPropertyId::CameraName:
return GetName();
case lcObjectPropertyId::CameraType:
return static_cast<int>(GetCameraType());
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
case lcObjectPropertyId::CameraPositionX:
case lcObjectPropertyId::CameraPositionY:
case lcObjectPropertyId::CameraPositionZ:
case lcObjectPropertyId::CameraTargetX:
case lcObjectPropertyId::CameraTargetY:
case lcObjectPropertyId::CameraTargetZ:
case lcObjectPropertyId::CameraUpX:
case lcObjectPropertyId::CameraUpY:
case lcObjectPropertyId::CameraUpZ:
case lcObjectPropertyId::LightName:
case lcObjectPropertyId::LightType:
case lcObjectPropertyId::LightColor:
case lcObjectPropertyId::LightBlenderPower:
case lcObjectPropertyId::LightPOVRayPower:
case lcObjectPropertyId::LightCastShadow:
case lcObjectPropertyId::LightPOVRayFadeDistance:
case lcObjectPropertyId::LightPOVRayFadePower:
case lcObjectPropertyId::LightPointBlenderRadius:
case lcObjectPropertyId::LightSpotBlenderRadius:
case lcObjectPropertyId::LightDirectionalBlenderAngle:
case lcObjectPropertyId::LightAreaSizeX:
case lcObjectPropertyId::LightAreaSizeY:
case lcObjectPropertyId::LightSpotConeAngle:
case lcObjectPropertyId::LightSpotPenumbraAngle:
case lcObjectPropertyId::LightSpotPOVRayTightness:
case lcObjectPropertyId::LightAreaShape:
case lcObjectPropertyId::LightAreaPOVRayGridX:
case lcObjectPropertyId::LightAreaPOVRayGridY:
case lcObjectPropertyId::ObjectPositionX:
case lcObjectPropertyId::ObjectPositionY:
case lcObjectPropertyId::ObjectPositionZ:
case lcObjectPropertyId::ObjectRotationX:
case lcObjectPropertyId::ObjectRotationY:
case lcObjectPropertyId::ObjectRotationZ:
case lcObjectPropertyId::Count:
break;
}
2024-02-19 23:54:45 +01:00
return QVariant();
}
2024-02-19 23:54:45 +01:00
bool lcCamera::SetPropertyValue(lcObjectPropertyId PropertyId, lcStep Step, bool AddKey, QVariant Value)
{
2024-02-19 23:54:45 +01:00
Q_UNUSED(Step);
Q_UNUSED(AddKey);
switch (PropertyId)
{
case lcObjectPropertyId::PieceId:
case lcObjectPropertyId::PieceColor:
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
break;
2024-02-20 02:38:04 +01:00
case lcObjectPropertyId::CameraName:
return SetName(Value.toString());
case lcObjectPropertyId::CameraType:
return SetCameraType(static_cast<lcCameraType>(Value.toInt()));
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
case lcObjectPropertyId::CameraPositionX:
case lcObjectPropertyId::CameraPositionY:
case lcObjectPropertyId::CameraPositionZ:
case lcObjectPropertyId::CameraTargetX:
case lcObjectPropertyId::CameraTargetY:
case lcObjectPropertyId::CameraTargetZ:
case lcObjectPropertyId::CameraUpX:
case lcObjectPropertyId::CameraUpY:
case lcObjectPropertyId::CameraUpZ:
case lcObjectPropertyId::LightName:
case lcObjectPropertyId::LightType:
case lcObjectPropertyId::LightColor:
case lcObjectPropertyId::LightBlenderPower:
case lcObjectPropertyId::LightPOVRayPower:
case lcObjectPropertyId::LightCastShadow:
case lcObjectPropertyId::LightPOVRayFadeDistance:
case lcObjectPropertyId::LightPOVRayFadePower:
case lcObjectPropertyId::LightPointBlenderRadius:
case lcObjectPropertyId::LightSpotBlenderRadius:
case lcObjectPropertyId::LightDirectionalBlenderAngle:
case lcObjectPropertyId::LightAreaSizeX:
case lcObjectPropertyId::LightAreaSizeY:
case lcObjectPropertyId::LightSpotConeAngle:
case lcObjectPropertyId::LightSpotPenumbraAngle:
case lcObjectPropertyId::LightSpotPOVRayTightness:
case lcObjectPropertyId::LightAreaShape:
case lcObjectPropertyId::LightAreaPOVRayGridX:
case lcObjectPropertyId::LightAreaPOVRayGridY:
case lcObjectPropertyId::ObjectPositionX:
case lcObjectPropertyId::ObjectPositionY:
case lcObjectPropertyId::ObjectPositionZ:
case lcObjectPropertyId::ObjectRotationX:
case lcObjectPropertyId::ObjectRotationY:
case lcObjectPropertyId::ObjectRotationZ:
case lcObjectPropertyId::Count:
break;
}
return false;
}
2024-01-15 02:41:01 +01:00
bool lcCamera::HasKeyFrame(lcObjectPropertyId PropertyId, lcStep Time) const
{
switch (PropertyId)
{
case lcObjectPropertyId::PieceId:
case lcObjectPropertyId::PieceColor:
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
return false;
case lcObjectPropertyId::CameraPositionX:
case lcObjectPropertyId::CameraPositionY:
case lcObjectPropertyId::CameraPositionZ:
return mPosition.HasKeyFrame(Time);
case lcObjectPropertyId::CameraTargetX:
case lcObjectPropertyId::CameraTargetY:
case lcObjectPropertyId::CameraTargetZ:
return mTargetPosition.HasKeyFrame(Time);
case lcObjectPropertyId::CameraUpX:
case lcObjectPropertyId::CameraUpY:
case lcObjectPropertyId::CameraUpZ:
return mUpVector.HasKeyFrame(Time);
case lcObjectPropertyId::LightName:
case lcObjectPropertyId::LightType:
case lcObjectPropertyId::LightColor:
case lcObjectPropertyId::LightBlenderPower:
case lcObjectPropertyId::LightPOVRayPower:
2024-01-21 21:53:18 +01:00
case lcObjectPropertyId::LightCastShadow:
case lcObjectPropertyId::LightPOVRayFadeDistance:
case lcObjectPropertyId::LightPOVRayFadePower:
case lcObjectPropertyId::LightPointBlenderRadius:
case lcObjectPropertyId::LightSpotBlenderRadius:
case lcObjectPropertyId::LightDirectionalBlenderAngle:
2024-01-21 21:53:18 +01:00
case lcObjectPropertyId::LightAreaSizeX:
case lcObjectPropertyId::LightAreaSizeY:
case lcObjectPropertyId::LightSpotConeAngle:
case lcObjectPropertyId::LightSpotPenumbraAngle:
case lcObjectPropertyId::LightSpotPOVRayTightness:
2024-01-21 21:53:18 +01:00
case lcObjectPropertyId::LightAreaShape:
case lcObjectPropertyId::LightAreaPOVRayGridX:
case lcObjectPropertyId::LightAreaPOVRayGridY:
2024-01-21 21:53:18 +01:00
case lcObjectPropertyId::ObjectPositionX:
case lcObjectPropertyId::ObjectPositionY:
case lcObjectPropertyId::ObjectPositionZ:
case lcObjectPropertyId::ObjectRotationX:
case lcObjectPropertyId::ObjectRotationY:
case lcObjectPropertyId::ObjectRotationZ:
case lcObjectPropertyId::Count:
return false;
}
return false;
}
bool lcCamera::SetKeyFrame(lcObjectPropertyId PropertyId, lcStep Time, bool KeyFrame)
{
switch (PropertyId)
{
case lcObjectPropertyId::PieceId:
case lcObjectPropertyId::PieceColor:
case lcObjectPropertyId::PieceStepShow:
case lcObjectPropertyId::PieceStepHide:
case lcObjectPropertyId::CameraName:
case lcObjectPropertyId::CameraType:
case lcObjectPropertyId::CameraFOV:
case lcObjectPropertyId::CameraNear:
case lcObjectPropertyId::CameraFar:
return false;
case lcObjectPropertyId::CameraPositionX:
case lcObjectPropertyId::CameraPositionY:
case lcObjectPropertyId::CameraPositionZ:
return mPosition.SetKeyFrame(Time, KeyFrame);
case lcObjectPropertyId::CameraTargetX:
case lcObjectPropertyId::CameraTargetY:
case lcObjectPropertyId::CameraTargetZ:
return mTargetPosition.SetKeyFrame(Time, KeyFrame);
case lcObjectPropertyId::CameraUpX:
case lcObjectPropertyId::CameraUpY:
case lcObjectPropertyId::CameraUpZ:
return mUpVector.SetKeyFrame(Time, KeyFrame);
case lcObjectPropertyId::LightName:
case lcObjectPropertyId::LightType:
case lcObjectPropertyId::LightColor:
case lcObjectPropertyId::LightBlenderPower:
case lcObjectPropertyId::LightPOVRayPower:
2024-01-15 02:41:01 +01:00
case lcObjectPropertyId::LightCastShadow:
case lcObjectPropertyId::LightPOVRayFadeDistance:
case lcObjectPropertyId::LightPOVRayFadePower:
case lcObjectPropertyId::LightPointBlenderRadius:
case lcObjectPropertyId::LightSpotBlenderRadius:
case lcObjectPropertyId::LightDirectionalBlenderAngle:
2024-01-15 02:41:01 +01:00
case lcObjectPropertyId::LightAreaSizeX:
case lcObjectPropertyId::LightAreaSizeY:
case lcObjectPropertyId::LightSpotConeAngle:
case lcObjectPropertyId::LightSpotPenumbraAngle:
case lcObjectPropertyId::LightSpotPOVRayTightness:
2024-01-15 02:41:01 +01:00
case lcObjectPropertyId::LightAreaShape:
case lcObjectPropertyId::LightAreaPOVRayGridX:
case lcObjectPropertyId::LightAreaPOVRayGridY:
2024-01-15 02:41:01 +01:00
case lcObjectPropertyId::ObjectPositionX:
case lcObjectPropertyId::ObjectPositionY:
case lcObjectPropertyId::ObjectPositionZ:
case lcObjectPropertyId::ObjectRotationX:
case lcObjectPropertyId::ObjectRotationY:
case lcObjectPropertyId::ObjectRotationZ:
case lcObjectPropertyId::Count:
return false;
}
return false;
}
void lcCamera::RemoveKeyFrames()
{
mPosition.RemoveAllKeys();
mTargetPosition.RemoveAllKeys();
mUpVector.RemoveAllKeys();
}
2014-05-01 20:42:11 +02:00
void lcCamera::RayTest(lcObjectRayTest& ObjectRayTest) const
2011-09-07 23:06:51 +02:00
{
2014-11-24 01:43:13 +01:00
lcVector3 Min = lcVector3(-LC_CAMERA_POSITION_EDGE, -LC_CAMERA_POSITION_EDGE, -LC_CAMERA_POSITION_EDGE);
lcVector3 Max = lcVector3(LC_CAMERA_POSITION_EDGE, LC_CAMERA_POSITION_EDGE, LC_CAMERA_POSITION_EDGE);
2011-09-07 23:06:51 +02:00
lcVector3 Start = lcMul31(ObjectRayTest.Start, mWorldView);
lcVector3 End = lcMul31(ObjectRayTest.End, mWorldView);
float Distance;
lcVector3 Plane;
if (lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, nullptr, &Plane) && (Distance < ObjectRayTest.Distance))
{
2014-08-07 17:22:33 +02:00
ObjectRayTest.ObjectSection.Object = const_cast<lcCamera*>(this);
ObjectRayTest.ObjectSection.Section = LC_CAMERA_SECTION_POSITION;
ObjectRayTest.Distance = Distance;
ObjectRayTest.PieceInfoRayTest.Plane = Plane;
}
2014-11-24 01:43:13 +01:00
Min = lcVector3(-LC_CAMERA_TARGET_EDGE, -LC_CAMERA_TARGET_EDGE, -LC_CAMERA_TARGET_EDGE);
Max = lcVector3(LC_CAMERA_TARGET_EDGE, LC_CAMERA_TARGET_EDGE, LC_CAMERA_TARGET_EDGE);
lcMatrix44 WorldView = mWorldView;
WorldView.SetTranslation(lcMul30(-mTargetPosition, WorldView));
Start = lcMul31(ObjectRayTest.Start, WorldView);
End = lcMul31(ObjectRayTest.End, WorldView);
2011-09-07 23:06:51 +02:00
if (lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, nullptr, &Plane) && (Distance < ObjectRayTest.Distance))
2012-08-17 01:50:40 +02:00
{
2014-08-07 17:22:33 +02:00
ObjectRayTest.ObjectSection.Object = const_cast<lcCamera*>(this);
ObjectRayTest.ObjectSection.Section = LC_CAMERA_SECTION_TARGET;
ObjectRayTest.Distance = Distance;
ObjectRayTest.PieceInfoRayTest.Plane = Plane;
2012-08-17 01:50:40 +02:00
}
2011-09-07 23:06:51 +02:00
2021-11-15 03:34:24 +01:00
const lcMatrix44 ViewWorld = lcMatrix44AffineInverse(mWorldView);
const lcVector3 UpVectorPosition = lcMul31(lcVector3(0, 25, 0), ViewWorld);
WorldView = mWorldView;
WorldView.SetTranslation(lcMul30(-UpVectorPosition, WorldView));
Start = lcMul31(ObjectRayTest.Start, WorldView);
End = lcMul31(ObjectRayTest.End, WorldView);
if (lcBoundingBoxRayIntersectDistance(Min, Max, Start, End, &Distance, nullptr, &Plane) && (Distance < ObjectRayTest.Distance))
{
2014-08-07 17:22:33 +02:00
ObjectRayTest.ObjectSection.Object = const_cast<lcCamera*>(this);
ObjectRayTest.ObjectSection.Section = LC_CAMERA_SECTION_UPVECTOR;
ObjectRayTest.Distance = Distance;
ObjectRayTest.PieceInfoRayTest.Plane = Plane;
}
2011-09-07 23:06:51 +02:00
}
2014-05-01 20:42:11 +02:00
void lcCamera::BoxTest(lcObjectBoxTest& ObjectBoxTest) const
2012-08-23 20:47:37 +02:00
{
2014-11-24 01:43:13 +01:00
lcVector3 Min(-LC_CAMERA_POSITION_EDGE, -LC_CAMERA_POSITION_EDGE, -LC_CAMERA_POSITION_EDGE);
lcVector3 Max(LC_CAMERA_POSITION_EDGE, LC_CAMERA_POSITION_EDGE, LC_CAMERA_POSITION_EDGE);
2012-08-23 20:47:37 +02:00
lcVector4 LocalPlanes[6];
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
{
2021-11-15 03:34:24 +01:00
const lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], mWorldView);
LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(mWorldView[3], Normal));
}
if (lcBoundingBoxIntersectsVolume(Min, Max, LocalPlanes))
{
2024-05-26 22:01:34 +02:00
ObjectBoxTest.Objects.emplace_back(const_cast<lcCamera*>(this));
2014-11-29 03:55:58 +01:00
return;
}
2014-11-24 01:43:13 +01:00
Min = lcVector3(-LC_CAMERA_TARGET_EDGE, -LC_CAMERA_TARGET_EDGE, -LC_CAMERA_TARGET_EDGE);
Max = lcVector3(LC_CAMERA_TARGET_EDGE, LC_CAMERA_TARGET_EDGE, LC_CAMERA_TARGET_EDGE);
lcMatrix44 WorldView = mWorldView;
WorldView.SetTranslation(lcMul30(-mTargetPosition, WorldView));
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
{
2021-11-15 03:34:24 +01:00
const lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], WorldView);
LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(WorldView[3], Normal));
}
if (lcBoundingBoxIntersectsVolume(Min, Max, LocalPlanes))
{
2024-05-26 22:01:34 +02:00
ObjectBoxTest.Objects.emplace_back(const_cast<lcCamera*>(this));
2014-11-29 03:55:58 +01:00
return;
}
2021-11-15 03:34:24 +01:00
const lcMatrix44 ViewWorld = lcMatrix44AffineInverse(mWorldView);
const lcVector3 UpVectorPosition = lcMul31(lcVector3(0, 25, 0), ViewWorld);
WorldView = mWorldView;
WorldView.SetTranslation(lcMul30(-UpVectorPosition, WorldView));
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
{
2021-11-15 03:34:24 +01:00
const lcVector3 Normal = lcMul30(ObjectBoxTest.Planes[PlaneIdx], WorldView);
LocalPlanes[PlaneIdx] = lcVector4(Normal, ObjectBoxTest.Planes[PlaneIdx][3] - lcDot3(WorldView[3], Normal));
2012-08-23 20:47:37 +02:00
}
if (lcBoundingBoxIntersectsVolume(Min, Max, LocalPlanes))
{
2024-05-26 22:01:34 +02:00
ObjectBoxTest.Objects.emplace_back(const_cast<lcCamera*>(this));
2014-11-29 03:55:58 +01:00
return;
}
2012-08-23 20:47:37 +02:00
}
2014-08-31 02:53:12 +02:00
void lcCamera::InsertTime(lcStep Start, lcStep Time)
{
2023-12-28 20:32:25 +01:00
mPosition.InsertTime(Start, Time);
mTargetPosition.InsertTime(Start, Time);
mUpVector.InsertTime(Start, Time);
2014-08-31 02:53:12 +02:00
}
void lcCamera::RemoveTime(lcStep Start, lcStep Time)
{
2023-12-28 20:32:25 +01:00
mPosition.RemoveTime(Start, Time);
mTargetPosition.RemoveTime(Start, Time);
mUpVector.RemoveTime(Start, Time);
2014-08-31 02:53:12 +02:00
}
void lcCamera::ZoomExtents(float AspectRatio, const lcVector3& Center, const std::vector<lcVector3>& Points, lcStep Step, bool AddKey)
2012-08-20 06:05:56 +02:00
{
2023-12-28 20:32:25 +01:00
lcVector3 Position, TargetPosition;
if (IsOrtho())
{
float MinX = FLT_MAX, MaxX = -FLT_MAX, MinY = FLT_MAX, MaxY = -FLT_MAX;
for (lcVector3 Point : Points)
{
Point = lcMul30(Point, mWorldView);
MinX = lcMin(MinX, Point.x);
MinY = lcMin(MinY, Point.y);
MaxX = lcMax(MaxX, Point.x);
MaxY = lcMax(MaxY, Point.y);
}
2021-11-15 03:34:24 +01:00
const lcVector3 ViewCenter = lcMul30(Center, mWorldView);
2021-01-04 00:01:28 +01:00
float Width = qMax(fabsf(MaxX - ViewCenter.x), fabsf(ViewCenter.x - MinX)) * 2;
float Height = qMax(fabsf(MaxY - ViewCenter.y), fabsf(ViewCenter.y - MinY)) * 2;
2012-08-20 06:05:56 +02:00
if (Width > Height * AspectRatio)
Height = Width / AspectRatio;
2012-08-20 06:05:56 +02:00
2021-11-15 03:34:24 +01:00
const float f = Height / (m_fovy * (LC_PI / 180.0f));
2021-11-15 03:34:24 +01:00
const lcVector3 FrontVector(mTargetPosition - mPosition);
2023-12-28 20:32:25 +01:00
Position = Center - lcNormalize(FrontVector) * f;
TargetPosition = Center;
}
else
{
2023-12-28 20:32:25 +01:00
const lcVector3 CenterPosition(mPosition + Center - mTargetPosition);
2021-11-15 03:34:24 +01:00
const lcMatrix44 ProjectionMatrix = lcMatrix44Perspective(m_fovy, AspectRatio, m_zNear, m_zFar);
2023-12-28 20:32:25 +01:00
std::tie(Position, std::ignore) = lcZoomExtents(CenterPosition, mWorldView, ProjectionMatrix, Points.data(), Points.size());
TargetPosition = Center;
}
2012-08-20 06:05:56 +02:00
if (IsSimple())
2014-07-06 08:04:09 +02:00
AddKey = false;
2023-12-28 20:32:25 +01:00
mPosition.ChangeKey(Position, Step, AddKey);
mTargetPosition.ChangeKey(TargetPosition, Step, AddKey);
2012-08-20 06:05:56 +02:00
2014-07-06 08:04:09 +02:00
UpdatePosition(Step);
2012-08-20 06:05:56 +02:00
}
void lcCamera::ZoomRegion(float AspectRatio, const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3* Corners, lcStep Step, bool AddKey)
{
2023-12-28 20:32:25 +01:00
lcVector3 NewPosition;
if (IsOrtho())
{
float MinX = FLT_MAX, MaxX = -FLT_MAX, MinY = FLT_MAX, MaxY = -FLT_MAX;
for (int PointIdx = 0; PointIdx < 2; PointIdx++)
{
2021-11-15 03:34:24 +01:00
const lcVector3 Point = lcMul30(Corners[PointIdx], mWorldView);
MinX = lcMin(MinX, Point.x);
MinY = lcMin(MinY, Point.y);
MaxX = lcMax(MaxX, Point.x);
MaxY = lcMax(MaxY, Point.y);
}
float Width = MaxX - MinX;
float Height = MaxY - MinY;
if (Width > Height * AspectRatio)
Height = Width / AspectRatio;
2021-11-15 03:34:24 +01:00
const float f = Height / (m_fovy * (LC_PI / 180.0f));
2021-11-15 03:34:24 +01:00
const lcVector3 FrontVector(mTargetPosition - mPosition);
2023-12-28 20:32:25 +01:00
NewPosition = TargetPosition - lcNormalize(FrontVector) * f;
}
else
{
2021-11-15 03:34:24 +01:00
const lcMatrix44 WorldView = lcMatrix44LookAt(Position, TargetPosition, mUpVector);
const lcMatrix44 ProjectionMatrix = lcMatrix44Perspective(m_fovy, AspectRatio, m_zNear, m_zFar);
2023-12-28 20:32:25 +01:00
std::tie(NewPosition, std::ignore) = lcZoomExtents(Position, WorldView, ProjectionMatrix, Corners, 2);
}
if (IsSimple())
2014-07-06 08:04:09 +02:00
AddKey = false;
2023-12-28 20:32:25 +01:00
mPosition.ChangeKey(NewPosition, Step, AddKey);
mTargetPosition.ChangeKey(TargetPosition, Step, AddKey);
2014-07-06 08:04:09 +02:00
UpdatePosition(Step);
}
2014-07-06 08:04:09 +02:00
void lcCamera::Zoom(float Distance, lcStep Step, bool AddKey)
2011-09-07 23:06:51 +02:00
{
2012-05-29 01:33:22 +02:00
lcVector3 FrontVector(mPosition - mTargetPosition);
FrontVector.Normalize();
FrontVector *= -5.0f * Distance;
2012-05-29 01:33:22 +02:00
2013-12-17 03:43:16 +01:00
// Don't zoom ortho in if it would cross the ortho focal plane.
2014-05-03 03:22:24 +02:00
if (IsOrtho())
2013-12-17 03:43:16 +01:00
{
if ((Distance > 0) && (lcDot(mPosition + FrontVector - mTargetPosition, mPosition - mTargetPosition) <= 0))
2013-12-17 03:43:16 +01:00
return;
}
2012-05-29 01:33:22 +02:00
if (IsSimple())
2014-07-06 08:04:09 +02:00
AddKey = false;
2023-12-28 20:32:25 +01:00
mPosition.ChangeKey(mPosition + FrontVector, Step, AddKey);
if (!IsOrtho())
mTargetPosition.ChangeKey(mTargetPosition + FrontVector, Step, AddKey);
2012-08-20 06:05:56 +02:00
2014-07-06 08:04:09 +02:00
UpdatePosition(Step);
2011-09-07 23:06:51 +02:00
}
void lcCamera::Pan(const lcVector3& Distance, lcStep Step, bool AddKey)
2011-09-07 23:06:51 +02:00
{
if (IsSimple())
2014-07-06 08:04:09 +02:00
AddKey = false;
2023-12-28 20:32:25 +01:00
mPosition.ChangeKey(mPosition + Distance, Step, AddKey);
mTargetPosition.ChangeKey(mTargetPosition + Distance, Step, AddKey);
2012-08-20 06:05:56 +02:00
2014-07-06 08:04:09 +02:00
UpdatePosition(Step);
2011-09-07 23:06:51 +02:00
}
2014-07-06 08:04:09 +02:00
void lcCamera::Orbit(float DistanceX, float DistanceY, const lcVector3& CenterPosition, lcStep Step, bool AddKey)
2011-09-07 23:06:51 +02:00
{
2012-05-29 01:33:22 +02:00
lcVector3 FrontVector(mPosition - mTargetPosition);
2023-12-28 20:32:25 +01:00
lcVector3 UpVector = mUpVector;
2012-05-29 01:33:22 +02:00
2013-01-27 02:22:37 +01:00
lcVector3 Z(lcNormalize(lcVector3(FrontVector[0], FrontVector[1], 0)));
2016-08-11 00:29:59 +02:00
if (qIsNaN(Z[0]) || qIsNaN(Z[1]))
2023-12-28 20:32:25 +01:00
Z = lcNormalize(lcVector3(UpVector[0], UpVector[1], 0));
2012-05-29 01:33:22 +02:00
2023-12-28 20:32:25 +01:00
if (UpVector[2] < 0)
2013-01-27 02:22:37 +01:00
{
Z[0] = -Z[0];
Z[1] = -Z[1];
}
2013-08-09 06:57:18 +02:00
2021-11-15 03:34:24 +01:00
const lcMatrix44 YRot(lcVector4(Z[0], Z[1], 0.0f, 0.0f), lcVector4(-Z[1], Z[0], 0.0f, 0.0f), lcVector4(0.0f, 0.0f, 1.0f, 0.0f), lcVector4(0.0f, 0.0f, 0.0f, 1.0f));
2023-12-28 20:32:25 +01:00
const lcMatrix44 Transform = lcMul(lcMul(lcMul(lcMatrix44AffineInverse(YRot), lcMatrix44RotationY(DistanceY)), YRot), lcMatrix44RotationZ(-DistanceX));
2013-12-17 03:43:16 +01:00
2023-12-28 20:32:25 +01:00
lcVector3 Position = lcMul31(mPosition - CenterPosition, Transform) + CenterPosition;
lcVector3 TargetPosition = lcMul31(mTargetPosition - CenterPosition, Transform) + CenterPosition;
UpVector = lcMul31(mUpVector, Transform);
2012-05-29 01:33:22 +02:00
if (IsSimple())
2014-07-06 08:04:09 +02:00
AddKey = false;
2023-12-28 20:32:25 +01:00
mPosition.ChangeKey(Position, Step, AddKey);
mTargetPosition.ChangeKey(TargetPosition, Step, AddKey);
mUpVector.ChangeKey(UpVector, Step, AddKey);
2012-08-20 06:05:56 +02:00
2014-07-06 08:04:09 +02:00
UpdatePosition(Step);
2011-09-07 23:06:51 +02:00
}
2014-07-06 08:04:09 +02:00
void lcCamera::Roll(float Distance, lcStep Step, bool AddKey)
2011-09-07 23:06:51 +02:00
{
2021-11-15 03:34:24 +01:00
const lcVector3 FrontVector(mPosition - mTargetPosition);
const lcMatrix44 Rotation = lcMatrix44FromAxisAngle(FrontVector, Distance);
2011-09-07 23:06:51 +02:00
2023-12-28 20:32:25 +01:00
const lcVector3 UpVector = lcMul30(mUpVector, Rotation);
2012-08-20 06:05:56 +02:00
if (IsSimple())
2014-07-06 08:04:09 +02:00
AddKey = false;
2023-12-28 20:32:25 +01:00
mUpVector.ChangeKey(UpVector, Step, AddKey);
2012-08-20 06:05:56 +02:00
2014-07-06 08:04:09 +02:00
UpdatePosition(Step);
2012-08-20 06:05:56 +02:00
}
void lcCamera::Center(const lcVector3& NewCenter, lcStep Step, bool AddKey)
2013-12-17 23:23:41 +01:00
{
const lcMatrix44 Inverse = lcMatrix44AffineInverse(mWorldView);
const lcVector3 Direction = -lcVector3(Inverse[2]);
2020-12-14 23:18:06 +01:00
// float Yaw, Pitch, Roll;
float Roll;
if (fabsf(Direction.z) < 0.9999f)
{
2020-12-14 23:18:06 +01:00
// Yaw = atan2f(Direction.y, Direction.x);
// Pitch = asinf(Direction.z);
Roll = atan2f(Inverse[0][2], Inverse[1][2]);
}
else
{
2020-12-14 23:18:06 +01:00
// Yaw = 0.0f;
// Pitch = asinf(Direction.z);
Roll = atan2f(Inverse[0][1], Inverse[1][1]);
}
2023-12-28 20:32:25 +01:00
lcVector3 FrontVector(mPosition - NewCenter);
2021-11-15 03:34:24 +01:00
const lcMatrix44 Rotation = lcMatrix44FromAxisAngle(FrontVector, Roll);
lcVector3 UpVector(0, 0, 1), SideVector;
FrontVector.Normalize();
if (fabsf(lcDot(UpVector, FrontVector)) > 0.99f)
SideVector = lcVector3(-1, 0, 0);
else
SideVector = lcCross(FrontVector, UpVector);
UpVector = lcCross(SideVector, FrontVector);
UpVector.Normalize();
2023-12-28 20:32:25 +01:00
UpVector = lcMul30(UpVector, Rotation);
2013-12-17 23:23:41 +01:00
if (IsSimple())
2014-07-06 08:04:09 +02:00
AddKey = false;
2023-12-28 20:32:25 +01:00
mTargetPosition.ChangeKey(NewCenter, Step, AddKey);
mUpVector.ChangeKey(UpVector, Step, AddKey);
2013-12-17 23:23:41 +01:00
2014-07-06 08:04:09 +02:00
UpdatePosition(Step);
2013-12-17 23:23:41 +01:00
}
2014-11-08 02:05:17 +01:00
void lcCamera::SetViewpoint(lcViewpoint Viewpoint)
2012-08-20 06:05:56 +02:00
{
2023-12-28 20:32:25 +01:00
const lcVector3 Positions[] =
2012-08-20 06:05:56 +02:00
{
2020-12-13 01:58:40 +01:00
lcVector3( 0.0f, -1250.0f, 0.0f), // lcViewpoint::Front
lcVector3( 0.0f, 1250.0f, 0.0f), // lcViewpoint::Back
lcVector3( 0.0f, 0.0f, 1250.0f), // lcViewpoint::Top
lcVector3( 0.0f, 0.0f, -1250.0f), // lcViewpoint::Bottom
lcVector3( 1250.0f, 0.0f, 0.0f), // lcViewpoint::Left
lcVector3(-1250.0f, 0.0f, 0.0f), // lcViewpoint::Right
lcVector3( 375.0f, -375.0f, 187.5f) // lcViewpoint::Home
2012-08-20 06:05:56 +02:00
};
2023-12-28 20:32:25 +01:00
const lcVector3 Ups[] =
2013-01-27 02:36:11 +01:00
{
2017-12-10 01:35:00 +01:00
lcVector3(0.0f, 0.0f, 1.0f),
lcVector3(0.0f, 0.0f, 1.0f),
lcVector3(0.0f, 1.0f, 0.0f),
lcVector3(0.0f,-1.0f, 0.0f),
lcVector3(0.0f, 0.0f, 1.0f),
lcVector3(0.0f, 0.0f, 1.0f),
lcVector3(0.2357f, -0.2357f, 0.94281f)
2013-01-27 02:36:11 +01:00
};
2012-08-20 06:05:56 +02:00
2023-12-28 20:32:25 +01:00
mPosition.ChangeKey(Positions[static_cast<int>(Viewpoint)], 1, false);
mTargetPosition.ChangeKey(lcVector3(0, 0, 0), 1, false);
mUpVector.ChangeKey(Ups[static_cast<int>(Viewpoint)], 1, false);
2012-08-20 06:05:56 +02:00
2014-11-08 02:05:17 +01:00
UpdatePosition(1);
2011-09-07 23:06:51 +02:00
}
2018-08-20 05:27:58 +02:00
void lcCamera::SetViewpoint(const lcVector3& Position)
{
lcVector3 UpVector(0, 0, 1), FrontVector(Position), SideVector;
FrontVector.Normalize();
if (fabsf(lcDot(UpVector, FrontVector)) > 0.99f)
SideVector = lcVector3(-1, 0, 0);
2018-08-20 05:27:58 +02:00
else
SideVector = lcCross(FrontVector, UpVector);
UpVector = lcCross(SideVector, FrontVector);
UpVector.Normalize();
2023-12-28 20:32:25 +01:00
mPosition.ChangeKey(Position, 1, false);
mTargetPosition.ChangeKey(lcVector3(0, 0, 0), 1, false);
mUpVector.ChangeKey(UpVector, 1, false);
2018-08-20 05:27:58 +02:00
UpdatePosition(1);
}
2023-12-28 20:32:25 +01:00
void lcCamera::SetViewpoint(const lcVector3& Position, const lcVector3& TargetPosition, const lcVector3& Up)
2020-12-13 00:03:06 +01:00
{
2023-12-28 20:32:25 +01:00
const lcVector3 Direction = TargetPosition - Position;
2020-12-13 00:03:06 +01:00
lcVector3 UpVector, SideVector;
SideVector = lcCross(Direction, Up);
UpVector = lcCross(SideVector, Direction);
UpVector.Normalize();
2023-12-28 20:32:25 +01:00
mPosition.ChangeKey(Position, 1, false);
mTargetPosition.ChangeKey(TargetPosition, 1, false);
mUpVector.ChangeKey(UpVector, 1, false);
2020-12-13 00:03:06 +01:00
UpdatePosition(1);
}
2019-08-16 02:41:32 +02:00
void lcCamera::SetAngles(float Latitude, float Longitude, float Distance)
{
2023-12-28 20:32:25 +01:00
lcVector3 Position = lcVector3(0, -1, 0);
lcVector3 TargetPosition = lcVector3(0, 0, 0);
lcVector3 UpVector = lcVector3(0, 0, 1);
2021-11-15 03:34:24 +01:00
const lcMatrix33 LongitudeMatrix = lcMatrix33RotationZ(LC_DTOR * Longitude);
2023-12-28 20:32:25 +01:00
Position = lcMul(Position, LongitudeMatrix);
2021-11-15 03:34:24 +01:00
const lcVector3 SideVector = lcMul(lcVector3(-1, 0, 0), LongitudeMatrix);
const lcMatrix33 LatitudeMatrix = lcMatrix33FromAxisAngle(SideVector, LC_DTOR * Latitude);
2023-12-28 20:32:25 +01:00
Position = lcMul(Position, LatitudeMatrix) * Distance;
UpVector = lcMul(UpVector, LatitudeMatrix);
2023-12-28 20:32:25 +01:00
mPosition.ChangeKey(Position, 1, false);
mTargetPosition.ChangeKey(TargetPosition, 1, false);
mUpVector.ChangeKey(UpVector, 1, false);
UpdatePosition(1);
}
2019-08-16 02:33:37 +02:00
void lcCamera::GetAngles(float& Latitude, float& Longitude, float& Distance) const
{
lcVector3 FrontVector(mPosition - mTargetPosition);
2021-11-15 03:34:24 +01:00
const lcVector3 X(1, 0, 0);
const lcVector3 Y(0, 1, 0);
const lcVector3 Z(0, 0, 1);
2019-08-16 02:33:37 +02:00
FrontVector.Normalize();
Latitude = acos(lcDot(-FrontVector, Z)) * LC_RTOD - 90.0f;
2021-11-15 03:34:24 +01:00
const lcVector3 CameraXY = -lcNormalize(lcVector3(FrontVector.x, FrontVector.y, 0.0f));
2019-08-16 02:33:37 +02:00
Longitude = acos(lcDot(CameraXY, Y)) * LC_RTOD;
if (lcDot(CameraXY, X) > 0)
Longitude = -Longitude;
Distance = lcLength(mPosition);
}