Camera cleanup.

This commit is contained in:
leo 2012-08-23 18:47:37 +00:00
parent 303d6e4214
commit 4da5f06d9a
8 changed files with 467 additions and 439 deletions

View file

@ -1,5 +1,3 @@
// Camera object.
#include "lc_global.h"
#include "lc_math.h"
#include "lc_colors.h"
@ -15,8 +13,6 @@
#define LC_CAMERA_SAVE_VERSION 6 // LeoCAD 0.73
GLuint Camera::m_nTargetList = 0;
static LC_OBJECT_KEY_INFO camera_key_info[LC_CK_COUNT] =
{
{ "Camera Position", 3, LC_CK_EYE },
@ -61,6 +57,26 @@ void CameraTarget::MinIntersectDist(lcClickLine* ClickLine)
}
}
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);
}
void CameraTarget::Select(bool bSelecting, bool bFocus, bool bMultiple)
{
m_pParent->SelectTarget(bSelecting, bFocus, bMultiple);
@ -81,20 +97,12 @@ Camera::Camera(bool Simple)
if (Simple)
m_nState |= LC_CAMERA_SIMPLE;
}
// Start with a standard camera.
Camera::Camera()
: Object(LC_OBJECT_CAMERA)
else
{
unsigned char nType = 7;
mPosition = lcVector3(-10.0f, -10.0f, 5.0f);
mTargetPosition = lcVector3(0.0f, 0.0f, 0.0f);
mUpVector = lcVector3(-0.2357f, -0.2357f, 0.94281f);
Initialize();
ChangeKey(1, false, true, mPosition, LC_CK_EYE);
ChangeKey(1, false, true, mTargetPosition, LC_CK_TARGET);
ChangeKey(1, false, true, mUpVector, LC_CK_UP);
@ -102,12 +110,9 @@ Camera::Camera()
ChangeKey(1, true, true, mTargetPosition, LC_CK_TARGET);
ChangeKey(1, true, true, mUpVector, LC_CK_UP);
if (nType != 8)
m_nState = LC_CAMERA_HIDDEN;
m_nType = nType;
UpdatePosition(1, false);
}
}
Camera::Camera(float ex, float ey, float ez, float tx, float ty, float tz)
: Object(LC_OBJECT_CAMERA)
@ -138,22 +143,17 @@ Camera::Camera(float ex, float ey, float ez, float tx, float ty, float tz)
Camera::~Camera()
{
if (m_nList != 0)
glDeleteLists (m_nList, 1);
delete m_pTarget;
}
void Camera::Initialize()
{
m_fovy = 30;
m_zNear = 1;
m_zFar = 500;
m_fovy = 30.0f;
m_zNear = 1.0f;
m_zFar = 500.0f;
m_nState = 0;
m_nList = 0;
m_nType = LC_CAMERA_USER;
m_nList = 0;
m_pTR = NULL;
memset(m_strName, 0, sizeof(m_strName));
@ -457,8 +457,6 @@ void Camera::UpdatePosition(unsigned short nTime, bool bAnimation)
mUpVector = lcNormalize(lcCross(SideVector, FrontVector));
mWorldView = lcMatrix44LookAt(mPosition, mTargetPosition, mUpVector);
UpdateBoundingBox();
}
void Camera::CopyPosition(const Camera* camera)
@ -471,27 +469,15 @@ void Camera::CopyPosition(const Camera* camera)
mPosition = camera->mPosition;
mTargetPosition = camera->mTargetPosition;
mUpVector = camera->mUpVector;
UpdateBoundingBox();
}
void Camera::UpdateBoundingBox()
void Camera::Render(float fLineWidth)
{
// Fix the up vector
lcVector3 FrontVector(mPosition - mTargetPosition);
float len = FrontVector.Length();
lcMatrix44 Mat = lcMatrix44AffineInverse(mWorldView);
Mat.SetTranslation(lcVector3(0, 0, 0));
if (!m_nList)
return;
glNewList(m_nList, GL_COMPILE);
lcMatrix44 ViewWorld = lcMatrix44AffineInverse(mWorldView);
// Draw camera.
glPushMatrix();
glTranslatef(mPosition[0], mPosition[1], mPosition[2]);
glMultMatrixf(Mat);
glMultMatrixf(ViewWorld);
glEnableClientState(GL_VERTEX_ARRAY);
float verts[34][3] =
@ -515,26 +501,47 @@ void Camera::UpdateBoundingBox()
{ 0.3f, 0.3f, -0.6f }, { -0.3f, 0.3f, -0.6f }
};
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);
glDrawArrays(GL_LINES, 0, 24);
glDrawArrays(GL_LINE_STRIP, 24, 10);
// glBegin(GL_LINES);
// glVertex3f(0,0,0);
// glVertex3f(0,0,len);
// glEnd();
glPopMatrix();
glTranslatef(0, 0, -len);
// Draw target.
glPushMatrix();
lcMatrix44 TargetMat = ViewWorld;
TargetMat.SetTranslation(mTargetPosition);
glMultMatrixf(TargetMat);
glEndList();
if (m_nTargetList == 0)
if (IsTargetSelected())
{
m_nTargetList = glGenLists(1);
glNewList (m_nTargetList, GL_COMPILE);
glLineWidth(2.0f);
if (m_nState & LC_CAMERA_TARGET_FOCUSED)
lcSetColorFocused();
else
lcSetColorSelected();
}
else
{
glLineWidth(1.0f);
lcSetColorCamera();
}
glEnableClientState(GL_VERTEX_ARRAY);
float box[24][3] =
{
{ 0.2f, 0.2f, 0.2f }, { -0.2f, 0.2f, 0.2f },
@ -550,95 +557,51 @@ void Camera::UpdateBoundingBox()
{ -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();
glEndList();
}
}
void Camera::Render(float fLineWidth)
lcVector3 Line[2] =
{
// Create the display lists if this is the first time we're rendered.
if (!m_nList)
{
m_nList = glGenLists(1);
UpdateBoundingBox();
}
mPosition,
mTargetPosition
};
if (IsEyeSelected())
{
glLineWidth(fLineWidth*2);
if (m_nState & LC_CAMERA_FOCUSED)
lcSetColorFocused();
else
lcSetColorSelected();
glCallList(m_nList);
glLineWidth(fLineWidth);
}
else
{
lcSetColorCamera();
glCallList(m_nList);
}
if (IsTargetSelected())
{
glLineWidth(fLineWidth*2);
if (m_nState & LC_CAMERA_TARGET_FOCUSED)
lcSetColorFocused();
else
lcSetColorSelected();
glCallList(m_nTargetList);
glLineWidth(fLineWidth);
}
else
{
lcSetColorCamera();
glCallList(m_nTargetList);
}
lcSetColorCamera();
glBegin(GL_LINES);
glVertex3fv(mPosition);
glVertex3fv(mTargetPosition);
glEnd();
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())
{
lcVector3 FrontVector(mTargetPosition - mPosition);
float len = FrontVector.Length();
glPushMatrix();
lcMatrix44 ViewWorld = lcMatrix44AffineInverse(mWorldView);
glMultMatrixf(ViewWorld);
lcMatrix44 InvProjection = lcMatrix44Inverse(lcMatrix44Perspective(m_fovy, 1.33f, 0.01f, len));
glMultMatrixf(InvProjection);
float Dist = lcLength(mTargetPosition - mPosition);
lcMatrix44 Projection = lcMatrix44Perspective(m_fovy, 1.33f, 0.01f, Dist);
Projection = lcMatrix44Inverse(Projection);
glMultMatrixf(Projection);
// draw the viewing frustum
glBegin(GL_LINE_LOOP);
glVertex3i(1, 1, 1);
glVertex3i(-1, 1, 1);
glVertex3i(-1, -1, 1);
glVertex3i(1, -1, 1);
glEnd();
// Draw the view frustum.
float verts[16][3] =
{
{ 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 },
};
glBegin(GL_LINES);
glVertex3i(1, 1, -1);
glVertex3i(1, 1, 1);
glVertex3i(-1, 1, -1);
glVertex3i(-1, 1, 1);
glVertex3i(-1, -1, -1);
glVertex3i(-1, -1, 1);
glVertex3i(1, -1, -1);
glVertex3i(1, -1, 1);
glEnd();
glVertexPointer(3, GL_FLOAT, 0, verts);
glDrawArrays(GL_LINES, 0, 16);
glPopMatrix();
}
glDisableClientState(GL_VERTEX_ARRAY);
}
void Camera::MinIntersectDist(lcClickLine* ClickLine)
@ -659,6 +622,23 @@ void Camera::MinIntersectDist(lcClickLine* ClickLine)
m_pTarget->MinIntersectDist(ClickLine);
}
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);
}
void Camera::LoadProjection(float fAspect)
{
if (m_pTR != NULL)

View file

@ -1,7 +1,6 @@
#ifndef _CAMERA_H_
#define _CAMERA_H_
#include "opengl.h"
#include "object.h"
#include "lc_math.h"
#include "array.h"
@ -53,8 +52,7 @@ public:
public:
virtual void MinIntersectDist(lcClickLine* ClickLine);
bool IntersectsVolume(const lcVector4 Planes[6])
{ return false; }
virtual bool IntersectsVolume(const lcVector4 Planes[6]) const;
void Select(bool bSelecting, bool bFocus, bool bMultiple);
void Move(unsigned short nTime, bool bAnimation, bool bAddKey, float x, float y, float z)
{
@ -68,16 +66,12 @@ public:
protected:
Camera* m_pParent;
friend class Camera; // FIXME: needed for BoundingBoxCalculate ()
// remove and use UpdatePosition instead
};
class Camera : public Object
{
public:
Camera(bool Simple);
Camera();
Camera(float ex, float ey, float ez, float tx, float ty, float tz);
virtual ~Camera();
@ -142,9 +136,8 @@ public:
bool FileLoad(lcFile& file);
void FileSave(lcFile& file) const;
virtual void MinIntersectDist(lcClickLine* ClickLine);
virtual bool IntersectsVolume(const lcVector4 Planes[6]) const;
void Select(bool bSelecting, bool bFocus, bool bMultiple);
bool IntersectsVolume(const lcVector4 Planes[6])
{ return false; }
void UpdatePosition(unsigned short nTime, bool bAnimation);
@ -175,7 +168,6 @@ public:
protected:
void Initialize();
void UpdateBoundingBox();
// Camera target
CameraTarget* m_pTarget;
@ -184,8 +176,6 @@ protected:
char m_strName[81];
unsigned char m_nState;
unsigned char m_nType;
GLuint m_nList;
static GLuint m_nTargetList;
TiledRender* m_pTR;
};

View file

@ -381,6 +381,13 @@ inline lcVector3 lcMul31(const lcVector3& a, const lcMatrix44& b)
return lcVector3(v[0], v[1], v[2]);
}
inline lcVector3 lcMul31(const lcVector4& a, const lcMatrix44& b)
{
lcVector4 v = b.r[0] * a[0] + b.r[1] * a[1] + b.r[2] * a[2] + b.r[3];
return lcVector3(v[0], v[1], v[2]);
}
inline lcVector3 lcMul30(const lcVector3& a, const lcMatrix44& b)
{
lcVector4 v = b.r[0] * a[0] + b.r[1] * a[1] + b.r[2] * a[2];
@ -388,6 +395,13 @@ inline lcVector3 lcMul30(const lcVector3& a, const lcMatrix44& b)
return lcVector3(v[0], v[1], v[2]);
}
inline lcVector3 lcMul30(const lcVector4& a, const lcMatrix44& b)
{
lcVector4 v = b.r[0] * a[0] + b.r[1] * a[1] + b.r[2] * a[2];
return lcVector3(v[0], v[1], v[2]);
}
inline lcVector4 lcMul4(const lcVector4& a, const lcMatrix44& b)
{
return b.r[0] * a[0] + b.r[1] * a[1] + b.r[2] * a[2] + b.r[3] * a[3];
@ -744,7 +758,7 @@ inline lcMatrix44 lcMatrix44AffineInverse(const lcMatrix44& m)
Inv.r[1] = lcVector4(m.r[0][1], m.r[1][1], m.r[2][1], m.r[1][3]);
Inv.r[2] = lcVector4(m.r[0][2], m.r[1][2], m.r[2][2], m.r[2][3]);
lcVector3 Trans = -lcMul30(lcVector3(m[3][0], m[3][1], m[3][2]), Inv);
lcVector3 Trans = -lcMul30(m.r[3], Inv);
Inv.r[3] = lcVector4(Trans[0], Trans[1], Trans[2], 1.0f);
return Inv;
@ -1370,12 +1384,22 @@ float LinePointMinDistance(const Vector3& Point, const Vector3& Start, const Vec
return Length(Closest - Point);
}
// Return true if Box intersects the volume defined by Planes.
bool BoundingBoxIntersectsVolume(const BoundingBox& Box, const Vector4* Planes, int NumPlanes)
*/
// Returns true if the axis aligned box intersects the volume defined by planes.
inline bool lcBoundingBoxIntersectsVolume(const lcVector3& Min, const lcVector3& Max, const lcVector4 Planes[6])
{
Vector3 Points[8];
Box.GetPoints(Points);
const int NumPlanes = 6;
lcVector3 Points[8] =
{
Points[0] = lcVector3(Min[0], Min[1], Min[2]),
Points[1] = lcVector3(Min[0], Max[1], Min[2]),
Points[2] = lcVector3(Max[0], Max[1], Min[2]),
Points[3] = lcVector3(Max[0], Min[1], Min[2]),
Points[4] = lcVector3(Min[0], Min[1], Max[2]),
Points[5] = lcVector3(Min[0], Max[1], Max[2]),
Points[6] = lcVector3(Max[0], Max[1], Max[2]),
Points[7] = lcVector3(Max[0], Min[1], Max[2])
};
// Start by testing trivial reject/accept cases.
int Outcodes[8];
@ -1387,7 +1411,7 @@ bool BoundingBoxIntersectsVolume(const BoundingBox& Box, const Vector4* Planes,
for (int j = 0; j < NumPlanes; j++)
{
if (Dot3(Points[i], Planes[j]) + Planes[j][3] > 0)
if (lcDot3(Points[i], Planes[j]) + Planes[j][3] > 0)
Outcodes[i] |= 1 << j;
}
}
@ -1408,9 +1432,29 @@ bool BoundingBoxIntersectsVolume(const BoundingBox& Box, const Vector4* Planes,
if (OutcodesOR == 0)
return true;
return true;
}
int Indices[36] =
{
0, 1, 2,
0, 2, 3,
7, 6, 5,
7, 5, 4,
0, 1, 5,
0, 5, 4,
2, 3, 7,
2, 7, 6,
0, 3, 7,
0, 7, 4,
1, 2, 6,
1, 6, 5
};
for (int Idx = 0; Idx < 36; Idx += 3)
if (lcTriangleIntersectsPlanes(Points[Indices[Idx]*3], Points[Indices[Idx+1]*3], Points[Indices[Idx+2]*3], Planes))
return true;
return false;
}
/*
bool SphereIntersectsVolume(const Vector3& Center, float Radius, const Vector4* Planes, int NumPlanes)
{
for (int j = 0; j < NumPlanes; j++)

View file

@ -38,7 +38,7 @@ public:
public:
virtual void MinIntersectDist(lcClickLine* ClickLine);
bool IntersectsVolume(const lcVector4 Planes[6])
virtual bool IntersectsVolume(const lcVector4 Planes[6]) const
{ return false; }
void Select (bool bSelecting, bool bFocus, bool bMultiple);
void Move (unsigned short nTime, bool bAnimation, bool bAddKey, float x, float y, float z)
@ -104,7 +104,7 @@ public:
void Render(float fLineWidth);
virtual void MinIntersectDist(lcClickLine* ClickLine);
bool IntersectsVolume(const lcVector4 Planes[6])
virtual bool IntersectsVolume(const lcVector4 Planes[6]) const
{ return false; }
void UpdatePosition(unsigned short nTime, bool bAnimation);
void Move(unsigned short nTime, bool bAnimation, bool bAddKey, float dx, float dy, float dz);

View file

@ -67,7 +67,7 @@ public:
virtual void Select(bool bSelecting, bool bFocus, bool bMultiple) = 0;
// Check if the object intersects the volume specified by a given set of planes.
virtual bool IntersectsVolume(const lcVector4 Planes[6]) = 0;
virtual bool IntersectsVolume(const lcVector4 Planes[6]) const = 0;
/*

View file

@ -412,7 +412,7 @@ void Piece::MinIntersectDist(lcClickLine* ClickLine)
ClickLine->Closest = this;
}
bool Piece::IntersectsVolume(const lcVector4 Planes[6])
bool Piece::IntersectsVolume(const lcVector4 Planes[6]) const
{
// First check the bounding box for quick rejection.
lcVector3 Box[8] =
@ -437,7 +437,7 @@ bool Piece::IntersectsVolume(const lcVector4 Planes[6])
for (i = 0; i < NumPlanes; i++)
{
lcVector3 PlaneNormal = lcMul30(lcVector3(Planes[i][0], Planes[i][1], Planes[i][2]), WorldToLocal);
lcVector3 PlaneNormal = lcMul30(Planes[i], WorldToLocal);
LocalPlanes[i] = lcVector4(PlaneNormal, Planes[i][3] - lcDot3(WorldToLocal[3], PlaneNormal));
}

View file

@ -29,7 +29,7 @@ public:
void Select (bool bSelecting, bool bFocus, bool bMultiple);
virtual void InsertTime (unsigned short start, bool animation, unsigned short time);
virtual void RemoveTime (unsigned short start, bool animation, unsigned short time);
virtual bool IntersectsVolume(const lcVector4 Planes[6]);
virtual bool IntersectsVolume(const lcVector4 Planes[6]) const;

View file

@ -364,7 +364,7 @@ bool Project::FileLoad(lcFile* file, bool bUndo, bool bMerge)
if (fv < 0.6f) // old view
{
Camera* pCam = new Camera();
Camera* pCam = new Camera(false);
pCam->CreateName(mCameras);
mCameras.Add(pCam);
@ -619,11 +619,11 @@ bool Project::FileLoad(lcFile* file, bool bUndo, bool bMerge)
file->ReadS32(&count, 1);
for (i = 0; i < count; i++)
mCameras.Add(new Camera());
mCameras.Add(new Camera(false));
if (count < 7)
{
Camera* pCam = new Camera();
Camera* pCam = new Camera(false);
for (i = 0; i < count; i++)
pCam->FileLoad(*file);
delete pCam;
@ -4546,7 +4546,7 @@ void Project::HandleCommand(LC_COMMANDS id, unsigned long nParam)
while (i--)
{
Camera* pCamera = new Camera();
Camera* pCamera = new Camera(false);
pCamera->FileLoad(*file);
pCamera->CreateName(mCameras);
pCamera->Select(true, false, false);
@ -6373,6 +6373,20 @@ void Project::FindObjectsInBox(float x1, float y1, float x2, float y2, PtrArray<
}
}
for (int CameraIdx = 0; CameraIdx < mCameras.GetSize(); CameraIdx++)
{
Camera* pCamera = mCameras[CameraIdx];
if (!pCamera->IsVisible() || pCamera == Cam)
continue;
if (pCamera->IntersectsVolume(Planes))
Objects.Add(pCamera);
if (pCamera->GetTarget()->IntersectsVolume(Planes))
Objects.Add(pCamera->GetTarget());
}
// TODO: lights and cameras.
}
@ -6441,10 +6455,10 @@ bool Project::StopTracking(bool bAccept)
pPiece->Select (true, false, false);
}
else
Objects[i]->Select(true, false, Control);
Objects[i]->Select(true, false, true);
}
else
Objects[i]->Select(true, false, Control);
Objects[i]->Select(true, false, true);
}
}