Compare commits
5 commits
881d09f9bc
...
375d6c89b9
Author | SHA1 | Date | |
---|---|---|---|
375d6c89b9 | |||
4a50ed159b | |||
1095a8c33b | |||
dc9ae9d986 | |||
faf74cba0e |
6 changed files with 75 additions and 5 deletions
|
@ -42,9 +42,9 @@ glm::mat3 lookAt(Data::Vector3 position, Data::Vector3 lookAt, Data::Vector3 up)
|
|||
Data::Vector3 f = (lookAt - position).Unit(); // Forward/Look
|
||||
Data::Vector3 u = up.Unit(); // Up
|
||||
Data::Vector3 s = f.Cross(u).Unit(); // Right
|
||||
u = s.Cross(f);
|
||||
u = s.Cross(f).Unit();
|
||||
|
||||
return { s, u, f };
|
||||
return { s, u, -f };
|
||||
}
|
||||
|
||||
Data::CFrame::CFrame(Data::Vector3 position, Data::Vector3 lookAt, Data::Vector3 up)
|
||||
|
|
|
@ -51,6 +51,10 @@ Data::Vector3 Data::Vector3::operator -() const {
|
|||
return Data::Vector3(-this->X(), -this->Y(), -this->Z());
|
||||
}
|
||||
|
||||
bool Data::Vector3::operator ==(Data::Vector3 other) const {
|
||||
return this->X() == other.X() && this->Y() == other.Y() && this->Z() == other.Z();
|
||||
}
|
||||
|
||||
Data::Vector3 Data::Vector3::Cross(Data::Vector3 other) const {
|
||||
return glm::cross(this->vector, other.vector);
|
||||
}
|
||||
|
|
|
@ -47,5 +47,7 @@ namespace Data {
|
|||
Data::Vector3 operator +(Data::Vector3) const;
|
||||
Data::Vector3 operator -(Data::Vector3) const;
|
||||
Data::Vector3 operator -() const;
|
||||
|
||||
bool operator ==(Data::Vector3) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ Data::CFrame Handles::GetCFrameOfHandle(HandleFace face) {
|
|||
|
||||
Data::Vector3 handleOffset = this->worldMode ? ((Data::Vector3::ONE * 2.f) + adornee->lock()->GetAABB() * 0.5f) : Data::Vector3(2.f + adornee->lock()->size * 0.5f);
|
||||
Data::Vector3 handlePos = localFrame * (handleOffset * face.normal);
|
||||
Data::CFrame cframe(handlePos, handlePos + localFrame.Rotation() * face.normal, upAxis);
|
||||
Data::CFrame cframe(handlePos, handlePos + localFrame.Rotation() * -face.normal, upAxis);
|
||||
|
||||
return cframe;
|
||||
}
|
||||
|
|
|
@ -193,6 +193,7 @@ void renderHandles() {
|
|||
|
||||
glDepthMask(GL_TRUE);
|
||||
glCullFace(GL_BACK);
|
||||
glFrontFace(GL_CCW); // This is right... Probably.....
|
||||
|
||||
// Use shader
|
||||
handleShader->use();
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <glm/common.hpp>
|
||||
#include <glm/ext/matrix_projection.hpp>
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/ext/scalar_constants.hpp>
|
||||
#include <glm/ext/vector_float3.hpp>
|
||||
#include <glm/geometric.hpp>
|
||||
#include <glm/gtc/round.hpp>
|
||||
|
@ -77,6 +78,50 @@ void MainGLWidget::handleCameraRotate(QMouseEvent* evt) {
|
|||
// QCursor::setPos(lastMousePos);
|
||||
}
|
||||
|
||||
|
||||
static Data::Vector3 orthoVecs[6] {
|
||||
{1, 0, 0},
|
||||
{-1, 0, 0},
|
||||
{0, 1, 0},
|
||||
{0, -1, 0},
|
||||
{0, 0, 1},
|
||||
{0, 0, -1},
|
||||
};
|
||||
|
||||
// Snaps CFrame to the neareest 90 degree angle
|
||||
// https://gamedev.stackexchange.com/a/183342
|
||||
Data::CFrame snapCFrame(Data::CFrame frame) {
|
||||
Data::Vector3 closestVec1{0, 0, 0};
|
||||
float closest1 = 0.f;
|
||||
|
||||
// Primary vector
|
||||
for (Data::Vector3 vec : orthoVecs) {
|
||||
float closeness = glm::dot((glm::vec3)frame.LookVector(), (glm::vec3)vec);
|
||||
if (closeness > closest1) {
|
||||
closest1 = closeness;
|
||||
closestVec1 = vec;
|
||||
}
|
||||
}
|
||||
|
||||
Data::Vector3 closestVec2{0, 0, 0};
|
||||
float closest2 = 0.f;
|
||||
|
||||
// Second vector
|
||||
for (Data::Vector3 vec : orthoVecs) {
|
||||
// Guard against accidental linear dependency
|
||||
if (vec == closestVec1) continue;
|
||||
|
||||
float closeness = glm::dot((glm::vec3)frame.UpVector(), (glm::vec3)vec);
|
||||
if (closeness > closest2) {
|
||||
closest2 = closeness;
|
||||
closestVec2 = vec;
|
||||
}
|
||||
}
|
||||
|
||||
// Data::Vector3 thirdVec = closestVec1.Cross(closestVec2);
|
||||
return Data::CFrame(frame.Position(), frame.Position() + closestVec1, closestVec2);
|
||||
}
|
||||
|
||||
bool isMouseDragging = false;
|
||||
std::optional<std::weak_ptr<Part>> draggingObject;
|
||||
std::optional<HandleFace> draggingHandle;
|
||||
|
@ -91,9 +136,23 @@ void MainGLWidget::handleObjectDrag(QMouseEvent* evt) {
|
|||
});
|
||||
|
||||
if (!rayHit) return;
|
||||
|
||||
Data::Vector3 vec = rayHit->worldPoint;
|
||||
vec = vec + Data::Vector3(rpToGlm(rayHit->worldNormal) * draggingObject->lock()->size / 2.f);
|
||||
draggingObject->lock()->cframe = draggingObject->lock()->cframe.Rotation() + vec;
|
||||
Data::CFrame targetFrame = partFromBody(rayHit->body)->cframe;
|
||||
Data::Vector3 surfaceNormal = targetFrame.Inverse().Rotation() * rayHit->worldNormal;
|
||||
// The part being dragged's frame local to the hit target's frame, but without its position component
|
||||
Data::CFrame localFrame = (targetFrame.Inverse() * draggingObject->lock()->cframe).Rotation();
|
||||
|
||||
// Snap axis
|
||||
localFrame = snapCFrame(localFrame);
|
||||
|
||||
// Unsink the object
|
||||
// Get the normal of the surface relative to the part's frame, and get the size along that vector
|
||||
Data::Vector3 partOffset = localFrame * ((localFrame.Inverse() * rayHit->worldNormal) * draggingObject->lock()->size / 2);
|
||||
|
||||
Data::CFrame newFrame = targetFrame.Rotation() * localFrame;
|
||||
draggingObject->lock()->cframe = newFrame + vec + partOffset;
|
||||
|
||||
syncPartPhysics(draggingObject->lock());
|
||||
}
|
||||
|
||||
|
@ -156,6 +215,10 @@ void MainGLWidget::handleHandleDrag(QMouseEvent* evt) {
|
|||
// Find outwarwd difference
|
||||
localDiff = localDiff * glm::sign(draggingHandle->normal);
|
||||
|
||||
// Minimum size of 0.01f
|
||||
localDiff = glm::max(part->size + localDiff, 0.01f) - part->size;
|
||||
diff = frame * (localDiff * glm::sign(draggingHandle->normal));
|
||||
|
||||
// Add local difference to size
|
||||
part->size += localDiff;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue