mirror of
https://github.com/leozide/leocad
synced 2024-12-28 22:23:35 +01:00
312 lines
9.4 KiB
C++
312 lines
9.4 KiB
C++
#include "lc_global.h"
|
|
#include "lc_viewcube.h"
|
|
#include "view.h"
|
|
#include "lc_context.h"
|
|
#include "texfont.h"
|
|
#include "lc_application.h"
|
|
|
|
//todo: move these
|
|
const float BoxSize = 10.0f;
|
|
|
|
lcViewCube::lcViewCube(View* View)
|
|
: mView(View)
|
|
{
|
|
mIntersectionFlags = 0;
|
|
}
|
|
|
|
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[8] =
|
|
{
|
|
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 + 24] =
|
|
{
|
|
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,
|
|
0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7
|
|
};
|
|
|
|
Context->SetMaterial(LC_MATERIAL_UNLIT_COLOR);
|
|
Context->SetWorldMatrix(lcMatrix44Identity());
|
|
Context->SetViewMatrix(GetViewMatrix());
|
|
Context->SetProjectionMatrix(GetProjectionMatrix());
|
|
|
|
Context->SetVertexBufferPointer(BoxVerts);
|
|
Context->SetVertexFormatPosition(3);
|
|
Context->SetIndexBufferPointer(BoxIndices);
|
|
|
|
Context->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
|
|
Context->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
Context->DrawIndexedPrimitives(GL_LINES, 24, GL_UNSIGNED_SHORT, 36 * 2);
|
|
|
|
glDisable(GL_DEPTH_TEST); // TODO: don't disable depth, fix z fighting
|
|
|
|
int IntersectionType = mIntersectionFlags.count();
|
|
if (IntersectionType == 1)
|
|
{
|
|
lcVector3 Center(0.0f, 0.0f, 0.0f), Dx(0.0f, 0.0f, 0.0f), Dy(0.0f, 0.0f, 0.0f);
|
|
int AxisIdx;
|
|
|
|
for (AxisIdx = 0; AxisIdx < 3; AxisIdx++)
|
|
{
|
|
if (mIntersectionFlags.test(AxisIdx * 2))
|
|
{
|
|
Center[AxisIdx] = -BoxSize;
|
|
break;
|
|
}
|
|
else if (mIntersectionFlags.test(AxisIdx * 2 + 1))
|
|
{
|
|
Center[AxisIdx] = BoxSize;
|
|
break;
|
|
}
|
|
}
|
|
|
|
Dx[(AxisIdx + 1) % 3] = BoxSize * 2 / 3;
|
|
Dy[(AxisIdx + 2) % 3] = BoxSize * 2 / 3;
|
|
|
|
lcVector3 FaceVerts[] =
|
|
{
|
|
Center - Dx - Dy, Center + Dx - Dy, Center - Dx + Dy, Center + Dx + Dy
|
|
};
|
|
|
|
Context->SetVertexBufferPointer(FaceVerts);
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
Context->SetColor(1.0f, 0.0f, 0.0f, 1.0f);
|
|
Context->DrawPrimitives(GL_TRIANGLE_STRIP, 0, 4);
|
|
}
|
|
else if (IntersectionType == 2)
|
|
{
|
|
lcVector3 Center(0.0f, 0.0f, 0.0f), Dx(0.0f, 0.0f, 0.0f), Dy(0.0f, 0.0f, 0.0f), Dz(0.0f, 0.0f, 0.0f);
|
|
int Corners = 0;
|
|
|
|
for (int AxisIdx = 0; AxisIdx < 3; AxisIdx++)
|
|
{
|
|
if (mIntersectionFlags.test(AxisIdx * 2))
|
|
{
|
|
if (!Corners++)
|
|
Dx[AxisIdx] = BoxSize * 1 / 3;
|
|
else
|
|
Dy[AxisIdx] = BoxSize * 1 / 3;
|
|
|
|
Center[AxisIdx] = -BoxSize;
|
|
}
|
|
else if (mIntersectionFlags.test(AxisIdx * 2 + 1))
|
|
{
|
|
if (!Corners++)
|
|
Dx[AxisIdx] = -BoxSize * 1 / 3;
|
|
else
|
|
Dy[AxisIdx] = -BoxSize * 1 / 3;
|
|
|
|
Center[AxisIdx] = BoxSize;
|
|
}
|
|
else
|
|
Dz[AxisIdx] = BoxSize * 2 / 3;
|
|
}
|
|
|
|
lcVector3 FaceVerts[] =
|
|
{
|
|
Center - Dz, Center + Dx - Dz, Center + Dz, Center + Dx + Dz,
|
|
Center - Dz, Center + Dy - Dz, Center + Dz, Center + Dy + Dz
|
|
};
|
|
|
|
Context->SetVertexBufferPointer(FaceVerts);
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
Context->SetColor(1.0f, 0.0f, 0.0f, 1.0f);
|
|
Context->DrawPrimitives(GL_TRIANGLE_STRIP, 0, 4);
|
|
Context->DrawPrimitives(GL_TRIANGLE_STRIP, 4, 4);
|
|
}
|
|
else if (IntersectionType == 3)
|
|
{
|
|
lcVector3 Signs;
|
|
|
|
for (int AxisIdx = 0; AxisIdx < 3; AxisIdx++)
|
|
{
|
|
if (mIntersectionFlags.test(AxisIdx * 2))
|
|
Signs[AxisIdx] = -1.0f;
|
|
else
|
|
Signs[AxisIdx] = 1.0f;
|
|
}
|
|
|
|
lcVector3 Center = Signs * BoxSize;
|
|
lcVector3 Dx = lcVector3(BoxSize * 1 / 3 * Signs[0], 0.0f, 0.0f);
|
|
lcVector3 Dy = lcVector3(0.0f, BoxSize * 1 / 3 * Signs[1], 0.0f);
|
|
lcVector3 Dz = lcVector3(0.0f, 0.0f, BoxSize * 1 / 3 * Signs[2]);
|
|
|
|
lcVector3 FaceVerts[] =
|
|
{
|
|
Center - Dz, Center - Dx - Dz, Center, Center - Dx,
|
|
Center - Dz, Center - Dy - Dz, Center, Center - Dy,
|
|
Center - Dx, Center - Dy - Dx, Center, Center - Dy
|
|
};
|
|
|
|
Context->SetVertexBufferPointer(FaceVerts);
|
|
Context->SetVertexFormatPosition(3);
|
|
|
|
Context->SetColor(1.0f, 0.0f, 0.0f, 1.0f);
|
|
Context->DrawPrimitives(GL_TRIANGLE_STRIP, 0, 4);
|
|
Context->DrawPrimitives(GL_TRIANGLE_STRIP, 4, 4);
|
|
Context->DrawPrimitives(GL_TRIANGLE_STRIP, 8, 4);
|
|
}
|
|
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
Context->SetMaterial(LC_MATERIAL_UNLIT_TEXTURE_MODULATE);
|
|
Context->BindTexture2D(gTexFont.GetTexture());
|
|
glEnable(GL_BLEND);
|
|
|
|
const char* ViewNames[6] = { "Front", "Back", "Top", "Bottom", "Left", "Right" };
|
|
|
|
int MaxText = 0;
|
|
|
|
for (int FaceIdx = 0; FaceIdx < 6; FaceIdx++)
|
|
{
|
|
int Width, Height;
|
|
gTexFont.GetStringDimensions(&Width, &Height, ViewNames[FaceIdx]);
|
|
if (Width > MaxText)
|
|
MaxText = Width;
|
|
if (Height > MaxText)
|
|
MaxText = Height;
|
|
}
|
|
|
|
float Scale = (BoxSize * 2.0f - 4.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))
|
|
};
|
|
|
|
float TextBuffer[256 * 5 * 3];
|
|
int CharsWritten = 0;
|
|
|
|
for (int FaceIdx = 0; FaceIdx < 6; FaceIdx++)
|
|
{
|
|
const char* ViewName = ViewNames[FaceIdx];
|
|
gTexFont.GetTriangles(ViewMatrices[FaceIdx], ViewName, TextBuffer + CharsWritten * 2 * 3 * 5);
|
|
CharsWritten += strlen(ViewName);
|
|
}
|
|
|
|
Context->SetVertexBufferPointer(TextBuffer);
|
|
Context->SetVertexFormat(0, 3, 0, 2, 0, false);
|
|
|
|
Context->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
Context->DrawPrimitives(GL_TRIANGLES, 0, CharsWritten * 2 * 3);
|
|
|
|
glDisable(GL_BLEND);
|
|
|
|
Context->SetViewport(0, 0, Width, Height);
|
|
}
|
|
|
|
bool lcViewCube::OnLeftButtonUp()
|
|
{
|
|
const lcPreferences& Preferences = lcGetPreferences();
|
|
if (Preferences.mViewCubeLocation == lcViewCubeLocation::DISABLED)
|
|
return 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] = -BoxSize;
|
|
else if (mIntersectionFlags.test(AxisIdx * 2 + 1))
|
|
Position[AxisIdx] = BoxSize;
|
|
}
|
|
|
|
mView->SetViewpoint(Position);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool lcViewCube::OnMouseMove()
|
|
{
|
|
const lcPreferences& Preferences = lcGetPreferences();
|
|
lcViewCubeLocation Location = Preferences.mViewCubeLocation;
|
|
|
|
if (Location == lcViewCubeLocation::DISABLED)
|
|
return false;
|
|
|
|
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;
|
|
|
|
if (x < 0 || x > Width || y < 0 || y > Height)
|
|
{
|
|
if (mIntersectionFlags.any())
|
|
{
|
|
mIntersectionFlags.reset();
|
|
mView->Redraw();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
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);
|
|
std::bitset<6> IntersectionFlags;
|
|
|
|
float Distance;
|
|
if (lcBoundingBoxRayIntersectDistance(lcVector3(-BoxSize, -BoxSize, -BoxSize), lcVector3(BoxSize, BoxSize, BoxSize), StartEnd[0], StartEnd[1], &Distance, &mIntersection))
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
if (IntersectionFlags != mIntersectionFlags)
|
|
{
|
|
mIntersectionFlags = IntersectionFlags;
|
|
mView->Redraw();
|
|
}
|
|
|
|
return true;
|
|
}
|