leocad/common/camera.cpp

818 lines
20 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>
#include "opengl.h"
#include "globals.h"
#include "lc_file.h"
2011-09-07 23:06:51 +02:00
#include "camera.h"
2012-08-20 06:05:56 +02:00
#include "view.h"
2011-09-07 23:06:51 +02:00
#include "tr.h"
#define LC_CAMERA_SAVE_VERSION 6 // LeoCAD 0.73
static LC_OBJECT_KEY_INFO camera_key_info[LC_CK_COUNT] =
{
2012-08-23 20:47:37 +02:00
{ "Camera Position", 3, LC_CK_EYE },
{ "Camera Target", 3, LC_CK_TARGET },
{ "Camera Up Vector", 3, LC_CK_UP }
2011-09-07 23:06:51 +02:00
};
// =============================================================================
// CameraTarget class
2012-08-23 20:47:37 +02:00
CameraTarget::CameraTarget(Camera *pParent)
: Object(LC_OBJECT_CAMERA_TARGET)
2011-09-07 23:06:51 +02:00
{
2012-08-23 20:47:37 +02:00
m_pParent = pParent;
/*
strcpy (m_strName, pParent->GetName ());
m_strName[LC_OBJECT_NAME_LEN-8] = '\0';
strcat (m_strName, ".Target");
*/
2011-09-07 23:06:51 +02:00
}
2012-08-23 20:47:37 +02:00
CameraTarget::~CameraTarget()
2011-09-07 23:06:51 +02:00
{
}
2012-08-17 01:50:40 +02:00
void CameraTarget::MinIntersectDist(lcClickLine* ClickLine)
2011-09-07 23:06:51 +02:00
{
2012-08-17 01:50:40 +02:00
lcVector3 Min = lcVector3(-0.2f, -0.2f, -0.2f);
lcVector3 Max = lcVector3(0.2f, 0.2f, 0.2f);
2011-09-07 23:06:51 +02:00
2012-08-17 01:50:40 +02:00
lcMatrix44 WorldView = ((Camera*)m_pParent)->mWorldView;
WorldView.SetTranslation(lcMul30(-((Camera*)m_pParent)->mTargetPosition, WorldView));
lcVector3 Start = lcMul31(ClickLine->Start, WorldView);
lcVector3 End = lcMul31(ClickLine->End, WorldView);
float Dist;
if (lcBoundingBoxRayMinIntersectDistance(Min, Max, Start, End, &Dist, NULL) && (Dist < ClickLine->MinDist))
{
ClickLine->Closest = this;
ClickLine->MinDist = Dist;
}
2011-09-07 23:06:51 +02:00
}
2012-08-23 20:47:37 +02:00
bool CameraTarget::IntersectsVolume(const lcVector4 Planes[6]) const
{
lcVector3 Min(-0.2f, -0.2f, -0.2f);
lcVector3 Max(0.2f, 0.2f, 0.2f);
// Transform the planes to local space.
lcVector4 LocalPlanes[6];
lcMatrix44 WorldView = m_pParent->mWorldView;
WorldView.SetTranslation(lcMul30(-m_pParent->mTargetPosition, WorldView));
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
{
lcVector3 Normal = lcMul30(lcVector3(Planes[PlaneIdx][0], Planes[PlaneIdx][1], Planes[PlaneIdx][2]), WorldView);
LocalPlanes[PlaneIdx] = lcVector4(Normal, Planes[PlaneIdx][3] - lcDot3(WorldView[3], Normal));
}
return lcBoundingBoxIntersectsVolume(Min, Max, LocalPlanes);
}
2012-08-17 01:50:40 +02:00
void CameraTarget::Select(bool bSelecting, bool bFocus, bool bMultiple)
2011-09-07 23:06:51 +02:00
{
2012-08-17 01:50:40 +02:00
m_pParent->SelectTarget(bSelecting, bFocus, bMultiple);
2011-09-07 23:06:51 +02:00
}
const char* CameraTarget::GetName() const
{
return m_pParent->GetName();
}
/////////////////////////////////////////////////////////////////////////////
// Camera construction/destruction
2012-08-20 06:05:56 +02:00
Camera::Camera(bool Simple)
: Object(LC_OBJECT_CAMERA)
2011-09-07 23:06:51 +02:00
{
2012-08-20 06:05:56 +02:00
Initialize();
if (Simple)
m_nState |= LC_CAMERA_SIMPLE;
2012-08-23 20:47:37 +02:00
else
{
mPosition = lcVector3(-10.0f, -10.0f, 5.0f);
mTargetPosition = lcVector3(0.0f, 0.0f, 0.0f);
mUpVector = lcVector3(-0.2357f, -0.2357f, 0.94281f);
ChangeKey(1, false, true, mPosition, LC_CK_EYE);
ChangeKey(1, false, true, mTargetPosition, LC_CK_TARGET);
ChangeKey(1, false, true, mUpVector, LC_CK_UP);
ChangeKey(1, true, true, mPosition, LC_CK_EYE);
ChangeKey(1, true, true, mTargetPosition, LC_CK_TARGET);
ChangeKey(1, true, true, mUpVector, LC_CK_UP);
UpdatePosition(1, false);
}
2011-09-07 23:06:51 +02:00
}
2012-08-22 03:13:32 +02:00
Camera::Camera(float ex, float ey, float ez, float tx, float ty, float tz)
: Object(LC_OBJECT_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();
float eye[3] = { ex, ey, ez }, target[3] = { tx, ty, tz };
ChangeKey(1, false, true, eye, LC_CK_EYE);
ChangeKey(1, false, true, target, LC_CK_TARGET);
ChangeKey(1, false, true, UpVector, LC_CK_UP);
ChangeKey(1, true, true, eye, LC_CK_EYE);
ChangeKey(1, true, true, target, LC_CK_TARGET);
ChangeKey(1, true, true, UpVector, LC_CK_UP);
UpdatePosition(1, false);
2011-09-07 23:06:51 +02:00
}
Camera::~Camera()
{
2012-08-23 20:47:37 +02:00
delete m_pTarget;
2011-09-07 23:06:51 +02:00
}
void Camera::Initialize()
{
2012-08-23 20:47:37 +02:00
m_fovy = 30.0f;
m_zNear = 1.0f;
m_zFar = 500.0f;
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
m_nState = 0;
m_nType = LC_CAMERA_USER;
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
m_pTR = NULL;
memset(m_strName, 0, sizeof(m_strName));
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
float *values[] = { mPosition, mTargetPosition, mUpVector };
RegisterKeys(values, camera_key_info, LC_CK_COUNT);
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
m_pTarget = new CameraTarget(this);
2011-09-07 23:06:51 +02:00
}
2012-08-22 03:13:32 +02:00
void Camera::CreateName(const PtrArray<Camera>& Cameras)
{
int i, max = 0;
const char* Prefix = "Camera ";
for (int CameraIdx = 0; CameraIdx < Cameras.GetSize(); CameraIdx++)
if (strncmp(Cameras[CameraIdx]->m_strName, Prefix, strlen(Prefix)) == 0)
if (sscanf(Cameras[CameraIdx]->m_strName + strlen(Prefix), " %d", &i) == 1)
2013-01-06 20:24:25 +01:00
if (i > max)
2012-08-22 03:13:32 +02:00
max = i;
sprintf(m_strName, "%s %d", Prefix, max+1);
}
2011-09-07 23:06:51 +02:00
/////////////////////////////////////////////////////////////////////////////
// Camera save/load
2012-03-23 00:44:56 +01:00
bool Camera::FileLoad(lcFile& file)
2011-09-07 23:06:51 +02:00
{
2012-08-23 20:47:37 +02:00
lcuint8 version, ch;
version = file.ReadU8();
if (version > LC_CAMERA_SAVE_VERSION)
return false;
if (version > 5)
if (!Object::FileLoad(file))
return false;
if (version == 4)
{
file.ReadBuffer(m_strName, 80);
m_strName[80] = 0;
}
else
{
ch = file.ReadU8();
if (ch == 0xFF)
return false; // don't read CString
file.ReadBuffer(m_strName, ch);
m_strName[ch] = 0;
}
if (version < 3)
{
double d[3];
float f[3];
file.ReadDoubles(d, 3);
f[0] = (float)d[0];
f[1] = (float)d[1];
f[2] = (float)d[2];
ChangeKey(1, false, true, f, LC_CK_EYE);
ChangeKey(1, true, true, f, LC_CK_EYE);
file.ReadDoubles(d, 3);
f[0] = (float)d[0];
f[1] = (float)d[1];
f[2] = (float)d[2];
ChangeKey(1, false, true, f, LC_CK_TARGET);
ChangeKey(1, true, true, f, LC_CK_TARGET);
file.ReadDoubles(d, 3);
f[0] = (float)d[0];
f[1] = (float)d[1];
f[2] = (float)d[2];
ChangeKey(1, false, true, f, LC_CK_UP);
ChangeKey(1, true, true, f, LC_CK_UP);
}
if (version == 3)
{
ch = file.ReadU8();
while (ch--)
{
lcuint8 step;
double eye[3], target[3], up[3];
float f[3];
file.ReadDoubles(eye, 3);
file.ReadDoubles(target, 3);
file.ReadDoubles(up, 3);
file.ReadU8(&step, 1);
if (up[0] == 0 && up[1] == 0 && up[2] == 0)
up[2] = 1;
f[0] = (float)eye[0];
f[1] = (float)eye[1];
f[2] = (float)eye[2];
ChangeKey(step, false, true, f, LC_CK_EYE);
ChangeKey(step, true, true, f, LC_CK_EYE);
f[0] = (float)target[0];
f[1] = (float)target[1];
f[2] = (float)target[2];
ChangeKey(step, false, true, f, LC_CK_TARGET);
ChangeKey(step, true, true, f, LC_CK_TARGET);
f[0] = (float)up[0];
f[1] = (float)up[1];
f[2] = (float)up[2];
ChangeKey(step, false, true, f, LC_CK_UP);
ChangeKey(step, true, true, f, LC_CK_UP);
file.ReadS32(); // snapshot
file.ReadS32(); // cam
}
}
if (version < 4)
{
m_fovy = (float)file.ReadDouble();
m_zFar = (float)file.ReadDouble();
m_zNear= (float)file.ReadDouble();
}
else
{
lcint32 n;
if (version < 6)
{
lcuint16 time;
float param[4];
lcuint8 type;
n = file.ReadS32();
while (n--)
{
file.ReadU16(&time, 1);
file.ReadFloats(param, 3);
file.ReadU8(&type, 1);
ChangeKey(time, false, true, param, type);
}
n = file.ReadS32();
while (n--)
{
file.ReadU16(&time, 1);
file.ReadFloats(param, 3);
file.ReadU8(&type, 1);
ChangeKey(time, true, true, param, type);
}
}
file.ReadFloats(&m_fovy, 1);
file.ReadFloats(&m_zFar, 1);
file.ReadFloats(&m_zNear, 1);
if (version < 5)
{
n = file.ReadS32();
if (n != 0)
m_nState |= LC_CAMERA_HIDDEN;
}
else
{
m_nState = file.ReadU8();
m_nType = file.ReadU8();
}
}
if ((version > 1) && (version < 4))
{
lcuint32 show;
lcint32 user;
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);
2012-08-23 20:47:37 +02:00
if (show == 0)
m_nState |= LC_CAMERA_HIDDEN;
}
return true;
2011-09-07 23:06:51 +02:00
}
2012-03-23 00:44:56 +01:00
void Camera::FileSave(lcFile& file) const
2011-09-07 23:06:51 +02:00
{
2012-08-23 20:47:37 +02:00
file.WriteU8(LC_CAMERA_SAVE_VERSION);
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
Object::FileSave(file);
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
lcuint8 ch = (unsigned char)strlen(m_strName);
file.WriteU8(ch);
file.WriteBuffer(m_strName, ch);
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
file.WriteFloat(m_fovy);
file.WriteFloat(m_zFar);
file.WriteFloat(m_zNear);
// version 5
file.WriteU8(m_nState);
file.WriteU8(m_nType);
2011-09-07 23:06:51 +02:00
}
/////////////////////////////////////////////////////////////////////////////
// Camera operations
2012-05-29 01:33:22 +02:00
void Camera::Move(unsigned short nTime, bool bAnimation, bool bAddKey, float dx, float dy, float dz)
2011-09-07 23:06:51 +02:00
{
2012-05-29 01:33:22 +02:00
lcVector3 Move(dx, dy, dz);
2011-09-07 23:06:51 +02:00
2012-08-20 06:05:56 +02:00
if (IsEyeSelected())
2012-05-29 01:33:22 +02:00
{
mPosition += Move;
2011-09-07 23:06:51 +02:00
2012-08-20 06:05:56 +02:00
if (!IsSimple())
2012-05-29 01:33:22 +02:00
ChangeKey(nTime, bAnimation, bAddKey, mPosition, LC_CK_EYE);
2012-08-20 06:05:56 +02:00
}
2011-09-07 23:06:51 +02:00
2012-08-20 06:05:56 +02:00
if (IsTargetSelected())
{
mTargetPosition += Move;
2011-09-07 23:06:51 +02:00
2012-08-20 06:05:56 +02:00
if (!IsSimple())
2012-05-29 01:33:22 +02:00
ChangeKey(nTime, bAnimation, bAddKey, mTargetPosition, LC_CK_TARGET);
2012-08-20 06:05:56 +02:00
}
2012-05-29 01:33:22 +02:00
2012-08-20 06:05:56 +02:00
// Fix the up vector
lcVector3 FrontVector(mTargetPosition - mPosition);
lcVector3 SideVector = lcCross(FrontVector, mUpVector);
mUpVector = lcNormalize(lcCross(SideVector, FrontVector));
2012-05-29 01:33:22 +02:00
2012-08-20 06:05:56 +02:00
if (!IsSimple())
2012-05-29 01:33:22 +02:00
ChangeKey(nTime, bAnimation, bAddKey, mUpVector, LC_CK_UP);
2011-09-07 23:06:51 +02:00
}
2012-08-23 20:47:37 +02:00
void Camera::Select(bool bSelecting, bool bFocus, bool bMultiple)
{
if (bSelecting == true)
{
if (bFocus == true)
{
m_nState |= (LC_CAMERA_FOCUSED|LC_CAMERA_SELECTED);
m_pTarget->Select(false, true, bMultiple);
}
else
m_nState |= LC_CAMERA_SELECTED;
if (bMultiple == false)
m_pTarget->Select(false, false, bMultiple);
}
else
{
if (bFocus == true)
m_nState &= ~(LC_CAMERA_FOCUSED);
else
m_nState &= ~(LC_CAMERA_SELECTED|LC_CAMERA_FOCUSED);
}
2011-09-07 23:06:51 +02:00
}
2012-08-23 20:47:37 +02:00
void Camera::SelectTarget(bool bSelecting, bool bFocus, bool bMultiple)
{
// FIXME: the target should handle this
if (bSelecting == true)
{
if (bFocus == true)
{
m_nState |= (LC_CAMERA_TARGET_FOCUSED|LC_CAMERA_TARGET_SELECTED);
Select(false, true, bMultiple);
}
else
m_nState |= LC_CAMERA_TARGET_SELECTED;
if (bMultiple == false)
Select(false, false, bMultiple);
}
else
{
if (bFocus == true)
m_nState &= ~(LC_CAMERA_TARGET_FOCUSED);
else
m_nState &= ~(LC_CAMERA_TARGET_SELECTED|LC_CAMERA_TARGET_FOCUSED);
}
2011-09-07 23:06:51 +02:00
}
void Camera::UpdatePosition(unsigned short nTime, bool bAnimation)
{
2012-08-20 06:05:56 +02:00
if (!IsSimple())
CalculateKeys(nTime, bAnimation);
2012-05-29 01:33:22 +02:00
lcVector3 FrontVector(mPosition - mTargetPosition);
lcVector3 SideVector = lcCross(FrontVector, mUpVector);
mUpVector = lcNormalize(lcCross(SideVector, FrontVector));
mWorldView = lcMatrix44LookAt(mPosition, mTargetPosition, mUpVector);
2011-09-07 23:06:51 +02:00
}
2012-08-20 06:05:56 +02:00
void Camera::CopyPosition(const Camera* 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;
}
2012-08-23 20:47:37 +02:00
void Camera::Render(float fLineWidth)
2011-09-07 23:06:51 +02:00
{
2012-08-23 20:47:37 +02:00
lcMatrix44 ViewWorld = lcMatrix44AffineInverse(mWorldView);
2012-05-29 01:33:22 +02:00
2012-08-23 20:47:37 +02:00
// Draw camera.
2012-05-29 01:33:22 +02:00
glPushMatrix();
2012-08-23 20:47:37 +02:00
glMultMatrixf(ViewWorld);
2012-05-29 01:33:22 +02:00
glEnableClientState(GL_VERTEX_ARRAY);
float verts[34][3] =
{
{ 0.3f, 0.3f, 0.3f }, { -0.3f, 0.3f, 0.3f },
{ -0.3f, 0.3f, 0.3f }, { -0.3f, -0.3f, 0.3f },
{ -0.3f, -0.3f, 0.3f }, { 0.3f, -0.3f, 0.3f },
{ 0.3f, -0.3f, 0.3f }, { 0.3f, 0.3f, 0.3f },
{ 0.3f, 0.3f, -0.3f }, { -0.3f, 0.3f, -0.3f },
{ -0.3f, 0.3f, -0.3f }, { -0.3f, -0.3f, -0.3f },
{ -0.3f, -0.3f, -0.3f }, { 0.3f, -0.3f, -0.3f },
{ 0.3f, -0.3f, -0.3f }, { 0.3f, 0.3f, -0.3f },
{ 0.3f, 0.3f, 0.3f }, { 0.3f, 0.3f, -0.3f },
{ -0.3f, 0.3f, 0.3f }, { -0.3f, 0.3f, -0.3f },
{ -0.3f, -0.3f, 0.3f }, { -0.3f, -0.3f, -0.3f },
{ 0.3f, -0.3f, 0.3f }, { 0.3f, -0.3f, -0.3f },
{ -0.3f, -0.3f, -0.6f }, { -0.3f, 0.3f, -0.6f },
{ 0.0f, 0.0f, -0.3f }, { -0.3f, -0.3f, -0.6f },
{ 0.3f, -0.3f, -0.6f }, { 0.0f, 0.0f, -0.3f },
{ 0.3f, 0.3f, -0.6f }, { 0.3f, -0.3f, -0.6f },
{ 0.3f, 0.3f, -0.6f }, { -0.3f, 0.3f, -0.6f }
};
2012-08-23 20:47:37 +02:00
if (IsEyeSelected())
{
glLineWidth(2.0f);
if (m_nState & LC_CAMERA_FOCUSED)
lcSetColorFocused();
else
lcSetColorSelected();
}
else
{
glLineWidth(1.0f);
lcSetColorCamera();
}
glVertexPointer(3, GL_FLOAT, 0, verts);
2012-05-29 01:33:22 +02:00
glDrawArrays(GL_LINES, 0, 24);
glDrawArrays(GL_LINE_STRIP, 24, 10);
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
glPopMatrix();
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
// Draw target.
glPushMatrix();
lcMatrix44 TargetMat = ViewWorld;
TargetMat.SetTranslation(mTargetPosition);
glMultMatrixf(TargetMat);
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
if (IsTargetSelected())
{
glLineWidth(2.0f);
if (m_nState & LC_CAMERA_TARGET_FOCUSED)
lcSetColorFocused();
else
lcSetColorSelected();
}
else
{
glLineWidth(1.0f);
lcSetColorCamera();
}
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
glEnableClientState(GL_VERTEX_ARRAY);
float box[24][3] =
2013-01-06 20:24:25 +01:00
{
2012-08-23 20:47:37 +02:00
{ 0.2f, 0.2f, 0.2f }, { -0.2f, 0.2f, 0.2f },
{ -0.2f, 0.2f, 0.2f }, { -0.2f, -0.2f, 0.2f },
{ -0.2f, -0.2f, 0.2f }, { 0.2f, -0.2f, 0.2f },
{ 0.2f, -0.2f, 0.2f }, { 0.2f, 0.2f, 0.2f },
{ 0.2f, 0.2f, -0.2f }, { -0.2f, 0.2f, -0.2f },
{ -0.2f, 0.2f, -0.2f }, { -0.2f, -0.2f, -0.2f },
{ -0.2f, -0.2f, -0.2f }, { 0.2f, -0.2f, -0.2f },
{ 0.2f, -0.2f, -0.2f }, { 0.2f, 0.2f, -0.2f },
{ 0.2f, 0.2f, 0.2f }, { 0.2f, 0.2f, -0.2f },
{ -0.2f, 0.2f, 0.2f }, { -0.2f, 0.2f, -0.2f },
{ -0.2f, -0.2f, 0.2f }, { -0.2f, -0.2f, -0.2f },
{ 0.2f, -0.2f, 0.2f }, { 0.2f, -0.2f, -0.2f }
};
glVertexPointer(3, GL_FLOAT, 0, box);
glDrawArrays(GL_LINES, 0, 24);
glPopMatrix();
lcVector3 Line[2] =
{
mPosition,
mTargetPosition
};
glVertexPointer(3, GL_FLOAT, 0, Line);
glColor4f(0.5f, 0.8f, 0.5f, 1.0f);
glLineWidth(1.0f);
glDrawArrays(GL_LINES, 0, 2);
if (IsSelected())
2012-05-29 01:33:22 +02:00
{
2012-08-23 20:47:37 +02:00
glPushMatrix();
glMultMatrixf(ViewWorld);
2012-05-29 01:33:22 +02:00
2012-08-23 20:47:37 +02:00
float Dist = lcLength(mTargetPosition - mPosition);
lcMatrix44 Projection = lcMatrix44Perspective(m_fovy, 1.33f, 0.01f, Dist);
Projection = lcMatrix44Inverse(Projection);
glMultMatrixf(Projection);
2012-05-29 01:33:22 +02:00
2012-08-23 20:47:37 +02:00
// Draw the view frustum.
float verts[16][3] =
2012-05-29 01:33:22 +02:00
{
2012-08-23 20:47:37 +02:00
{ 1, 1, 1 }, { -1, 1, 1 },
{ -1, 1, 1 }, { -1, -1, 1 },
{ -1, -1, 1 }, { 1, -1, 1 },
{ 1, -1, 1 }, { 1, 1, 1 },
{ 1, 1, -1 }, { 1, 1, 1 },
{ -1, 1, -1 }, { -1, 1, 1 },
{ -1, -1, -1 }, { -1, -1, 1 },
{ 1, -1, -1 }, { 1, -1, 1 },
2012-05-29 01:33:22 +02:00
};
2012-08-23 20:47:37 +02:00
glVertexPointer(3, GL_FLOAT, 0, verts);
glDrawArrays(GL_LINES, 0, 16);
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
glPopMatrix();
2011-09-07 23:06:51 +02:00
}
2012-08-23 20:47:37 +02:00
glDisableClientState(GL_VERTEX_ARRAY);
2011-09-07 23:06:51 +02:00
}
2012-08-17 01:50:40 +02:00
void Camera::MinIntersectDist(lcClickLine* ClickLine)
2011-09-07 23:06:51 +02:00
{
2012-08-17 01:50:40 +02:00
lcVector3 Min = lcVector3(-0.3f, -0.3f, -0.3f);
lcVector3 Max = lcVector3(0.3f, 0.3f, 0.3f);
2011-09-07 23:06:51 +02:00
2012-08-17 01:50:40 +02:00
lcVector3 Start = lcMul31(ClickLine->Start, mWorldView);
lcVector3 End = lcMul31(ClickLine->End, mWorldView);
2011-09-07 23:06:51 +02:00
2012-08-17 01:50:40 +02:00
float Dist;
if (lcBoundingBoxRayMinIntersectDistance(Min, Max, Start, End, &Dist, NULL) && (Dist < ClickLine->MinDist))
{
ClickLine->Closest = this;
ClickLine->MinDist = Dist;
}
2011-09-07 23:06:51 +02:00
2012-08-17 01:50:40 +02:00
m_pTarget->MinIntersectDist(ClickLine);
2011-09-07 23:06:51 +02:00
}
2012-08-23 20:47:37 +02:00
bool Camera::IntersectsVolume(const lcVector4 Planes[6]) const
{
lcVector3 Min(-0.3f, -0.3f, -0.3f);
lcVector3 Max(0.3f, 0.3f, 0.3f);
// Transform the planes to local space.
lcVector4 LocalPlanes[6];
for (int PlaneIdx = 0; PlaneIdx < 6; PlaneIdx++)
{
lcVector3 Normal = lcMul30(Planes[PlaneIdx], mWorldView);
LocalPlanes[PlaneIdx] = lcVector4(Normal, Planes[PlaneIdx][3] - lcDot3(mWorldView[3], Normal));
}
return lcBoundingBoxIntersectsVolume(Min, Max, LocalPlanes);
}
2011-09-07 23:06:51 +02:00
void Camera::LoadProjection(float fAspect)
{
2012-08-23 20:47:37 +02:00
if (m_pTR != NULL)
m_pTR->BeginTile();
else
{
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(lcMatrix44Perspective(m_fovy, fAspect, m_zNear, m_zFar));
2011-09-07 23:06:51 +02:00
/*
ymax = 10;//(m_zFar-m_zNear)*tan(DTOR*m_fovy)/3;
ymin = -ymax;
xmin = ymin * fAspect;
xmax = ymax * fAspect;
znear = -60;
zfar = 60;
glOrtho(xmin, xmax, ymin, ymax, znear, zfar);
*/
2012-08-23 20:47:37 +02:00
}
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(mWorldView);
2011-09-07 23:06:51 +02:00
}
2012-08-20 06:05:56 +02:00
void Camera::ZoomExtents(View* view, const lcVector3& Center, const lcVector3* Points, int NumPoints, unsigned short nTime, bool bAnimation, bool bAddKey)
{
int Viewport[4] = { 0, 0, view->GetWidth(), view->GetHeight() };
float Aspect = (float)Viewport[2]/(float)Viewport[3];
lcVector3 Position(mPosition + Center - mTargetPosition);
lcMatrix44 Projection = lcMatrix44Perspective(m_fovy, Aspect, m_zNear, m_zFar);
mPosition = lcZoomExtents(Position, mWorldView, Projection, Points, NumPoints);
mTargetPosition = Center;
if (!IsSimple())
{
ChangeKey(nTime, bAnimation, bAddKey, mPosition, LC_CK_EYE);
ChangeKey(nTime, bAnimation, bAddKey, mTargetPosition, LC_CK_TARGET);
}
UpdatePosition(nTime, bAnimation);
}
2011-09-07 23:06:51 +02:00
void Camera::DoZoom(int dy, int mouse, unsigned short nTime, bool bAnimation, bool bAddKey)
{
2012-05-29 01:33:22 +02:00
lcVector3 FrontVector(mPosition - mTargetPosition);
FrontVector.Normalize();
FrontVector *= 2.0f * dy / (21 - mouse);
// TODO: option to move eye, target or both
mPosition += FrontVector;
mTargetPosition += FrontVector;
2012-08-20 06:05:56 +02:00
if (!IsSimple())
{
ChangeKey(nTime, bAnimation, bAddKey, mPosition, LC_CK_EYE);
ChangeKey(nTime, bAnimation, bAddKey, mTargetPosition, LC_CK_TARGET);
}
2012-05-29 01:33:22 +02:00
UpdatePosition(nTime, bAnimation);
2011-09-07 23:06:51 +02:00
}
void Camera::DoPan(int dx, int dy, int mouse, unsigned short nTime, bool bAnimation, bool bAddKey)
{
2012-05-29 01:33:22 +02:00
lcVector3 FrontVector(mPosition - mTargetPosition);
lcVector3 SideVector = lcNormalize(lcCross(FrontVector, mUpVector));
lcVector3 Move = (SideVector * (2.0f * dx / (21 - mouse))) + (mUpVector * (-2.0f * dy / (21 - mouse)));
mPosition += Move;
mTargetPosition += Move;
2012-08-20 06:05:56 +02:00
if (!IsSimple())
{
ChangeKey(nTime, bAnimation, bAddKey, mPosition, LC_CK_EYE);
ChangeKey(nTime, bAnimation, bAddKey, mTargetPosition, LC_CK_TARGET);
}
2012-05-29 01:33:22 +02:00
UpdatePosition(nTime, bAnimation);
2011-09-07 23:06:51 +02:00
}
void Camera::DoRotate(int dx, int dy, int mouse, unsigned short nTime, bool bAnimation, bool bAddKey, float* /*center*/)
{
2012-05-29 01:33:22 +02:00
lcVector3 FrontVector(mPosition - mTargetPosition);
lcVector3 SideVector = lcNormalize(lcCross(FrontVector, mUpVector));
// TODO: option to move eye or target
float len = FrontVector.Length();
FrontVector += (SideVector * (2.0f * dx / (21 - mouse))) + (mUpVector * (-2.0f * dy / (21 - mouse)));
FrontVector.Normalize();
mPosition = (FrontVector * len) + mTargetPosition;
// Calculate new up
FrontVector = mPosition - mTargetPosition;
SideVector = lcCross(FrontVector, mUpVector);
mUpVector = lcNormalize(lcCross(SideVector, FrontVector));
2012-08-20 06:05:56 +02:00
if (!IsSimple())
{
ChangeKey(nTime, bAnimation, bAddKey, mPosition, LC_CK_EYE);
ChangeKey(nTime, bAnimation, bAddKey, mUpVector, LC_CK_UP);
}
2012-05-29 01:33:22 +02:00
UpdatePosition(nTime, bAnimation);
2011-09-07 23:06:51 +02:00
}
void Camera::DoRoll(int dx, int mouse, unsigned short nTime, bool bAnimation, bool bAddKey)
{
2012-05-29 01:33:22 +02:00
lcVector3 FrontVector(mPosition - mTargetPosition);
lcMatrix44 Rotation = lcMatrix44FromAxisAngle(FrontVector, 2.0f * dx / (21 - mouse) * LC_DTOR);
2011-09-07 23:06:51 +02:00
2012-05-29 01:33:22 +02:00
mUpVector = lcMul30(mUpVector, Rotation);
2012-08-20 06:05:56 +02:00
if (!IsSimple())
ChangeKey(nTime, bAnimation, bAddKey, mUpVector, LC_CK_UP);
UpdatePosition(nTime, bAnimation);
}
void Camera::SetViewpoint(LC_VIEWPOINT Viewpoint, unsigned short nTime, bool bAnimation, bool bAddKey)
{
lcVector3 Positions[] =
{
lcVector3(50,0,0), lcVector3(-50,0,0), lcVector3(0,0,50), lcVector3(0,0,-50),
lcVector3(0,50,0), lcVector3(0,-50,0), lcVector3(-10,-10,5)
};
lcVector3 Ups[] = { lcVector3(0,0,1), lcVector3(0,0,1), lcVector3(1,0,0), lcVector3(-1,0,0), lcVector3(0,0,1), lcVector3(0,0,1), lcVector3(-0.2357f, -0.2357f, 0.94281f) };
mPosition = Positions[Viewpoint];
mTargetPosition = lcVector3(0, 0, 0);
mUpVector = Ups[Viewpoint];
if (!IsSimple())
{
ChangeKey(nTime, bAnimation, bAddKey, mPosition, LC_CK_EYE);
ChangeKey(nTime, bAnimation, bAddKey, mTargetPosition, LC_CK_TARGET);
ChangeKey(nTime, bAnimation, bAddKey, mUpVector, LC_CK_UP);
}
2012-05-29 01:33:22 +02:00
UpdatePosition(nTime, bAnimation);
2011-09-07 23:06:51 +02:00
}
void Camera::StartTiledRendering(int tw, int th, int iw, int ih, float fAspect)
{
2012-08-23 20:47:37 +02:00
m_pTR = new TiledRender();
m_pTR->TileSize(tw, th, 0);
m_pTR->ImageSize(iw, ih);
m_pTR->Perspective(m_fovy, fAspect, m_zNear, m_zFar);
2011-09-07 23:06:51 +02:00
}
void Camera::GetTileInfo(int* row, int* col, int* width, int* height)
{
2012-08-23 20:47:37 +02:00
if (m_pTR != NULL)
{
*row = m_pTR->m_Rows - m_pTR->m_CurrentRow - 1;
*col = m_pTR->m_CurrentColumn;
*width = m_pTR->m_CurrentTileWidth;
*height = m_pTR->m_CurrentTileHeight;
}
2011-09-07 23:06:51 +02:00
}
bool Camera::EndTile()
{
2012-08-23 20:47:37 +02:00
if (m_pTR != NULL)
{
if (m_pTR->EndTile())
return true;
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
delete m_pTR;
m_pTR = NULL;
}
2011-09-07 23:06:51 +02:00
2012-08-23 20:47:37 +02:00
return false;
2011-09-07 23:06:51 +02:00
}