mirror of
https://github.com/leozide/leocad
synced 2024-11-17 07:47:55 +01:00
357 lines
13 KiB
C++
357 lines
13 KiB
C++
#include "lc_global.h"
|
|
#include "lc_viewcube.h"
|
|
#include "view.h"
|
|
#include "lc_context.h"
|
|
#include "lc_stringcache.h"
|
|
#include "lc_application.h"
|
|
|
|
//todo: move these
|
|
const float BoxSize = 10.0f;
|
|
const float EdgeSize = BoxSize * 1.0f / 3.0f;
|
|
const float CenterSize = BoxSize * 2.0f / 3.0f;
|
|
|
|
lcViewCube::lcViewCube(View* View)
|
|
: mView(View)
|
|
{
|
|
mMouseDown = false;
|
|
}
|
|
|
|
lcMatrix44 lcViewCube::GetViewMatrix() const
|
|
{
|
|
lcMatrix44 ViewMatrix = mView->mCamera->mWorldView;
|
|
ViewMatrix.SetTranslation(lcVector3(0, 0, 0));
|
|
return ViewMatrix;
|
|
}
|
|
|
|
lcMatrix44 lcViewCube::GetProjectionMatrix() const
|
|
{
|
|
return lcMatrix44Ortho(-BoxSize * 2, BoxSize * 2, -BoxSize * 2, BoxSize * 2, -50, 50);
|
|
}
|
|
|
|
void lcViewCube::Draw()
|
|
{
|
|
const lcPreferences& Preferences = lcGetPreferences();
|
|
lcViewCubeLocation Location = Preferences.mViewCubeLocation;
|
|
|
|
if (Location == lcViewCubeLocation::DISABLED)
|
|
return;
|
|
|
|
lcContext* Context = mView->mContext;
|
|
int Width = mView->mWidth;
|
|
int Height = mView->mHeight;
|
|
int ViewportSize = Preferences.mViewCubeSize;
|
|
|
|
int Left = (Location == lcViewCubeLocation::BOTTOM_LEFT || Location == lcViewCubeLocation::TOP_LEFT) ? 0 : Width - ViewportSize;
|
|
int Bottom = (Location == lcViewCubeLocation::BOTTOM_LEFT || Location == lcViewCubeLocation::BOTTOM_RIGHT) ? 0 : Height - ViewportSize;
|
|
Context->SetViewport(Left, Bottom, ViewportSize, ViewportSize);
|
|
|
|
const lcVector3 BoxVerts[56] =
|
|
{
|
|
lcVector3( BoxSize, -CenterSize, -CenterSize), lcVector3( BoxSize, CenterSize, -CenterSize), lcVector3( BoxSize, -CenterSize, CenterSize), lcVector3( BoxSize, CenterSize, CenterSize),
|
|
lcVector3(-BoxSize, -CenterSize, -CenterSize), lcVector3(-BoxSize, CenterSize, -CenterSize), lcVector3(-BoxSize, -CenterSize, CenterSize), lcVector3(-BoxSize, CenterSize, CenterSize),
|
|
lcVector3(-CenterSize, BoxSize, -CenterSize), lcVector3(CenterSize, BoxSize, -CenterSize), lcVector3(-CenterSize, BoxSize, CenterSize), lcVector3(CenterSize, BoxSize, CenterSize),
|
|
lcVector3(-CenterSize, -BoxSize, -CenterSize), lcVector3(CenterSize, -BoxSize, -CenterSize), lcVector3(-CenterSize, -BoxSize, CenterSize), lcVector3(CenterSize, -BoxSize, CenterSize),
|
|
lcVector3(-CenterSize, -CenterSize, BoxSize), lcVector3(CenterSize, -CenterSize, BoxSize), lcVector3(-CenterSize, CenterSize, BoxSize), lcVector3(CenterSize, CenterSize, BoxSize),
|
|
lcVector3(-CenterSize, -CenterSize, -BoxSize), lcVector3(CenterSize, -CenterSize, -BoxSize), lcVector3(-CenterSize, CenterSize, -BoxSize), lcVector3(CenterSize, CenterSize, -BoxSize),
|
|
|
|
lcVector3( BoxSize, -BoxSize, -CenterSize), lcVector3( BoxSize, BoxSize, -CenterSize), lcVector3( BoxSize, -BoxSize, CenterSize), lcVector3( BoxSize, BoxSize, CenterSize),
|
|
lcVector3(-BoxSize, -BoxSize, -CenterSize), lcVector3(-BoxSize, BoxSize, -CenterSize), lcVector3(-BoxSize, -BoxSize, CenterSize), lcVector3(-BoxSize, BoxSize, CenterSize),
|
|
lcVector3(-CenterSize, BoxSize, -BoxSize), lcVector3(CenterSize, BoxSize, -BoxSize), lcVector3(-CenterSize, BoxSize, BoxSize), lcVector3(CenterSize, BoxSize, BoxSize),
|
|
lcVector3(-CenterSize, -BoxSize, -BoxSize), lcVector3(CenterSize, -BoxSize, -BoxSize), lcVector3(-CenterSize, -BoxSize, BoxSize), lcVector3(CenterSize, -BoxSize, BoxSize),
|
|
lcVector3(-BoxSize, -CenterSize, BoxSize), lcVector3(BoxSize, -CenterSize, BoxSize), lcVector3(-BoxSize, CenterSize, BoxSize), lcVector3(BoxSize, CenterSize, BoxSize),
|
|
lcVector3(-BoxSize, -CenterSize, -BoxSize), lcVector3(BoxSize, -CenterSize, -BoxSize), lcVector3(-BoxSize, CenterSize, -BoxSize), lcVector3(BoxSize, CenterSize, -BoxSize),
|
|
|
|
lcVector3( BoxSize, -BoxSize, -BoxSize), lcVector3( BoxSize, BoxSize, -BoxSize), lcVector3( BoxSize, -BoxSize, BoxSize), lcVector3( BoxSize, BoxSize, BoxSize),
|
|
lcVector3(-BoxSize, -BoxSize, -BoxSize), lcVector3(-BoxSize, BoxSize, -BoxSize), lcVector3(-BoxSize, -BoxSize, BoxSize), lcVector3(-BoxSize, BoxSize, BoxSize)
|
|
};
|
|
|
|
const GLushort BoxIndices[36 + 144 + 144 + 24] =
|
|
{
|
|
0, 1, 2, 3, 2, 1, 5, 6, 7, 6, 5, 4,
|
|
10, 9, 8, 9, 10, 11, 13, 15, 14, 12, 13, 14,
|
|
16, 17, 18, 19, 18, 17, 21, 22, 23, 22, 21, 20,
|
|
|
|
25, 3, 1, 3, 25, 27, 9, 11, 25, 27, 25, 11,
|
|
0, 2, 24, 26, 24, 2, 24, 15, 13, 15, 24, 26,
|
|
2, 3, 43, 2, 43, 41, 19, 17, 43, 41, 43, 17,
|
|
47, 1, 0, 45, 47, 0, 47, 21, 23, 21, 47, 45,
|
|
5, 7, 29, 31, 29, 7, 10, 8, 31, 8, 29, 31,
|
|
28, 6, 4, 6, 28, 30, 12, 14, 28, 30, 28, 14,
|
|
42, 7, 6, 40, 42, 6, 42, 16, 18, 16, 42, 40,
|
|
4, 5, 46, 4, 46, 44, 22, 20, 46, 44, 46, 20,
|
|
34, 11, 10, 34, 35, 11, 35, 34, 19, 18, 19, 34,
|
|
8, 9, 32, 9, 33, 32, 23, 32, 33, 32, 23, 22,
|
|
14, 15, 38, 15, 39, 38, 17, 38, 39, 38, 17, 16,
|
|
36, 13, 12, 36, 37, 13, 37, 36, 21, 20, 21, 36,
|
|
|
|
51, 3, 27, 43, 3, 51, 27, 11, 51, 51, 11, 35, 35, 19, 51, 51, 19, 43,
|
|
25, 1, 49, 49, 1, 47, 49, 9, 25, 33, 9, 49, 49, 23, 33, 47, 23, 49,
|
|
26, 2, 50, 50, 2, 41, 50, 15, 26, 39, 15, 50, 50, 17, 39, 41, 17, 50,
|
|
48, 0, 24, 45, 0, 48, 24, 13, 48, 48, 13, 37, 37, 21, 48, 48, 21, 45,
|
|
31, 7, 55, 55, 7, 42, 55, 10, 31, 34, 10, 55, 55, 18, 34, 42, 18, 55,
|
|
53, 5, 29, 46, 5, 53, 29, 8, 53, 53, 8, 32, 32, 22, 53, 53, 22, 46,
|
|
54, 6, 30, 40, 6, 54, 30, 14, 54, 54, 14, 38, 38, 16, 54, 54, 16, 40,
|
|
28, 4, 52, 52, 4, 44, 52, 12, 28, 36, 12, 52, 52, 20, 36, 44, 20, 52,
|
|
|
|
48, 52, 49, 53, 50, 54, 51, 55, 48, 49, 50, 51, 52, 53, 54, 55, 48, 50, 49, 51, 52, 54, 53, 55
|
|
};
|
|
|
|
Context->SetMaterial(LC_MATERIAL_UNLIT_COLOR);
|
|
Context->SetWorldMatrix(lcMatrix44Identity());
|
|
Context->SetViewMatrix(GetViewMatrix());
|
|
Context->SetProjectionMatrix(GetProjectionMatrix());
|
|
|
|
Context->SetVertexBufferPointer(BoxVerts);
|
|
Context->SetVertexFormatPosition(3);
|
|
Context->SetIndexBufferPointer(BoxIndices);
|
|
|
|
glDepthFunc(GL_ALWAYS);
|
|
glEnable(GL_CULL_FACE);
|
|
|
|
Context->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 36 + 144 + 144, GL_UNSIGNED_SHORT, 0);
|
|
|
|
int IntersectionType = mIntersectionFlags.count();
|
|
if (IntersectionType == 1)
|
|
{
|
|
for (int FlagIdx = 0; FlagIdx < 6; FlagIdx++)
|
|
{
|
|
if (mIntersectionFlags.test(FlagIdx))
|
|
{
|
|
Context->SetColor(1.0f, 0.0f, 0.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, FlagIdx * 6 * 2);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (IntersectionType == 2)
|
|
{
|
|
int First;
|
|
|
|
if (mIntersectionFlags.test(0))
|
|
{
|
|
if (mIntersectionFlags.test(2))
|
|
First = 36;
|
|
else if (mIntersectionFlags.test(3))
|
|
First = 36 + 12;
|
|
else if (mIntersectionFlags.test(4))
|
|
First = 36 + 24;
|
|
else
|
|
First = 36 + 36;
|
|
}
|
|
else if (mIntersectionFlags.test(1))
|
|
{
|
|
if (mIntersectionFlags.test(2))
|
|
First = 36 + 48;
|
|
else if (mIntersectionFlags.test(3))
|
|
First = 36 + 48 + 12;
|
|
else if (mIntersectionFlags.test(4))
|
|
First = 36 + 48 + 24;
|
|
else
|
|
First = 36 + 48 + 36;
|
|
}
|
|
else if (mIntersectionFlags.test(2))
|
|
{
|
|
if (mIntersectionFlags.test(4))
|
|
First = 36 + 96;
|
|
else
|
|
First = 36 + 96 + 12;
|
|
}
|
|
else
|
|
{
|
|
if (mIntersectionFlags.test(4))
|
|
First = 36 + 96 + 24;
|
|
else
|
|
First = 36 + 96 + 36;
|
|
}
|
|
|
|
Context->SetColor(1.0f, 0.0f, 0.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 12, GL_UNSIGNED_SHORT, First * 2);
|
|
}
|
|
else if (IntersectionType == 3)
|
|
{
|
|
int First = 36 + 144;
|
|
|
|
if (mIntersectionFlags.test(1))
|
|
First += 72;
|
|
|
|
if (mIntersectionFlags.test(3))
|
|
First += 36;
|
|
|
|
if (mIntersectionFlags.test(5))
|
|
First += 18;
|
|
|
|
Context->SetColor(1.0f, 0.0f, 0.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 18, GL_UNSIGNED_SHORT, First * 2);
|
|
}
|
|
|
|
glDepthFunc(GL_LEQUAL);
|
|
|
|
Context->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, (36 + 144 + 144) * 2);
|
|
|
|
Context->SetMaterial(LC_MATERIAL_UNLIT_TEXTURE_MODULATE);
|
|
glEnable(GL_BLEND);
|
|
glDepthFunc(GL_ALWAYS);
|
|
|
|
QStringList ViewNames =
|
|
{
|
|
QT_TRANSLATE_NOOP("ViewName", "Front"),
|
|
QT_TRANSLATE_NOOP("ViewName", "Back"),
|
|
QT_TRANSLATE_NOOP("ViewName", "Top"),
|
|
QT_TRANSLATE_NOOP("ViewName", "Bottom"),
|
|
QT_TRANSLATE_NOOP("ViewName", "Left"),
|
|
QT_TRANSLATE_NOOP("ViewName", "Right")
|
|
};
|
|
|
|
int MaxText = 0;
|
|
|
|
for (int FaceIdx = 0; FaceIdx < 6; FaceIdx++)
|
|
{
|
|
int Width, Height;
|
|
gStringCache.GetStringDimensions(&Width, &Height, ViewNames[FaceIdx]);
|
|
if (Width > MaxText)
|
|
MaxText = Width;
|
|
if (Height > MaxText)
|
|
MaxText = Height;
|
|
}
|
|
|
|
float Scale = BoxSize * 4.0f / 3.0f / (float)MaxText;
|
|
|
|
lcMatrix44 ViewMatrices[6] =
|
|
{
|
|
lcMatrix44(lcVector4(Scale, 0.0f, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, Scale, 0.0f), lcVector4(0.0f, 1.0f, 0.0f, 0.0f), lcVector4(0.0f, -BoxSize - 0.01f, 0.0f, 1.0f)),
|
|
lcMatrix44(lcVector4(-Scale, 0.0f, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, Scale, 0.0f), lcVector4(0.0f, 1.0f, 0.0f, 0.0f), lcVector4(0.0f, BoxSize + 0.01f, 0.0f, 1.0f)),
|
|
lcMatrix44(lcVector4(Scale, 0.0f, 0.0f, 0.0f), lcVector4(0.0f, Scale, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, 1.0f, 0.0f), lcVector4(0.0f, 0.0f, BoxSize + 0.01f, 1.0f)),
|
|
lcMatrix44(lcVector4(Scale, 0.0f, 0.0f, 0.0f), lcVector4(0.0f, -Scale, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, 1.0f, 0.0f), lcVector4(0.0f, 0.0f, -BoxSize - 0.01f, 1.0f)),
|
|
lcMatrix44(lcVector4(0.0f, Scale, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, Scale, 0.0f), lcVector4(1.0f, 0.0f, 0.0f, 0.0f), lcVector4(BoxSize + 0.01f, 0.0f, 0.0f, 1.0f)),
|
|
lcMatrix44(lcVector4(0.0f, -Scale, 0.0f, 0.0f), lcVector4(0.0f, 0.0f, Scale, 0.0f), lcVector4(1.0f, 0.0f, 0.0f, 0.0f), lcVector4(-BoxSize - 0.01f, 0.0f, 0.0f, 1.0f))
|
|
};
|
|
|
|
gStringCache.CacheStrings(ViewNames); // todo: precache earlier because the texture only gets uploaded on the next frame
|
|
gStringCache.DrawStrings(Context, ViewMatrices, ViewNames);
|
|
|
|
glDisable(GL_BLEND);
|
|
glDisable(GL_CULL_FACE);
|
|
glDepthFunc(GL_LEQUAL);
|
|
|
|
Context->SetViewport(0, 0, Width, Height);
|
|
}
|
|
|
|
bool lcViewCube::OnLeftButtonDown()
|
|
{
|
|
const lcPreferences& Preferences = lcGetPreferences();
|
|
if (Preferences.mViewCubeLocation == lcViewCubeLocation::DISABLED)
|
|
return false;
|
|
|
|
mIntersectionFlags = GetIntersectionFlags(mIntersection);
|
|
|
|
if (!mIntersectionFlags.any())
|
|
return false;
|
|
|
|
mMouseDownX = mView->mInputState.x;
|
|
mMouseDownY = mView->mInputState.y;
|
|
mMouseDown = true;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool lcViewCube::OnLeftButtonUp()
|
|
{
|
|
const lcPreferences& Preferences = lcGetPreferences();
|
|
if (Preferences.mViewCubeLocation == lcViewCubeLocation::DISABLED)
|
|
return false;
|
|
|
|
if (!mMouseDown)
|
|
return false;
|
|
|
|
mMouseDown = false;
|
|
|
|
if (!mIntersectionFlags.any())
|
|
return false;
|
|
|
|
lcVector3 Position(0.0f, 0.0f, 0.0f);
|
|
|
|
for (int AxisIdx = 0; AxisIdx < 3; AxisIdx++)
|
|
{
|
|
if (mIntersectionFlags.test(AxisIdx * 2))
|
|
Position[AxisIdx] = 1250.0f;
|
|
else if (mIntersectionFlags.test(AxisIdx * 2 + 1))
|
|
Position[AxisIdx] = -1250.0f;
|
|
}
|
|
|
|
mView->SetViewpoint(Position);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool lcViewCube::OnMouseMove()
|
|
{
|
|
const lcPreferences& Preferences = lcGetPreferences();
|
|
lcViewCubeLocation Location = Preferences.mViewCubeLocation;
|
|
|
|
if (Location == lcViewCubeLocation::DISABLED)
|
|
return false;
|
|
|
|
if (IsDragging())
|
|
{
|
|
mIntersectionFlags.reset();
|
|
mView->StartOrbitTracking();
|
|
return true;
|
|
}
|
|
|
|
if (mView->IsTracking())
|
|
return false;
|
|
|
|
std::bitset<6> IntersectionFlags = GetIntersectionFlags(mIntersection);
|
|
|
|
if (IntersectionFlags != mIntersectionFlags)
|
|
{
|
|
mIntersectionFlags = IntersectionFlags;
|
|
mView->Redraw();
|
|
}
|
|
|
|
return mIntersectionFlags.any();
|
|
}
|
|
|
|
bool lcViewCube::IsDragging() const
|
|
{
|
|
return mMouseDown && (qAbs(mMouseDownX - mView->mInputState.x) > 3 || qAbs(mMouseDownY - mView->mInputState.y) > 3);
|
|
}
|
|
|
|
std::bitset<6> lcViewCube::GetIntersectionFlags(lcVector3& Intersection) const
|
|
{
|
|
const lcPreferences& Preferences = lcGetPreferences();
|
|
lcViewCubeLocation Location = Preferences.mViewCubeLocation;
|
|
|
|
int Width = mView->mWidth;
|
|
int Height = mView->mHeight;
|
|
int ViewportSize = Preferences.mViewCubeSize;
|
|
int Left = (Location == lcViewCubeLocation::BOTTOM_LEFT || Location == lcViewCubeLocation::TOP_LEFT) ? 0 : Width - ViewportSize;
|
|
int Bottom = (Location == lcViewCubeLocation::BOTTOM_LEFT || Location == lcViewCubeLocation::BOTTOM_RIGHT) ? 0 : Height - ViewportSize;
|
|
int x = mView->mInputState.x - Left;
|
|
int y = mView->mInputState.y - Bottom;
|
|
std::bitset<6> IntersectionFlags;
|
|
|
|
if (x < 0 || x > Width || y < 0 || y > Height)
|
|
return IntersectionFlags;
|
|
|
|
lcVector3 StartEnd[2] = { lcVector3(x, y, 0), lcVector3(x, y, 1) };
|
|
const int Viewport[4] = { 0, 0, ViewportSize, ViewportSize };
|
|
|
|
lcUnprojectPoints(StartEnd, 2, GetViewMatrix(), GetProjectionMatrix(), Viewport);
|
|
|
|
float Distance;
|
|
if (lcBoundingBoxRayIntersectDistance(lcVector3(-BoxSize, -BoxSize, -BoxSize), lcVector3(BoxSize, BoxSize, BoxSize), StartEnd[0], StartEnd[1], &Distance, &Intersection))
|
|
{
|
|
for (int AxisIdx = 0; AxisIdx < 3; AxisIdx++)
|
|
{
|
|
if (mIntersection[AxisIdx] > BoxSize * 2 / 3)
|
|
IntersectionFlags.set(2 * AxisIdx);
|
|
else if (mIntersection[AxisIdx] < -BoxSize * 2 / 3)
|
|
IntersectionFlags.set(2 * AxisIdx + 1);
|
|
}
|
|
}
|
|
|
|
return IntersectionFlags;
|
|
}
|