summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorleo2005-02-05 00:36:12 +0000
committerleo2005-02-05 00:36:12 +0000
commitbfe0fb1e139839503b54c879cb15fad7f2d66187 (patch)
treed4a830e064134830eb21a993dd24d41184325ed3 /common
parent1235f5fa68dea0997e36b6fc7ba5a868b88bbe60 (diff)
More mouse movement improvements.
git-svn-id: http://svn.leocad.org/trunk@373 c7d43263-9d01-0410-8a33-9dba5d9f93d6
Diffstat (limited to 'common')
-rw-r--r--common/algebra.h16
-rw-r--r--common/project.cpp447
-rw-r--r--common/project.h20
3 files changed, 326 insertions, 157 deletions
diff --git a/common/algebra.h b/common/algebra.h
index 671fe4f..1a18bb2 100644
--- a/common/algebra.h
+++ b/common/algebra.h
@@ -72,6 +72,9 @@ public:
friend inline Float4 operator/(const Float4& a, float f)
{ return Float4(a.x/f, a.y/f, a.z/f, a.w/f); };
+ friend inline Float4 operator-(const Float4& a)
+ { return Float4(-a.x, -a.y, -a.z, -a.w); };
+
// Dot product.
friend inline float Dot3(const Float4& a, const Float4& b)
{ return a.x*b.x + a.y*b.y + a.z*b.z; };
@@ -173,6 +176,12 @@ public:
friend inline Float4 operator/(const Float4& a, float f)
{ return Float4(_mm_div_ps(a.xyzw, _mm_load_ps1(&f))); };
+ friend inline Float4 operator-(const Float4& a)
+ {
+ static const __declspec(align(16)) unsigned int Mask[4] = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 };
+ return Float4(_mm_xor_ps(xyzw, *(__m128*)&Mask));
+ };
+
// Dot product.
friend inline float Dot3(const Float4& a, const Float4& b)
{
@@ -421,6 +430,13 @@ inline Point3 operator-(const Vector3& a, const Point3& b)
inline Vector3 operator-(const Vector3& a, const Vector3& b)
{ return Vector3(a.GetValue()-b.GetValue()); };
+// Negate.
+inline Vector3 operator-(const Vector3& a)
+{ return Vector3(-a.GetValue()); }
+
+inline Point3 operator-(const Point3& a)
+{ return Point3(-a.GetValue()); }
+
// Dot product.
inline float Dot3(const Vector3& a, const Vector3& b)
{ return Dot3(a.GetValue(), b.GetValue()); };
diff --git a/common/project.cpp b/common/project.cpp
index 6b7df6d..8a6a534 100644
--- a/common/project.cpp
+++ b/common/project.cpp
@@ -2373,35 +2373,55 @@ void Project::RenderOverlays(int Viewport)
{
glDisable(GL_DEPTH_TEST);
- float Arrows[6][3] = {
- { m_OverlayCenter[0], m_OverlayCenter[1], m_OverlayCenter[2] },
- { m_OverlayCenter[0] + m_OverlayScale, m_OverlayCenter[1], m_OverlayCenter[2] },
- { m_OverlayCenter[0], m_OverlayCenter[1], m_OverlayCenter[2] },
- { m_OverlayCenter[0], m_OverlayCenter[1] + m_OverlayScale, m_OverlayCenter[2] },
- { m_OverlayCenter[0], m_OverlayCenter[1], m_OverlayCenter[2] },
- { m_OverlayCenter[0], m_OverlayCenter[1], m_OverlayCenter[2] + m_OverlayScale }
- };
+ // Draw a quad if we're moving on a plane.
+ if ((m_OverlayMode == LC_OVERLAY_XY) || (m_OverlayMode == LC_OVERLAY_XZ) || (m_OverlayMode == LC_OVERLAY_YZ))
+ {
+ glPushMatrix();
+ glTranslatef(m_OverlayCenter[0], m_OverlayCenter[1], m_OverlayCenter[2]);
+ if (m_OverlayMode == LC_OVERLAY_XZ)
+ glRotatef(90.0f, 0.0f, 0.0f, -1.0f);
+ else if (m_OverlayMode == LC_OVERLAY_XY)
+ glRotatef(90.0f, 0.0f, 1.0f, 0.0f);
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glBegin(GL_QUADS);
+ glColor4f(0.8f, 0.8f, 0.0f, 0.3f);
+ glVertex3f(0.0f, 0.0f, 0.0f);
+ glVertex3f(0.0f, m_OverlayScale * 0.5f, 0.0f);
+ glVertex3f(0.0f, m_OverlayScale * 0.5f, m_OverlayScale * 0.5f);
+ glVertex3f(0.0f, 0.0f, m_OverlayScale * 0.5f);
+ glEnd();
+
+ glDisable(GL_BLEND);
+
+ glPopMatrix();
+ }
+
+ // Draw the arrows.
for (int i = 0; i < 3; i++)
{
- if (m_OverlayMode == LC_OVERLAY_X + i)
+ switch (i)
{
- glColor3f(0.8f, 0.8f, 0.0f);
- }
- else
- {
- switch (i)
- {
- case 0:
+ case 0:
+ if ((m_OverlayMode == LC_OVERLAY_X) || (m_OverlayMode == LC_OVERLAY_XY) || (m_OverlayMode == LC_OVERLAY_XZ))
+ glColor3f(0.8f, 0.8f, 0.0f);
+ else
glColor3f(0.8f, 0.0f, 0.0f);
- break;
- case 1:
+ break;
+ case 1:
+ if ((m_OverlayMode == LC_OVERLAY_Y) || (m_OverlayMode == LC_OVERLAY_XY) || (m_OverlayMode == LC_OVERLAY_YZ))
+ glColor3f(0.8f, 0.8f, 0.0f);
+ else
glColor3f(0.0f, 0.8f, 0.0f);
- break;
- case 2:
+ break;
+ case 2:
+ if ((m_OverlayMode == LC_OVERLAY_Z) || (m_OverlayMode == LC_OVERLAY_XZ) || (m_OverlayMode == LC_OVERLAY_YZ))
+ glColor3f(0.8f, 0.8f, 0.0f);
+ else
glColor3f(0.0f, 0.0f, 0.8f);
- break;
- }
+ break;
}
glPushMatrix();
@@ -3135,9 +3155,7 @@ void Project::UpdateSelection()
if (m_nTracking == LC_TRACK_NONE)
{
- m_OverlayMode = LC_OVERLAY_XYZ;
- m_OverlayActive = GetSelectionCenter(m_OverlayCenter);
- m_OverlayScale = 1.0f;
+ ActivateOverlay();
}
SystemUpdateSelected(flags);
@@ -6055,9 +6073,7 @@ void Project::SetAction(int nAction)
if ((m_nCurAction == LC_ACTION_MOVE) || (m_nCurAction == LC_ACTION_ROTATE))
{
- m_OverlayMode = LC_OVERLAY_XYZ;
- m_OverlayActive = GetSelectionCenter(m_OverlayCenter);
- m_OverlayScale = 1.0f;
+ ActivateOverlay();
if (m_OverlayActive)
UpdateAllViews();
@@ -6556,53 +6572,51 @@ void Project::StartTracking(int mode)
FileSave(m_pTrackFile, true);
}
-void Project::SnapPoint (float *point, float *reminder) const
+void Project::SnapVector(Vector3& Delta, Vector3& Leftover) const
{
- int i;
-
if (m_nSnap & LC_DRAW_SNAP_X)
{
- i = (int)(point[0]/0.4f);
-
- if (reminder != NULL)
- reminder[0] = point[0] - (0.4f * i);
-
- point[0] = 0.4f * i;
+ int i = (int)(Delta[0] / 0.4f);
+ Leftover.SetX(Delta[0] - (0.4f * i));
+ Delta.SetX(0.4f * i);
}
if (m_nSnap & LC_DRAW_SNAP_Y)
{
- i = (int)(point[1]/0.4f);
-
- if (reminder != NULL)
- reminder[1] = point[1] - (0.4f * i);
-
- point[1] = 0.4f * i;
+ int i = (int)(Delta[1] / 0.4f);
+ Leftover.SetY(Delta[1] - (0.4f * i));
+ Delta.SetY(0.4f * i);
}
if (m_nSnap & LC_DRAW_SNAP_Z)
{
- i = (int)(point[2]/0.32f);
-
- if (reminder != NULL)
- reminder[2] = point[2] - (0.32f * i);
-
- point[2] = 0.32f * i;
+ int i = (int)(Delta[2] / 0.32f);
+ Leftover.SetZ(Delta[2] - (0.32f * i));
+ Delta.SetZ(0.32f * i);
}
}
-void Project::MoveSelectedObjects(float x, float y, float z)
+void Project::MoveSelectedObjects(const Vector3& Delta)
{
+ float x, y, z;
Piece* pPiece;
Camera* pCamera;
Light* pLight;
if (m_nSnap & LC_DRAW_LOCK_X)
x = 0;
+ else
+ x = Delta[0];
+
if (m_nSnap & LC_DRAW_LOCK_Y)
y = 0;
+ else
+ y = Delta[1];
+
if (m_nSnap & LC_DRAW_LOCK_Z)
z = 0;
+ else
+ z = Delta[2];
for (pCamera = m_pCameras; pCamera; pCamera = pCamera->m_pNext)
if (pCamera->IsSelected())
@@ -7175,6 +7189,7 @@ void Project::OnLeftButtonDown(int x, int y, bool bControl, bool bShift)
m_bTrackCancel = false;
m_nDownX = x;
m_nDownY = y;
+ m_MouseSnapLeftover = Vector3(0, 0, 0);
LoadViewportProjection();
glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);
@@ -7710,129 +7725,202 @@ void Project::OnMouseMove(int x, int y, bool bControl, bool bShift)
case LC_ACTION_MOVE:
{
- Camera *camera = m_pViewCameras[m_nActiveViewport];
+ if (m_OverlayActive && (m_OverlayMode != LC_OVERLAY_XYZ))
+ {
+ Camera* Camera = m_pViewCameras[m_nActiveViewport];
- if (camera->IsSide ())
- {
- Matrix mat;
- float delta[3];
+ Vector3 ScreenX = Cross3(Camera->GetTargetPosition() - Camera->GetEyePosition(), Camera->GetUpVector());
+ Vector3 ScreenY = Camera->GetUpVector();
+ ScreenX.Normalize();
+ Vector3 Dir1, Dir2;
+ bool SingleDir = true;
- mat.CreateLookat (camera->GetEyePos (), camera->GetTargetPos (), camera->GetUpVec ());
- mat.SetTranslation (0, 0, 0);
- mat.Invert ();
+ switch (m_OverlayMode)
+ {
+ case LC_OVERLAY_X:
+ Dir1 = Vector3(1, 0, 0);
+ break;
+ case LC_OVERLAY_Y:
+ Dir1 = Vector3(0, 1, 0);
+ break;
+ case LC_OVERLAY_Z:
+ Dir1 = Vector3(0, 0, 1);
+ break;
+ case LC_OVERLAY_XY:
+ Dir1 = Vector3(1, 0, 0);
+ Dir2 = Vector3(0, 1, 0);
+ SingleDir = false;
+ break;
+ case LC_OVERLAY_XZ:
+ Dir1 = Vector3(1, 0, 0);
+ Dir2 = Vector3(0, 0, 1);
+ SingleDir = false;
+ break;
+ case LC_OVERLAY_YZ:
+ Dir1 = Vector3(0, 1, 0);
+ Dir2 = Vector3(0, 0, 1);
+ SingleDir = false;
+ break;
+ }
- if (m_nTracking == LC_TRACK_LEFT)
- {
- delta[0] = (float)(x - m_nDownX);
- delta[1] = (float)(y - m_nDownY);
- delta[2] = 0;
- }
- else
- {
- delta[0] = 0;
- delta[1] = 0;
- delta[2] = (float)(y - m_nDownY);
- }
+ // Find out what direction the mouse is going to move stuff.
+ Vector3 MoveX, MoveY;
- mat.TransformPoints (delta, 1);
+ if (SingleDir)
+ {
+ float dx1 = Dot3(ScreenX, Dir1);
+ float dy1 = Dot3(ScreenY, Dir1);
- float mouse = 0.25f/(21-m_nMouse);
- delta[0] = delta[0] * mouse + m_fTrack[0];
- delta[1] = delta[1] * mouse + m_fTrack[1];
- delta[2] = delta[2] * mouse + m_fTrack[2];
+ if (fabsf(dx1) > fabsf(dy1))
+ {
+ if (dx1 >= 0.0f)
+ MoveX = Dir1;
+ else
+ MoveX = -Dir1;
- SnapPoint (delta, m_fTrack);
+ MoveY = Vector3(0, 0, 0);
+ }
+ else
+ {
+ MoveX = Vector3(0, 0, 0);
- if (m_OverlayActive)
+ if (dy1 > 0.0f)
+ MoveY = Dir1;
+ else
+ MoveY = -Dir1;
+ }
+ }
+ else
{
- switch (m_OverlayMode)
+ float dx1 = Dot3(ScreenX, Dir1);
+ float dy1 = Dot3(ScreenY, Dir1);
+ float dx2 = Dot3(ScreenX, Dir2);
+ float dy2 = Dot3(ScreenY, Dir2);
+
+ if (fabsf(dx1) > fabsf(dx2))
{
- case LC_OVERLAY_XYZ:
- break;
- case LC_OVERLAY_X:
- delta[1] = delta[2] = 0.0f;
- break;
- case LC_OVERLAY_Y:
- delta[0] = delta[2] = 0.0f;
- break;
- case LC_OVERLAY_Z:
- delta[0] = delta[1] = 0.0f;
- break;
- case LC_OVERLAY_XY:
- delta[2] = 0.0f;
- break;
- case LC_OVERLAY_XZ:
- delta[1] = 0.0f;
- break;
- case LC_OVERLAY_YZ:
- delta[0] = 0.0f;
- break;
- case LC_OVERLAY_CAMERA:
- break;
+ if (dx1 >= 0.0f)
+ MoveX = Dir1;
+ else
+ MoveX = -Dir1;
+
+ if (dy2 >= 0.0f)
+ MoveY = Dir2;
+ else
+ MoveY = -Dir2;
+ }
+ else
+ {
+ if (dx2 >= 0.0f)
+ MoveX = Dir2;
+ else
+ MoveX = -Dir2;
+
+ if (dy1 > 0.0f)
+ MoveY = Dir1;
+ else
+ MoveY = -Dir1;
}
}
- MoveSelectedObjects(delta[0], delta[1], delta[2]);
+ MoveX *= (float)(x - m_nDownX) * 0.25f / (21 - m_nMouse);
+ MoveY *= (float)(y - m_nDownY) * 0.25f / (21 - m_nMouse);
- m_nDownX = x;
- m_nDownY = y;
- }
- else
- {
- // TODO: rewrite
+ m_nDownX = x;
+ m_nDownY = y;
- float mouse = 5.0f/(21-m_nMouse);
- float delta[3] = {
- (ptx - m_fTrack[0])*mouse,
- (pty - m_fTrack[1])*mouse,
- (ptz - m_fTrack[2])*mouse };
- float d[3] = { delta[0], delta[1], delta[2] };
+ Vector3 Delta = MoveX + MoveY + m_MouseSnapLeftover;
+ SnapVector(Delta, m_MouseSnapLeftover);
+ MoveSelectedObjects(Delta);
+ }
+ else
+ {
+ Camera *camera = m_pViewCameras[m_nActiveViewport];
- if (m_OverlayActive)
+ // TODO: old 3D mouse movement code needs to be improved.
+ if (camera->IsSide ())
{
- switch (m_OverlayMode)
+ Matrix mat;
+ float delta[3];
+
+ mat.CreateLookat (camera->GetEyePos (), camera->GetTargetPos (), camera->GetUpVec ());
+ mat.SetTranslation (0, 0, 0);
+ mat.Invert ();
+
+ if (m_nTracking == LC_TRACK_LEFT)
{
- case LC_OVERLAY_XYZ:
- break;
- case LC_OVERLAY_X:
- delta[1] = delta[2] = 0.0f;
- break;
- case LC_OVERLAY_Y:
- delta[0] = delta[2] = 0.0f;
- break;
- case LC_OVERLAY_Z:
- delta[0] = delta[1] = 0.0f;
- break;
- case LC_OVERLAY_XY:
- delta[2] = 0.0f;
- break;
- case LC_OVERLAY_XZ:
- delta[1] = 0.0f;
- break;
- case LC_OVERLAY_YZ:
- delta[0] = 0.0f;
- break;
- case LC_OVERLAY_CAMERA:
- break;
+ delta[0] = (float)(x - m_nDownX);
+ delta[1] = (float)(y - m_nDownY);
+ delta[2] = 0;
}
- }
+ else
+ {
+ delta[0] = 0;
+ delta[1] = 0;
+ delta[2] = (float)(y - m_nDownY);
+ }
+
+ mat.TransformPoints (delta, 1);
- SnapPoint (delta, NULL);
+ float mouse = 0.25f/(21-m_nMouse);
+ delta[0] = delta[0] * mouse + m_fTrack[0];
+ delta[1] = delta[1] * mouse + m_fTrack[1];
+ delta[2] = delta[2] * mouse + m_fTrack[2];
+
+ SnapPoint (delta, m_fTrack);
+
+ if (m_OverlayActive)
+ {
+ switch (m_OverlayMode)
+ {
+ case LC_OVERLAY_XYZ:
+ break;
+ case LC_OVERLAY_CAMERA:
+ break;
+ }
+ }
- m_fTrack[0] = ptx + (delta[0]-d[0])/mouse;
- m_fTrack[1] = pty + (delta[1]-d[1])/mouse;
- m_fTrack[2] = ptz + (delta[2]-d[2])/mouse;
+ MoveSelectedObjects(delta[0], delta[1], delta[2]);
- if ((m_nSnap & LC_DRAW_3DMOUSE) || (m_OverlayActive && (m_OverlayMode != LC_OVERLAY_XYZ)))
- MoveSelectedObjects(delta[0], delta[1], delta[2]);
- else
+ m_nDownX = x;
+ m_nDownY = y;
+ }
+ else
{
- if (m_nTracking == LC_TRACK_LEFT)
- MoveSelectedObjects(delta[0], delta[1], 0);
- else
- MoveSelectedObjects(0, 0, delta[2]);
- }
- }
+ // TODO: rewrite
+
+ float mouse = 5.0f/(21-m_nMouse);
+ float delta[3] = { (ptx - m_fTrack[0])*mouse, (pty - m_fTrack[1])*mouse, (ptz - m_fTrack[2])*mouse };
+ float d[3] = { delta[0], delta[1], delta[2] };
+
+ if (m_OverlayActive)
+ {
+ switch (m_OverlayMode)
+ {
+ case LC_OVERLAY_XYZ:
+ break;
+ case LC_OVERLAY_CAMERA:
+ break;
+ }
+ }
+
+ SnapPoint (delta, NULL);
+
+ m_fTrack[0] = ptx + (delta[0]-d[0])/mouse;
+ m_fTrack[1] = pty + (delta[1]-d[1])/mouse;
+ m_fTrack[2] = ptz + (delta[2]-d[2])/mouse;
+
+ if ((m_nSnap & LC_DRAW_3DMOUSE) || (m_OverlayActive && (m_OverlayMode != LC_OVERLAY_XYZ)))
+ MoveSelectedObjects(delta[0], delta[1], delta[2]);
+ else
+ {
+ if (m_nTracking == LC_TRACK_LEFT)
+ MoveSelectedObjects(delta[0], delta[1], 0);
+ else
+ MoveSelectedObjects(0, 0, delta[2]);
+ }
+ }
+ }
SystemUpdateFocus(NULL);
UpdateAllViews();
@@ -8135,13 +8223,34 @@ void Project::MouseUpdateOverlays(int x, int y)
if ((Closest - Pt).LengthSquared() < 100.0f)
{
- Mode = LC_OVERLAY_X + i - 1;
- break;
+ // If we already know the mouse is close to another axis, select a plane.
+ if (Mode != -1)
+ {
+ if (Mode == LC_OVERLAY_X)
+ {
+ if (i == 2)
+ {
+ Mode = LC_OVERLAY_XY;
+ }
+ else
+ {
+ Mode = LC_OVERLAY_XZ;
+ }
+ }
+ else
+ {
+ Mode = LC_OVERLAY_YZ;
+ }
+
+ break;
+ }
+ else
+ {
+ Mode = LC_OVERLAY_X + i - 1;
+ }
}
}
- // TODO: Check if the mouse is near the center and select a plane.
-
if (Mode == -1)
{
Mode = LC_OVERLAY_XYZ;
@@ -8311,3 +8420,31 @@ void Project::MouseUpdateOverlays(int x, int y)
}
}
}
+
+void Project::ActivateOverlay()
+{
+ m_OverlayActive = GetSelectionCenter(m_OverlayCenter);
+
+ if (m_OverlayActive)
+ {
+ m_OverlayMode = LC_OVERLAY_XYZ;
+
+ GLdouble ScreenX, ScreenY, ScreenZ, PointX, PointY, PointZ;
+ GLdouble ModelMatrix[16], ProjMatrix[16];
+ GLint Viewport[4];
+
+ LoadViewportProjection();
+ glGetDoublev(GL_MODELVIEW_MATRIX, ModelMatrix);
+ glGetDoublev(GL_PROJECTION_MATRIX, ProjMatrix);
+ glGetIntegerv(GL_VIEWPORT, Viewport);
+
+ // Calculate the scaling factor by projecting the center to the front plane then
+ // projecting a point close to it back.
+ gluProject(m_OverlayCenter[0], m_OverlayCenter[1], m_OverlayCenter[2], ModelMatrix, ProjMatrix, Viewport, &ScreenX, &ScreenY, &ScreenZ);
+ gluUnProject(ScreenX + 10.0f, ScreenY, ScreenZ, ModelMatrix, ProjMatrix, Viewport, &PointX, &PointY, &PointZ);
+
+ Vector3 Dist((float)PointX - m_OverlayCenter[0], (float)PointY - m_OverlayCenter[1], (float)PointZ - m_OverlayCenter[2]);
+ m_OverlayScale = Dist.Length() * 5.0f;
+ }
+}
+
diff --git a/common/project.h b/common/project.h
index 8639ac9..cd23d3a 100644
--- a/common/project.h
+++ b/common/project.h
@@ -149,9 +149,23 @@ protected:
void SelectAndFocusNone(bool bFocusOnly);
bool GetSelectionCenter(Point3& Center) const;
void CalculateStep();
- void MoveSelectedObjects(float x, float y, float z);
+ void MoveSelectedObjects(const Vector3& Delta);
void RotateSelectedObjects(float x, float y, float z);
- void SnapPoint (float *point, float *reminder) const;
+ void SnapVector(Vector3& Delta, Vector3& Leftover) const;
+
+ // Deprecated compatibility functions.
+ // TODO: Update function calls to use the math library.
+ inline void MoveSelectedObjects(float x, float y, float z)
+ { MoveSelectedObjects(Vector3(x, y, z)); };
+ void SnapPoint(float *point, float *reminder) const
+ {
+ Vector3 Pt(point[0], point[1], point[2]);
+ Vector3 Rem;
+ if (reminder) Rem = Vector3(reminder[0], reminder[1], reminder[2]);
+ SnapVector(Pt, Rem);
+ point[0] = Pt[0]; point[1] = Pt[1]; point[2] = Pt[2];
+ if (reminder) { reminder[0] = Rem[0]; reminder[1] = Rem[1]; reminder[2] = Rem[2]; }
+ };
// Rendering
void RenderScene(bool bShaded, bool bDrawViewports);
@@ -178,6 +192,7 @@ protected:
int m_nDownY;
float m_fTrack[3];
int m_nMouse;
+ Vector3 m_MouseSnapLeftover;
// Mouse control overlays.
typedef enum
@@ -199,6 +214,7 @@ protected:
Point3 m_OverlayTrackStart;
Vector3 m_OverlayDelta;
void MouseUpdateOverlays(int x, int y);
+ void ActivateOverlay();
void LoadViewportProjection();
bool SetActiveViewport(int x, int y);