diff --git a/common/camera.cpp b/common/camera.cpp index c23c87c7..f6e7109c 100644 --- a/common/camera.cpp +++ b/common/camera.cpp @@ -1,5 +1,3 @@ -// Camera object. - #include "lc_global.h" #include "lc_math.h" #include "lc_colors.h" @@ -15,30 +13,28 @@ #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 }, - { "Camera Target", 3, LC_CK_TARGET }, - { "Camera Up Vector", 3, LC_CK_UP } + { "Camera Position", 3, LC_CK_EYE }, + { "Camera Target", 3, LC_CK_TARGET }, + { "Camera Up Vector", 3, LC_CK_UP } }; // ============================================================================= // CameraTarget class -CameraTarget::CameraTarget (Camera *pParent) - : Object (LC_OBJECT_CAMERA_TARGET) +CameraTarget::CameraTarget(Camera *pParent) + : Object(LC_OBJECT_CAMERA_TARGET) { - m_pParent = pParent; - /* - strcpy (m_strName, pParent->GetName ()); - m_strName[LC_OBJECT_NAME_LEN-8] = '\0'; - strcat (m_strName, ".Target"); - */ + m_pParent = pParent; + /* + strcpy (m_strName, pParent->GetName ()); + m_strName[LC_OBJECT_NAME_LEN-8] = '\0'; + strcat (m_strName, ".Target"); + */ } -CameraTarget::~CameraTarget () +CameraTarget::~CameraTarget() { } @@ -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,32 +97,21 @@ Camera::Camera(bool Simple) if (Simple) m_nState |= LC_CAMERA_SIMPLE; -} + 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); -// Start with a standard camera. -Camera::Camera() - : Object(LC_OBJECT_CAMERA) -{ - unsigned char nType = 7; + 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); - 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); - ChangeKey(1, true, true, mPosition, LC_CK_EYE); - 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); + UpdatePosition(1, false); + } } Camera::Camera(float ex, float ey, float ez, float tx, float ty, float tz) @@ -138,30 +143,25 @@ 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; + 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_nState = 0; + m_nType = LC_CAMERA_USER; - m_pTR = NULL; - memset(m_strName, 0, sizeof(m_strName)); + m_pTR = NULL; + memset(m_strName, 0, sizeof(m_strName)); - float *values[] = { mPosition, mTargetPosition, mUpVector }; - RegisterKeys (values, camera_key_info, LC_CK_COUNT); + float *values[] = { mPosition, mTargetPosition, mUpVector }; + RegisterKeys(values, camera_key_info, LC_CK_COUNT); - m_pTarget = new CameraTarget (this); + m_pTarget = new CameraTarget(this); } void Camera::CreateName(const PtrArray& Cameras) @@ -183,184 +183,184 @@ void Camera::CreateName(const PtrArray& Cameras) bool Camera::FileLoad(lcFile& file) { - lcuint8 version, ch; + lcuint8 version, ch; - version = file.ReadU8(); + version = file.ReadU8(); - if (version > LC_CAMERA_SAVE_VERSION) - return false; + if (version > LC_CAMERA_SAVE_VERSION) + return false; - if (version > 5) - if (!Object::FileLoad (file)) - 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 == 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]; + 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_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_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); - } + 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(); + if (version == 3) + { + ch = file.ReadU8(); - while (ch--) - { - lcuint8 step; - double eye[3], target[3], up[3]; - float f[3]; + 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); + 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; + 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)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)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); + 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 - } - } + 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 < 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; + 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); + n = file.ReadS32(); + while (n--) + { + file.ReadU16(&time, 1); + file.ReadFloats(param, 3); + file.ReadU8(&type, 1); - ChangeKey (time, false, true, param, type); - } + ChangeKey(time, false, true, param, type); + } - 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); - ChangeKey (time, true, true, param, type); - } - } + ChangeKey(time, true, true, param, type); + } + } - file.ReadFloats(&m_fovy, 1); - file.ReadFloats(&m_zFar, 1); - file.ReadFloats(&m_zNear, 1); + 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 < 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; + if ((version > 1) && (version < 4)) + { + lcuint32 show; + lcint32 user; - show = file.ReadU32(); -// if (version > 2) - user = file.ReadS32(); - if (show == 0) - m_nState |= LC_CAMERA_HIDDEN; - } + show = file.ReadU32(); +// if (version > 2) + user = file.ReadS32(); + if (show == 0) + m_nState |= LC_CAMERA_HIDDEN; + } - return true; + return true; } void Camera::FileSave(lcFile& file) const { - file.WriteU8(LC_CAMERA_SAVE_VERSION); + file.WriteU8(LC_CAMERA_SAVE_VERSION); - Object::FileSave (file); + Object::FileSave(file); - lcuint8 ch = (unsigned char)strlen(m_strName); - file.WriteU8(ch); - file.WriteBuffer(m_strName, ch); + lcuint8 ch = (unsigned char)strlen(m_strName); + file.WriteU8(ch); + file.WriteBuffer(m_strName, ch); - file.WriteFloat(m_fovy); - file.WriteFloat(m_zFar); - file.WriteFloat(m_zNear); - // version 5 - file.WriteU8(m_nState); - file.WriteU8(m_nType); + file.WriteFloat(m_fovy); + file.WriteFloat(m_zFar); + file.WriteFloat(m_zNear); + // version 5 + file.WriteU8(m_nState); + file.WriteU8(m_nType); } ///////////////////////////////////////////////////////////////////////////// @@ -395,56 +395,56 @@ void Camera::Move(unsigned short nTime, bool bAnimation, bool bAddKey, float dx, ChangeKey(nTime, bAnimation, bAddKey, mUpVector, LC_CK_UP); } -void Camera::Select (bool bSelecting, bool bFocus, bool bMultiple) +void Camera::Select(bool bSelecting, bool bFocus, bool bMultiple) { - if (bSelecting == true) - { - if (bFocus == true) - { - m_nState |= (LC_CAMERA_FOCUSED|LC_CAMERA_SELECTED); + 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; + 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); - } + 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); + } } -void Camera::SelectTarget (bool bSelecting, bool bFocus, bool bMultiple) +void Camera::SelectTarget(bool bSelecting, bool bFocus, bool bMultiple) { - // FIXME: the target should handle this + // FIXME: the target should handle this - if (bSelecting == true) - { - if (bFocus == true) - { - m_nState |= (LC_CAMERA_TARGET_FOCUSED|LC_CAMERA_TARGET_SELECTED); + 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; + 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); - } + 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); + } } void Camera::UpdatePosition(unsigned short nTime, bool bAnimation) @@ -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,130 +501,107 @@ void Camera::UpdateBoundingBox() { 0.3f, 0.3f, -0.6f }, { -0.3f, 0.3f, -0.6f } }; - glVertexPointer (3, GL_FLOAT, 0, verts); + 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); + glEnableClientState(GL_VERTEX_ARRAY); + float box[24][3] = + { + { 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(); - float box[24][3] = + 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()) + { + glPushMatrix(); + glMultMatrixf(ViewWorld); + + float Dist = lcLength(mTargetPosition - mPosition); + lcMatrix44 Projection = lcMatrix44Perspective(m_fovy, 1.33f, 0.01f, Dist); + Projection = lcMatrix44Inverse(Projection); + glMultMatrixf(Projection); + + // Draw the view frustum. + float verts[16][3] = { - { 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 } + { 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 }, }; - glVertexPointer (3, GL_FLOAT, 0, box); - glDrawArrays(GL_LINES, 0, 24); + glVertexPointer(3, GL_FLOAT, 0, verts); + glDrawArrays(GL_LINES, 0, 16); + glPopMatrix(); - glEndList(); - } -} - -void Camera::Render(float fLineWidth) -{ - // Create the display lists if this is the first time we're rendered. - if (!m_nList) - { - m_nList = glGenLists(1); - UpdateBoundingBox(); } - 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(); - - 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); - - // 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(); - - 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(); - - glPopMatrix(); - } + glDisableClientState(GL_VERTEX_ARRAY); } void Camera::MinIntersectDist(lcClickLine* ClickLine) @@ -659,14 +622,31 @@ 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) - m_pTR->BeginTile(); - else - { - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(lcMatrix44Perspective(m_fovy, fAspect, m_zNear, m_zFar)); + if (m_pTR != NULL) + m_pTR->BeginTile(); + else + { + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(lcMatrix44Perspective(m_fovy, fAspect, m_zNear, m_zFar)); /* ymax = 10;//(m_zFar-m_zNear)*tan(DTOR*m_fovy)/3; ymin = -ymax; @@ -676,10 +656,10 @@ void Camera::LoadProjection(float fAspect) zfar = 60; glOrtho(xmin, xmax, ymin, ymax, znear, zfar); */ - } + } - glMatrixMode(GL_MODELVIEW); - glLoadMatrixf(mWorldView); + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(mWorldView); } void Camera::ZoomExtents(View* view, const lcVector3& Center, const lcVector3* Points, int NumPoints, unsigned short nTime, bool bAnimation, bool bAddKey) @@ -805,33 +785,33 @@ void Camera::SetViewpoint(LC_VIEWPOINT Viewpoint, unsigned short nTime, bool bAn void Camera::StartTiledRendering(int tw, int th, int iw, int ih, float fAspect) { - 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); + 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); } void Camera::GetTileInfo(int* row, int* col, int* width, int* height) { - 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; - } + 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; + } } bool Camera::EndTile() { - if (m_pTR != NULL) - { - if (m_pTR->EndTile()) - return true; + if (m_pTR != NULL) + { + if (m_pTR->EndTile()) + return true; - delete m_pTR; - m_pTR = NULL; - } + delete m_pTR; + m_pTR = NULL; + } - return false; + return false; } diff --git a/common/camera.h b/common/camera.h index be97683c..c5489cb9 100644 --- a/common/camera.h +++ b/common/camera.h @@ -1,7 +1,6 @@ #ifndef _CAMERA_H_ #define _CAMERA_H_ -#include "opengl.h" #include "object.h" #include "lc_math.h" #include "array.h" @@ -48,36 +47,31 @@ enum LC_CK_TYPES class CameraTarget : public Object { public: - CameraTarget (Camera *pParent); - virtual ~CameraTarget (); + CameraTarget(Camera *pParent); + virtual ~CameraTarget(); public: virtual void MinIntersectDist(lcClickLine* ClickLine); - bool IntersectsVolume(const lcVector4 Planes[6]) - { 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) + 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) { // FIXME: move the position handling to the camera target } const char* GetName() const; - Camera* GetParent () const + Camera* GetParent() const { return m_pParent; } 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(); @@ -113,7 +107,7 @@ public: bool IsVisible() { return (m_nState & LC_CAMERA_HIDDEN) == 0; } bool IsSelected() - { return (m_nState & (LC_CAMERA_SELECTED|LC_CAMERA_TARGET_SELECTED)) != 0; } + { return (m_nState & (LC_CAMERA_SELECTED|LC_CAMERA_TARGET_SELECTED)) != 0; } bool IsEyeSelected() { return (m_nState & LC_CAMERA_SELECTED) != 0; } bool IsTargetSelected() @@ -127,7 +121,7 @@ public: void Select() { m_nState |= (LC_CAMERA_SELECTED|LC_CAMERA_TARGET_SELECTED); } void UnSelect() - { m_nState &= ~(LC_CAMERA_SELECTED|LC_CAMERA_FOCUSED|LC_CAMERA_TARGET_SELECTED|LC_CAMERA_TARGET_FOCUSED); } + { m_nState &= ~(LC_CAMERA_SELECTED|LC_CAMERA_FOCUSED|LC_CAMERA_TARGET_SELECTED|LC_CAMERA_TARGET_FOCUSED); } void UnFocus() { m_nState &= ~(LC_CAMERA_FOCUSED|LC_CAMERA_TARGET_FOCUSED); } void FocusEye() @@ -136,15 +130,14 @@ public: { m_nState |= (LC_CAMERA_TARGET_FOCUSED|LC_CAMERA_TARGET_SELECTED); } */ - void SelectTarget (bool bSelecting, bool bFocus, bool bMultiple); + void SelectTarget(bool bSelecting, bool bFocus, bool bMultiple); public: bool FileLoad(lcFile& file); void FileSave(lcFile& file) const; virtual void MinIntersectDist(lcClickLine* ClickLine); - void Select (bool bSelecting, bool bFocus, bool bMultiple); - 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 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; }; diff --git a/common/lc_math.h b/common/lc_math.h index fad81e27..3b3f5839 100644 --- a/common/lc_math.h +++ b/common/lc_math.h @@ -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++) diff --git a/common/light.h b/common/light.h index 71da879a..01fa73c9 100644 --- a/common/light.h +++ b/common/light.h @@ -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); diff --git a/common/object.h b/common/object.h index f4e370ea..0158689b 100755 --- a/common/object.h +++ b/common/object.h @@ -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; /* diff --git a/common/piece.cpp b/common/piece.cpp index d0d4a2eb..d576337e 100644 --- a/common/piece.cpp +++ b/common/piece.cpp @@ -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)); } diff --git a/common/piece.h b/common/piece.h index c263de6f..3f3cc175 100644 --- a/common/piece.h +++ b/common/piece.h @@ -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; diff --git a/common/project.cpp b/common/project.cpp index 3d34f4d8..e11f1798 100644 --- a/common/project.cpp +++ b/common/project.cpp @@ -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); } }