First pass view cube.

This commit is contained in:
Leonardo Zide
2018-08-19 20:28:04 -07:00
parent 1c1a5fb599
commit 4aa2cbeeb6
8 changed files with 433 additions and 1 deletions
+22
View File
@@ -996,6 +996,28 @@ void lcCamera::SetViewpoint(lcViewpoint Viewpoint)
UpdatePosition(1);
}
void lcCamera::SetViewpoint(const lcVector3& Position)
{
mPosition = Position;
mTargetPosition = lcVector3(0, 0, 0);
lcVector3 UpVector(0, 0, 1), FrontVector(Position), SideVector;
FrontVector.Normalize();
if (FrontVector == UpVector)
SideVector = lcVector3(1, 0, 0);
else
SideVector = lcCross(FrontVector, UpVector);
UpVector = lcCross(SideVector, FrontVector);
UpVector.Normalize();
mUpVector = UpVector;
ChangeKey(mPositionKeys, mPosition, 1, false);
ChangeKey(mTargetPositionKeys, mTargetPosition, 1, false);
ChangeKey(mUpVectorKeys, mUpVector, 1, false);
UpdatePosition(1);
}
void lcCamera::SetAngles(float Latitude, float Longitude)
{
mPosition = lcVector3(0, -1, 0);
+1
View File
@@ -284,6 +284,7 @@ public:
void MoveSelected(lcStep Step, bool AddKey, const lcVector3& Distance);
void MoveRelative(const lcVector3& Distance, lcStep Step, bool AddKey);
void SetViewpoint(lcViewpoint Viewpoint);
void SetViewpoint(const lcVector3& Position);
void SetAngles(float Latitude, float Longitude);
char m_strName[81];
+293
View File
@@ -0,0 +1,293 @@
#include "lc_global.h"
#include "lc_viewcube.h"
#include "view.h"
#include "lc_context.h"
#include "texfont.h"
//todo: move these and add preferences
const int ViewportSize = 100;
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()
{
lcContext* Context = mView->mContext;
int Width = mView->mWidth;
int Height = mView->mHeight;
Context->SetViewport(Width - ViewportSize, Height - ViewportSize, 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()
{
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()
{
int x = mView->mInputState.x;
int y = mView->mInputState.y;
int Width = mView->mWidth;
int Height = mView->mHeight;
if (x < Width - ViewportSize || x > Width || y < Height - ViewportSize || y > Height)
{
if (mIntersectionFlags.any())
{
mIntersectionFlags.reset();
mView->Redraw();
}
return false;
}
x -= Width - ViewportSize;
y -= Height - ViewportSize;
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;
}
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include "lc_math.h"
#include <bitset>
class View;
class lcViewCube
{
public:
lcViewCube(View* View);
void Draw();
bool OnMouseMove();
bool OnLeftButtonUp();
protected:
lcMatrix44 GetViewMatrix() const;
lcMatrix44 GetProjectionMatrix() const;
View* mView;
lcVector3 mIntersection;
std::bitset<6> mIntersectionFlags;
};
+67
View File
@@ -239,6 +239,73 @@ void TexFont::PrintText(lcContext* Context, float Left, float Top, float Z, cons
delete[] Verts;
}
void TexFont::GetTriangles(const lcMatrix44& Transform, const char* Text, float* Buffer) const
{
float Width = 0.0f;
for (const char* ch = Text; *ch; ch++)
Width += mGlyphs[*ch].width;
float Left = -Width / 2.0f;
float Top = mFontHeight / 2.0f;
float Z = 0.0f;
while (*Text)
{
int ch = *Text;
lcVector3 Points[4] =
{
lcVector3(Left, Top, Z),
lcVector3(Left, Top - mFontHeight, Z),
lcVector3(Left + mGlyphs[ch].width, Top - mFontHeight, Z),
lcVector3(Left + mGlyphs[ch].width, Top, Z),
};
for (int PointIdx = 0; PointIdx < 4; PointIdx++)
Points[PointIdx] = lcMul31(Points[PointIdx], Transform);
*Buffer++ = Points[0].x;
*Buffer++ = Points[0].y;
*Buffer++ = Points[0].z;
*Buffer++ = mGlyphs[ch].left;
*Buffer++ = mGlyphs[ch].top;
*Buffer++ = Points[1].x;
*Buffer++ = Points[1].y;
*Buffer++ = Points[1].z;
*Buffer++ = mGlyphs[ch].left;
*Buffer++ = mGlyphs[ch].bottom;
*Buffer++ = Points[2].x;
*Buffer++ = Points[2].y;
*Buffer++ = Points[2].z;
*Buffer++ = mGlyphs[ch].right;
*Buffer++ = mGlyphs[ch].bottom;
*Buffer++ = Points[2].x;
*Buffer++ = Points[2].y;
*Buffer++ = Points[2].z;
*Buffer++ = mGlyphs[ch].right;
*Buffer++ = mGlyphs[ch].bottom;
*Buffer++ = Points[3].x;
*Buffer++ = Points[3].y;
*Buffer++ = Points[3].z;
*Buffer++ = mGlyphs[ch].right;
*Buffer++ = mGlyphs[ch].top;
*Buffer++ = Points[0].x;
*Buffer++ = Points[0].y;
*Buffer++ = Points[0].z;
*Buffer++ = mGlyphs[ch].left;
*Buffer++ = mGlyphs[ch].top;
Left += mGlyphs[ch].width;
Text++;
}
}
void TexFont::GetGlyphTriangles(float Left, float Top, float Z, int Glyph, float* Buffer) const
{
Left -= mGlyphs[Glyph].width / 2.0f;
+1
View File
@@ -20,6 +20,7 @@ public:
void Release();
void PrintText(lcContext* Context, float Left, float Top, float Z, const char* Text) const;
void GetTriangles(const lcMatrix44& Transform, const char* Text, float* Buffer) const;
void GetGlyphTriangles(float Left, float Top, float Z, int Glyph, float* Buffer) const;
void GetStringDimensions(int* cx, int* cy, const char* Text) const;
+21 -1
View File
@@ -13,6 +13,7 @@ lcVertexBuffer View::mRotateMoveVertexBuffer;
lcIndexBuffer View::mRotateMoveIndexBuffer;
View::View(lcModel* Model)
: mViewCube(this)
{
mModel = Model;
mActiveSubmodelInstance = nullptr;
@@ -314,6 +315,18 @@ void View::SetViewpoint(lcViewpoint Viewpoint)
gMainWindow->UpdateCurrentCamera(-1);
}
void View::SetViewpoint(const lcVector3& Position)
{
if (!mCamera || !mCamera->IsSimple())
mCamera = new lcCamera(true);
mCamera->SetViewpoint(Position);
ZoomExtents();
Redraw();
gMainWindow->UpdateCurrentCamera(-1);
}
void View::SetCameraAngles(float Latitude, float Longitude)
{
if (!mCamera || !mCamera->IsSimple())
@@ -855,6 +868,7 @@ void View::OnDraw()
else if (Tool == LC_TOOL_ROTATE_VIEW && mTrackButton == LC_TRACKBUTTON_NONE)
DrawRotateViewOverlay();
mViewCube.Draw();
DrawViewport();
}
@@ -1709,7 +1723,7 @@ void View::DrawAxes()
mContext->SetColor(0.0f, 0.0f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_LINES, 6, GL_UNSIGNED_SHORT, 0);
mContext->SetColor(0.8f, 0.0f, 0.0f, 1.0f),
mContext->SetColor(0.8f, 0.0f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, 6 * 2);
mContext->SetColor(0.0f, 0.8f, 0.0f, 1.0f);
mContext->DrawIndexedPrimitives(GL_TRIANGLES, 24, GL_UNSIGNED_SHORT, (6 + 24) * 2);
@@ -2756,6 +2770,9 @@ void View::OnLeftButtonDown()
void View::OnLeftButtonUp()
{
StopTracking(mTrackButton == LC_TRACKBUTTON_LEFT);
if (mViewCube.OnLeftButtonUp())
return;
}
void View::OnLeftButtonDoubleClick()
@@ -2850,6 +2867,9 @@ void View::OnMouseMove()
if (mTrackButton == LC_TRACKBUTTON_NONE)
{
if (mViewCube.OnMouseMove())
return;
UpdateTrackTool();
if (mTrackTool == LC_TRACKTOOL_INSERT)
+4
View File
@@ -3,6 +3,8 @@
#include "lc_glwidget.h"
#include "camera.h"
#include "lc_scene.h"
#include "lc_viewcube.h"
#include "lc_commands.h"
enum lcTrackButton
{
@@ -109,6 +111,7 @@ public:
void SetCamera(const char* CameraName);
void SetCameraIndex(int Index);
void SetViewpoint(lcViewpoint Viewpoint);
void SetViewpoint(const lcVector3& Position);
void SetCameraAngles(float Latitude, float Longitude);
void SetDefaultCamera();
lcMatrix44 GetProjectionMatrix() const;
@@ -187,6 +190,7 @@ protected:
bool mHighlight;
QImage mRenderImage;
std::pair<lcFramebuffer, lcFramebuffer> mRenderFramebuffer;
lcViewCube mViewCube;
lcVertexBuffer mGridBuffer;
int mGridSettings[7];