From b92553f63e5d03aff24dfbd40693edb17ac092d6 Mon Sep 17 00:00:00 2001 From: ousnius Date: Sat, 8 Oct 2016 02:45:46 +0200 Subject: [PATCH] Added scaling knobs to the transform tool The center one is for uniform scalin. --- src/components/TweakBrush.cpp | 35 ++++++++----- src/components/TweakBrush.h | 2 +- src/program/OutfitStudio.cpp | 96 ++++++++++++++++++++++++----------- src/program/OutfitStudio.h | 20 +++++--- src/render/GLSurface.cpp | 62 ++++++++++++++++++++++ src/render/GLSurface.h | 5 +- 6 files changed, 168 insertions(+), 52 deletions(-) diff --git a/src/components/TweakBrush.cpp b/src/components/TweakBrush.cpp index 1cbd49ef..448fddfd 100644 --- a/src/components/TweakBrush.cpp +++ b/src/components/TweakBrush.cpp @@ -1079,17 +1079,6 @@ void TB_XForm::brushAction(mesh* m, TweakPickInfo& pickInfo, int* points, int nP dv.z *= pick.view.z; Matrix4 xform; - float dist = 0.0f; - if (fabs(dv.x) > EPSILON) { - dist = dv.x; - } - else if (fabs(dv.y) > EPSILON) { - dist = dv.y; - } - else if (fabs(dv.z) > EPSILON) { - dist = dv.z; - } - if (xformType == 0) { xform.Translate(dv * strength); @@ -1108,8 +1097,28 @@ void TB_XForm::brushAction(mesh* m, TweakPickInfo& pickInfo, int* points, int nP xform.PushTranslate(pick.center * -1.0f); } else if (xformType == 2) { - dist = fabs(1.0f + dist / 10.0f); - xform.Scale(dist, dist, dist); + Vector3 dist(1.0f, 1.0f, 1.0f); + if (fabs(dv.x) > EPSILON) + dist.x = fabs(1.0f + dv.x / 10.0f); + else if (fabs(dv.y) > EPSILON) + dist.y = fabs(1.0f + dv.y / 10.0f); + else if (fabs(dv.z) > EPSILON) + dist.z = fabs(1.0f + dv.z / 10.0f); + + xform.Scale(dist.x, dist.y, dist.z); + } + else if (xformType == 3) { + xform.PushTranslate(pick.center); + Vector3 a = pick.origin - pick.center; + Vector3 b = pickInfo.origin - pick.center; + Vector3 dist = a + b; + + float scale = (dist.x + dist.y) / 2.0f; + scale = fabs(1.0f + scale / 10.0f); + if (scale > EPSILON) + xform.PushScale(scale, scale, scale); + + xform.PushTranslate(pick.center * -1.0f); } Vector3 vs; diff --git a/src/components/TweakBrush.h b/src/components/TweakBrush.h index 2dcdf014..12cdb7f9 100644 --- a/src/components/TweakBrush.h +++ b/src/components/TweakBrush.h @@ -330,7 +330,7 @@ class TB_Move : public TweakBrush { class TB_XForm : public TweakBrush { TweakPickInfo pick; float d; // Plane dist, - int xformType; // 0 = Move, 1 = Rotate, 2 = Scale + int xformType; // 0 = Move, 1 = Rotate, 2 = Scale, 3 = Uniform Scale public: TB_XForm(); diff --git a/src/program/OutfitStudio.cpp b/src/program/OutfitStudio.cpp index 023a3d37..b2ba60ec 100644 --- a/src/program/OutfitStudio.cpp +++ b/src/program/OutfitStudio.cpp @@ -5555,12 +5555,6 @@ wxGLPanel::wxGLPanel(wxWindow* parent, const wxSize& size, const wxGLAttributes& bConnectedEdit = false; bGlobalBrushCollision = true; - XMoveMesh = nullptr; - YMoveMesh = nullptr; - ZMoveMesh = nullptr; - XRotateMesh = nullptr; - YRotateMesh = nullptr; - ZRotateMesh = nullptr; lastCenterDistance = 0.0f; strokeManager = &baseStrokes; @@ -5991,20 +5985,29 @@ bool wxGLPanel::StartTransform(const wxPoint& screenPos) { } } else if (mname.find("Scale") != string::npos) { - translateBrush.SetXFormType(2); - switch (mname[0]) { - case 'X': - tpi.view = Vector3(1.0f, 0.0f, 0.0f); - tpi.normal = Vector3(0.0f, 0.0f, 1.0f); - break; - case 'Y': - tpi.view = Vector3(0.0f, 1.0f, 0.0f); + if (mname.find("Uniform") == string::npos) { + translateBrush.SetXFormType(2); + switch (mname[0]) { + case 'X': + tpi.view = Vector3(1.0f, 0.0f, 0.0f); + tpi.normal = Vector3(0.0f, 0.0f, 1.0f); + break; + case 'Y': + tpi.view = Vector3(0.0f, 1.0f, 0.0f); + tpi.normal = Vector3(0.0f, 0.0f, 1.0f); + break; + case 'Z': + tpi.view = Vector3(0.0f, 0.0f, 1.0f); + tpi.normal = Vector3(1.0f, 0.0f, 0.0f); + break; + } + } + else { + translateBrush.SetXFormType(3); + gls.CollidePlane(screenPos.x, screenPos.y, tpi.origin, Vector3(1.0f, 0.0f, 0.0f), -tpi.center.x); + gls.CollidePlane(screenPos.x, screenPos.y, tpi.origin, Vector3(0.0f, 1.0f, 0.0f), -tpi.center.y); + gls.CollidePlane(screenPos.x, screenPos.y, tpi.origin, Vector3(0.0f, 0.0f, 1.0f), -tpi.center.z); tpi.normal = Vector3(0.0f, 0.0f, 1.0f); - break; - case 'Z': - tpi.view = Vector3(0.0f, 0.0f, 1.0f); - tpi.normal = Vector3(1.0f, 0.0f, 0.0f); - break; } } @@ -6019,6 +6022,10 @@ bool wxGLPanel::StartTransform(const wxPoint& screenPos) { XRotateMesh->bVisible = false; YRotateMesh->bVisible = false; ZRotateMesh->bVisible = false; + XScaleMesh->bVisible = false; + YScaleMesh->bVisible = false; + ZScaleMesh->bVisible = false; + ScaleUniformMesh->bVisible = false; hitMesh->bVisible = true; return true; } @@ -6158,20 +6165,22 @@ void wxGLPanel::ShowTransformTool(bool show, bool keepVisibility) { xformCenter.Zero(); if (show) { - bool XMoveVis = true; - bool YMoveVis = true; - bool ZMoveVis = true; - bool XRotateVis = true; - bool YRotateVis = true; - bool ZRotateVis = true; - - if (keepVisibility && XMoveMesh && YMoveMesh && ZMoveMesh && XRotateMesh && YRotateMesh && ZRotateMesh) { + bool XMoveVis = true, YMoveVis = true, ZMoveVis = true; + bool XRotateVis = true, YRotateVis = true, ZRotateVis = true; + bool XScaleVis = true, YScaleVis = true, ZScaleVis = true; + bool ScaleUniformVis = true; + + if (keepVisibility && XMoveMesh) { XMoveVis = XMoveMesh->bVisible; YMoveVis = YMoveMesh->bVisible; ZMoveVis = ZMoveMesh->bVisible; XRotateVis = XRotateMesh->bVisible; YRotateVis = YRotateMesh->bVisible; ZRotateVis = ZRotateMesh->bVisible; + XScaleVis = XScaleMesh->bVisible; + YScaleVis = YScaleMesh->bVisible; + ZScaleVis = ZScaleMesh->bVisible; + ScaleUniformVis = ScaleUniformMesh->bVisible; } XMoveMesh = gls.AddVis3dArrow(xformCenter, Vector3(1.0f, 0.0f, 0.0f), 0.04f, 0.15f, 1.75f, Vector3(1.0f, 0.0f, 0.0f), "XMoveMesh"); @@ -6182,6 +6191,11 @@ void wxGLPanel::ShowTransformTool(bool show, bool keepVisibility) { YRotateMesh = gls.AddVis3dRing(xformCenter, Vector3(0.0f, 1.0f, 0.0f), 1.25f, 0.04f, Vector3(0.0f, 1.0f, 0.0f), "YRotateMesh"); ZRotateMesh = gls.AddVis3dRing(xformCenter, Vector3(0.0f, 0.0f, 1.0f), 1.25f, 0.04f, Vector3(0.0f, 0.0f, 1.0f), "ZRotateMesh"); + XScaleMesh = gls.AddVis3dCube(xformCenter + Vector3(0.75f, 0.0f, 0.0f), Vector3(1.0f, 0.0f, 0.0f), 0.12f, Vector3(1.0f, 0.0f, 0.0f), "XScaleMesh"); + YScaleMesh = gls.AddVis3dCube(xformCenter + Vector3(0.0f, 0.75f, 0.0f), Vector3(0.0f, 1.0f, 0.0f), 0.12f, Vector3(0.0f, 1.0f, 0.0f), "YScaleMesh"); + ZScaleMesh = gls.AddVis3dCube(xformCenter + Vector3(0.0f, 0.0f, 0.75f), Vector3(0.0f, 0.0f, 1.0f), 0.12f, Vector3(0.0f, 0.0f, 1.0f), "ZScaleMesh"); + ScaleUniformMesh = gls.AddVis3dCube(xformCenter, Vector3(1.0f, 0.0f, 0.0f), 0.15f, Vector3(0.0f, 0.0f, 0.0f), "ScaleUniformMesh"); + lastCenterDistance = 0.0f; if (keepVisibility) { @@ -6191,16 +6205,24 @@ void wxGLPanel::ShowTransformTool(bool show, bool keepVisibility) { XRotateMesh->bVisible = XRotateVis; YRotateMesh->bVisible = YRotateVis; ZRotateMesh->bVisible = ZRotateVis; + XScaleMesh->bVisible = XScaleVis; + YScaleMesh->bVisible = YScaleVis; + ZScaleMesh->bVisible = ZScaleVis; + ScaleUniformMesh->bVisible = ScaleUniformVis; } } else { - if (XMoveMesh && YMoveMesh && ZMoveMesh && XRotateMesh && YRotateMesh && ZRotateMesh) { + if (XMoveMesh) { XMoveMesh->bVisible = false; YMoveMesh->bVisible = false; ZMoveMesh->bVisible = false; XRotateMesh->bVisible = false; YRotateMesh->bVisible = false; ZRotateMesh->bVisible = false; + XScaleMesh->bVisible = false; + YScaleMesh->bVisible = false; + ZScaleMesh->bVisible = false; + ScaleUniformMesh->bVisible = false; } } @@ -6212,7 +6234,7 @@ void wxGLPanel::UpdateTransformTool() { if (!transformMode) return; - if (!XMoveMesh || !YMoveMesh || !ZMoveMesh || !XRotateMesh || !YRotateMesh || !ZRotateMesh) + if (!XMoveMesh) return; Vector3 unprojected; @@ -6227,6 +6249,11 @@ void wxGLPanel::UpdateTransformTool() { XRotateMesh->ScaleVertices(xformCenter, factor); YRotateMesh->ScaleVertices(xformCenter, factor); ZRotateMesh->ScaleVertices(xformCenter, factor); + + XScaleMesh->ScaleVertices(xformCenter, factor); + YScaleMesh->ScaleVertices(xformCenter, factor); + ZScaleMesh->ScaleVertices(xformCenter, factor); + ScaleUniformMesh->ScaleVertices(xformCenter, factor); } lastCenterDistance = unprojected.DistanceTo(xformCenter) / 15.0f; @@ -6238,6 +6265,11 @@ void wxGLPanel::UpdateTransformTool() { XRotateMesh->ScaleVertices(xformCenter, lastCenterDistance); YRotateMesh->ScaleVertices(xformCenter, lastCenterDistance); ZRotateMesh->ScaleVertices(xformCenter, lastCenterDistance); + + XScaleMesh->ScaleVertices(xformCenter, lastCenterDistance); + YScaleMesh->ScaleVertices(xformCenter, lastCenterDistance); + ZScaleMesh->ScaleVertices(xformCenter, lastCenterDistance); + ScaleUniformMesh->ScaleVertices(xformCenter, lastCenterDistance); } void wxGLPanel::ShowVertexEdit(bool show) { @@ -6397,13 +6429,17 @@ void wxGLPanel::OnMouseMove(wxMouseEvent& event) { } if (transformMode && !isTransforming) { - if (XMoveMesh && YMoveMesh && ZMoveMesh && XRotateMesh && YRotateMesh && ZRotateMesh) { + if (XMoveMesh) { XMoveMesh->color = Vector3(1.0f, 0.0f, 0.0f); YMoveMesh->color = Vector3(0.0f, 1.0f, 0.0f); ZMoveMesh->color = Vector3(0.0f, 0.0f, 1.0f); XRotateMesh->color = Vector3(1.0f, 0.0f, 0.0f); YRotateMesh->color = Vector3(0.0f, 1.0f, 0.0f); ZRotateMesh->color = Vector3(0.0f, 0.0f, 1.0f); + XScaleMesh->color = Vector3(1.0f, 0.0f, 0.0f); + YScaleMesh->color = Vector3(0.0f, 1.0f, 0.0f); + ZScaleMesh->color = Vector3(0.0f, 0.0f, 1.0f); + ScaleUniformMesh->color = Vector3(0.0f, 0.0f, 0.0f); Vector3 outOrigin, outNormal; mesh* hitMesh = nullptr; diff --git a/src/program/OutfitStudio.h b/src/program/OutfitStudio.h index df25b958..e9ba62af 100644 --- a/src/program/OutfitStudio.h +++ b/src/program/OutfitStudio.h @@ -393,6 +393,10 @@ class wxGLPanel : public wxGLCanvas { XRotateMesh = nullptr; YRotateMesh = nullptr; ZRotateMesh = nullptr; + XScaleMesh = nullptr; + YScaleMesh = nullptr; + ZScaleMesh = nullptr; + ScaleUniformMesh = nullptr; gls.Cleanup(); } @@ -498,12 +502,16 @@ class wxGLPanel : public wxGLCanvas { TweakUndo* strokeManager; TweakUndo baseStrokes; - mesh* XMoveMesh; - mesh* YMoveMesh; - mesh* ZMoveMesh; - mesh* XRotateMesh; - mesh* YRotateMesh; - mesh* ZRotateMesh; + mesh* XMoveMesh = nullptr; + mesh* YMoveMesh = nullptr; + mesh* ZMoveMesh = nullptr; + mesh* XRotateMesh = nullptr; + mesh* YRotateMesh = nullptr; + mesh* ZRotateMesh = nullptr; + mesh* XScaleMesh = nullptr; + mesh* YScaleMesh = nullptr; + mesh* ZScaleMesh = nullptr; + mesh* ScaleUniformMesh = nullptr; Vector3 xformCenter; // Transform center for transform brushes (rotate, specifically cares about this) float lastCenterDistance; diff --git a/src/render/GLSurface.cpp b/src/render/GLSurface.cpp index 3225bb1c..029b2157 100644 --- a/src/render/GLSurface.cpp +++ b/src/render/GLSurface.cpp @@ -1237,6 +1237,68 @@ mesh* GLSurface::AddVis3dArrow(const Vector3& origin, const Vector3& direction, return m; } +mesh* GLSurface::AddVis3dCube(const Vector3& center, const Vector3& normal, float radius, const Vector3& color, const string& name) { + int meshID = GetOverlayID(name); + if (meshID >= 0) + delete overlays[meshID]; + else + meshID = -1; + + mesh* m = new mesh(); + + int nCubeVerts = 8; + int nCubeTris = 12; + m->nVerts = nCubeVerts; + m->nTris = nCubeTris; + m->nEdges = 0; + + m->verts = new Vector3[m->nVerts]; + m->tris = new Triangle[m->nTris]; + m->color = color; + m->shapeName = name; + m->rendermode = RenderMode::UnlitSolid; + m->material = GetPrimitiveMaterial(); + + Matrix4 mat; + mat.Align(Vector3(0.0f, 0.0f, 1.0f), normal); + mat.Scale(radius, radius, radius); + mat.Translate(center); + + m->verts[0] = mat * Vector3(-1.0f, -1.0f, 1.0f); + m->verts[1] = mat * Vector3(1.0f, -1.0f, 1.0f); + m->verts[2] = mat * Vector3(1.0f, 1.0f, 1.0f); + m->verts[3] = mat * Vector3(-1.0f, 1.0f, 1.0f); + m->verts[4] = mat * Vector3(-1.0f, -1.0f, -1.0f); + m->verts[5] = mat * Vector3(1.0f, -1.0f, -1.0f); + m->verts[6] = mat * Vector3(1.0f, 1.0f, -1.0f); + m->verts[7] = mat * Vector3(-1.0f, 1.0f, -1.0f); + + m->tris[0] = Triangle(0, 1, 2); + m->tris[1] = Triangle(2, 3, 0); + m->tris[2] = Triangle(1, 5, 6); + m->tris[3] = Triangle(6, 2, 1); + m->tris[4] = Triangle(7, 6, 5); + m->tris[5] = Triangle(5, 4, 7); + m->tris[6] = Triangle(4, 0, 3); + m->tris[7] = Triangle(3, 7, 4); + m->tris[8] = Triangle(4, 5, 1); + m->tris[9] = Triangle(1, 0, 4); + m->tris[10] = Triangle(3, 2, 6); + m->tris[11] = Triangle(6, 7, 3); + + m->CreateBuffers(); + + if (meshID >= 0) { + overlays[meshID] = m; + } + else { + namedOverlays[m->shapeName] = overlays.size(); + overlays.push_back(m); + meshID = overlays.size() - 1; + } + return m; +} + void GLSurface::Update(const string& shapeName, vector* vertices, vector* uvs, vector* changed) { int id = GetMeshID(shapeName); if (id < 0) diff --git a/src/render/GLSurface.h b/src/render/GLSurface.h index 20d4a7e0..c64f8d9e 100644 --- a/src/render/GLSurface.h +++ b/src/render/GLSurface.h @@ -242,8 +242,9 @@ class GLSurface { bool CollideOverlay(int ScreenX, int ScreenY, Vector3& outOrigin, Vector3& outNormal, mesh** hitMesh = nullptr, int* outFacet = nullptr, Vector3* inRayDir = 0, Vector3* inRayOrigin = 0); int AddVisCircle(const Vector3& center, const Vector3& normal, float radius, const string& name = "RingMesh"); - mesh* AddVis3dRing(const Vector3& center, const Vector3& normal, float holeRadius, float ringRadius, const Vector3& color, const string& name = "XRotateMesh"); - mesh* AddVis3dArrow(const Vector3& origin, const Vector3& direction, float stemRadius, float pointRadius, float length, const Vector3& color, const string& name = "XMoveMesh"); + mesh* AddVis3dRing(const Vector3& center, const Vector3& normal, float holeRadius, float ringRadius, const Vector3& color, const string& name); + mesh* AddVis3dArrow(const Vector3& origin, const Vector3& direction, float stemRadius, float pointRadius, float length, const Vector3& color, const string& name); + mesh* AddVis3dCube(const Vector3& center, const Vector3& normal, float radius, const Vector3& color, const string& name); mesh* AddVisPoint(const Vector3& p, const string& name = "PointMesh", const Vector3* color = nullptr); void AddMeshFromNif(NifFile* nif, string shapeName, Vector3* color = nullptr, bool smoothNormalSeams = true);