Compare commits
No commits in common. "3bd0e77c8fbaf912af0e45531dcd9053266928a4" and "1a1db6926dafde46742ae1213e10b0fd89792085" have entirely different histories.
3bd0e77c8f
...
1a1db6926d
12 changed files with 93 additions and 312 deletions
1
.vscode/launch.json
vendored
1
.vscode/launch.json
vendored
|
|
@ -18,7 +18,6 @@
|
||||||
"program": "${workspaceFolder}/build/bin/editor",
|
"program": "${workspaceFolder}/build/bin/editor",
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
"preLaunchTask": "buildDebug"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
|
|
|
||||||
11
.vscode/tasks.json
vendored
11
.vscode/tasks.json
vendored
|
|
@ -1,11 +0,0 @@
|
||||||
{
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"label": "buildDebug",
|
|
||||||
"type": "process",
|
|
||||||
"command": "cmake",
|
|
||||||
"args": ["--build", "build", "-j16"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
// Project-local debug tasks
|
|
||||||
//
|
|
||||||
// For more documentation on how to configure debug tasks,
|
|
||||||
// see: https://zed.dev/docs/debugger
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"label": "Debug editor",
|
|
||||||
"build": {
|
|
||||||
"command": "cmake",
|
|
||||||
"args": ["--build", "build", "-j16"],
|
|
||||||
"cwd": "$ZED_WORKTREE_ROOT"
|
|
||||||
},
|
|
||||||
"program": "$ZED_WORKTREE_ROOT/build/bin/editor",
|
|
||||||
"request": "launch",
|
|
||||||
"adapter": "CodeLLDB"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
@ -57,8 +57,6 @@ set(SOURCES
|
||||||
src/rendering/font.h
|
src/rendering/font.h
|
||||||
src/rendering/defaultmeshes.h
|
src/rendering/defaultmeshes.h
|
||||||
src/rendering/texture3d.cpp
|
src/rendering/texture3d.cpp
|
||||||
src/rendering/frustum.h
|
|
||||||
src/rendering/frustum.cpp
|
|
||||||
src/physics/world.h
|
src/physics/world.h
|
||||||
src/physics/world.cpp
|
src/physics/world.cpp
|
||||||
src/logger.cpp
|
src/logger.cpp
|
||||||
|
|
|
||||||
|
|
@ -67,18 +67,3 @@ void Workspace::PhysicsStep(float deltaTime) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Instance>> Workspace::CastFrustum(Frustum frustum) {
|
|
||||||
std::vector<std::shared_ptr<Instance>> parts;
|
|
||||||
|
|
||||||
for (auto it = GetDescendantsStart(); it != GetDescendantsEnd(); it++) {
|
|
||||||
if (!it->IsA<BasePart>()) continue;
|
|
||||||
std::shared_ptr<BasePart> part = std::dynamic_pointer_cast<BasePart>(*it);
|
|
||||||
|
|
||||||
if (!part->locked && frustum.checkAABB(part->position(), part->GetAABB())) {
|
|
||||||
parts.push_back(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return parts;
|
|
||||||
}
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
#include "objects/base/service.h"
|
#include "objects/base/service.h"
|
||||||
#include "objects/joint/jointinstance.h"
|
#include "objects/joint/jointinstance.h"
|
||||||
#include "physics/world.h"
|
#include "physics/world.h"
|
||||||
#include "rendering/frustum.h"
|
|
||||||
#include <glm/ext/vector_float3.hpp>
|
#include <glm/ext/vector_float3.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
@ -62,5 +61,4 @@ public:
|
||||||
|
|
||||||
void PhysicsStep(float deltaTime);
|
void PhysicsStep(float deltaTime);
|
||||||
inline std::optional<const RaycastResult> CastRayNearest(glm::vec3 point, glm::vec3 rotation, float maxLength, std::optional<RaycastFilter> filter = std::nullopt, unsigned short categoryMaskBits = 0xFFFF) { return physicsWorld->castRay(point, rotation, maxLength, filter, categoryMaskBits); }
|
inline std::optional<const RaycastResult> CastRayNearest(glm::vec3 point, glm::vec3 rotation, float maxLength, std::optional<RaycastFilter> filter = std::nullopt, unsigned short categoryMaskBits = 0xFFFF) { return physicsWorld->castRay(point, rotation, maxLength, filter, categoryMaskBits); }
|
||||||
std::vector<std::shared_ptr<Instance>> CastFrustum(Frustum frustum);
|
|
||||||
};
|
};
|
||||||
|
|
@ -144,7 +144,6 @@ void drawText(std::shared_ptr<Font> font, std::string text, float x, float y, fl
|
||||||
// activate corresponding render state
|
// activate corresponding render state
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // TODO: Figure out why when changed to GL_ONE this causes graphical errors
|
|
||||||
|
|
||||||
fontShader->use();
|
fontShader->use();
|
||||||
fontShader->set("textColor", color);
|
fontShader->set("textColor", color);
|
||||||
|
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
#include "frustum.h"
|
|
||||||
#include "datatypes/vector.h"
|
|
||||||
#include <glm/ext/matrix_clip_space.hpp>
|
|
||||||
|
|
||||||
// https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling
|
|
||||||
|
|
||||||
// https://stackoverflow.com/q/66227192/16255372
|
|
||||||
FrustumPlane::FrustumPlane(Vector3 point, Vector3 normal) : normal(normal.Unit()), distance(normal.Unit().Dot(point)) {}
|
|
||||||
|
|
||||||
Frustum::Frustum() {}
|
|
||||||
|
|
||||||
Frustum::Frustum(const Camera cam, float aspect, float fovY, float zNear, float zFar) {
|
|
||||||
const float halfVSide = zFar * tanf(fovY * 0.5f);
|
|
||||||
const float halfHSide = halfVSide * aspect;
|
|
||||||
const glm::vec3 frontMultFar = zFar * -cam.cameraFront;
|
|
||||||
|
|
||||||
// Don't forget to normalize!!!
|
|
||||||
glm::vec3 camRight = glm::normalize(glm::cross(cam.cameraFront, cam.cameraUp)); // Technically this is left, but whatever
|
|
||||||
glm::vec3 trueCamUp = glm::cross(-cam.cameraFront, camRight);
|
|
||||||
near = { cam.cameraPos + zNear * -cam.cameraFront, -cam.cameraFront };
|
|
||||||
far = { cam.cameraPos + frontMultFar, cam.cameraFront };
|
|
||||||
right = { cam.cameraPos,
|
|
||||||
glm::cross(frontMultFar - camRight * halfHSide, trueCamUp) };
|
|
||||||
left = { cam.cameraPos,
|
|
||||||
glm::cross(trueCamUp,frontMultFar + camRight * halfHSide) };
|
|
||||||
top = { cam.cameraPos,
|
|
||||||
glm::cross(camRight, frontMultFar - trueCamUp * halfVSide) };
|
|
||||||
bottom = { cam.cameraPos,
|
|
||||||
glm::cross(frontMultFar + trueCamUp * halfVSide, camRight) };
|
|
||||||
}
|
|
||||||
|
|
||||||
Frustum Frustum::createSliced(const Camera cam, float width, float height, float left, float right, float top, float bottom, float fovY, float zNear, float zFar) {
|
|
||||||
Frustum frustum;
|
|
||||||
|
|
||||||
float aspect = width / height;
|
|
||||||
float halfVSide = zFar * tanf(fovY * 0.5f);
|
|
||||||
float halfHSide = halfVSide * aspect;
|
|
||||||
const glm::vec3 frontMultFar = zFar * -cam.cameraFront;
|
|
||||||
|
|
||||||
float leftSide = -halfHSide * (left / width * 2 - 1);
|
|
||||||
float rightSide = halfHSide * (right / width * 2 - 1);
|
|
||||||
float topSide = -halfVSide * (top / height * 2 - 1);
|
|
||||||
float bottomSide = halfVSide * (bottom / height * 2 - 1);
|
|
||||||
|
|
||||||
// Don't forget to normalize!!!
|
|
||||||
glm::vec3 camRight = glm::normalize(glm::cross(cam.cameraFront, cam.cameraUp)); // Technically this is left, but whatever
|
|
||||||
glm::vec3 trueCamUp = glm::cross(-cam.cameraFront, camRight);
|
|
||||||
frustum.near = { cam.cameraPos + zNear * -cam.cameraFront, -cam.cameraFront };
|
|
||||||
frustum.far = { cam.cameraPos + frontMultFar, cam.cameraFront };
|
|
||||||
frustum.right = { cam.cameraPos,
|
|
||||||
glm::cross(frontMultFar - camRight * rightSide, trueCamUp) };
|
|
||||||
frustum.left = { cam.cameraPos,
|
|
||||||
glm::cross(trueCamUp,frontMultFar + camRight * leftSide) };
|
|
||||||
frustum.top = { cam.cameraPos,
|
|
||||||
glm::cross(camRight, frontMultFar - trueCamUp * topSide) };
|
|
||||||
frustum.bottom = { cam.cameraPos,
|
|
||||||
glm::cross(frontMultFar + trueCamUp * bottomSide, camRight) };
|
|
||||||
return frustum;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FrustumPlane::checkPointForward(Vector3 point) {
|
|
||||||
return (normal.Dot(point) - distance) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FrustumPlane::checkAABBForward(Vector3 center, Vector3 extents) {
|
|
||||||
// Not entirely sure how this algorithm works... but hey, when has that ever stopped me?
|
|
||||||
|
|
||||||
// https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling
|
|
||||||
// https://gdbooks.gitbooks.io/3dcollisions/content/Chapter2/static_aabb_plane.html
|
|
||||||
// Compute the projection interval radius of b onto L(t) = b.c + t * p.n
|
|
||||||
extents = extents * 0.5f;
|
|
||||||
const float r = extents.X() * std::abs(normal.X()) +
|
|
||||||
extents.Y() * std::abs(normal.Y()) + extents.Z() * std::abs(normal.Z());
|
|
||||||
|
|
||||||
return -r <= (normal.Dot(center) - distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Frustum::checkPoint(Vector3 point) {
|
|
||||||
return true
|
|
||||||
// TODO: Near and far are broken for some reason
|
|
||||||
// && near.checkPointForward(point)
|
|
||||||
// && far.checkPointForward(point)
|
|
||||||
&& left.checkPointForward(point)
|
|
||||||
&& right.checkPointForward(point)
|
|
||||||
&& top.checkPointForward(point)
|
|
||||||
&& bottom.checkPointForward(point)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Frustum::checkAABB(Vector3 center, Vector3 extents) {
|
|
||||||
return true
|
|
||||||
// TODO: Near and far are broken for some reason
|
|
||||||
// && near.checkAABBForward(center, extents)
|
|
||||||
// && far.checkAABBForward(center, extents)
|
|
||||||
&& left.checkAABBForward(center, extents)
|
|
||||||
&& right.checkAABBForward(center, extents)
|
|
||||||
&& top.checkAABBForward(center, extents)
|
|
||||||
&& bottom.checkAABBForward(center, extents)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "camera.h"
|
|
||||||
#include "datatypes/vector.h"
|
|
||||||
|
|
||||||
// https://learnopengl.com/Guest-Articles/2021/Scene/Frustum-Culling
|
|
||||||
|
|
||||||
struct FrustumPlane {
|
|
||||||
Vector3 normal;
|
|
||||||
float distance; // leastPoint = normal * distance
|
|
||||||
// leastPoint is the closest point to (0,0)
|
|
||||||
|
|
||||||
FrustumPlane(Vector3 point, Vector3 normal);
|
|
||||||
FrustumPlane() = default;
|
|
||||||
|
|
||||||
bool checkPointForward(Vector3);
|
|
||||||
bool checkAABBForward(Vector3 center, Vector3 extents);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Frustum {
|
|
||||||
FrustumPlane near;
|
|
||||||
FrustumPlane far;
|
|
||||||
FrustumPlane left;
|
|
||||||
FrustumPlane right;
|
|
||||||
FrustumPlane top;
|
|
||||||
FrustumPlane bottom;
|
|
||||||
|
|
||||||
Frustum(const Camera cam, float aspect, float fovY, float zNear, float zFar);
|
|
||||||
static Frustum createSliced(const Camera cam, float width, float height, float left, float right, float top, float bottom, float fovY, float zNear, float zFar);
|
|
||||||
bool checkPoint(Vector3);
|
|
||||||
bool checkAABB(Vector3 center, Vector3 extents);
|
|
||||||
|
|
||||||
private:
|
|
||||||
Frustum();
|
|
||||||
};
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
#include <glad/gl.h>
|
#include <glad/gl.h>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
#include <glm/ext/matrix_clip_space.hpp>
|
#include <glm/ext/matrix_clip_space.hpp>
|
||||||
#include <glm/ext/matrix_float4x4.hpp>
|
#include <glm/ext/matrix_float4x4.hpp>
|
||||||
|
|
@ -77,6 +79,8 @@ void renderInit(int width, int height) {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glEnable(GL_MULTISAMPLE);
|
glEnable(GL_MULTISAMPLE);
|
||||||
glFrontFace(GL_CW);
|
glFrontFace(GL_CW);
|
||||||
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
debugFontTexture = new Texture("assets/textures/debugfnt.bmp", GL_RGB);
|
debugFontTexture = new Texture("assets/textures/debugfnt.bmp", GL_RGB);
|
||||||
|
|
||||||
|
|
@ -166,7 +170,7 @@ void renderParts() {
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
// Use shader
|
// Use shader
|
||||||
shader->use();
|
shader->use();
|
||||||
|
|
@ -230,7 +234,7 @@ void renderSurfaceExtras() {
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
// Use shader
|
// Use shader
|
||||||
ghostShader->use();
|
ghostShader->use();
|
||||||
|
|
@ -354,7 +358,7 @@ void renderAABB() {
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
glFrontFace(GL_CW);
|
glFrontFace(GL_CW);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
// Use shader
|
// Use shader
|
||||||
ghostShader->use();
|
ghostShader->use();
|
||||||
|
|
@ -393,7 +397,7 @@ void renderWireframe() {
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
glFrontFace(GL_CW);
|
glFrontFace(GL_CW);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
|
||||||
|
|
||||||
// Use shader
|
// Use shader
|
||||||
|
|
@ -433,7 +437,7 @@ void renderOutlines() {
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
// Use shader
|
// Use shader
|
||||||
outlineShader->use();
|
outlineShader->use();
|
||||||
|
|
@ -496,7 +500,7 @@ void renderSelectionAssembly() {
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
PartAssembly selectionAssembly = PartAssembly::FromSelection(gDataModel->GetService<Selection>());
|
PartAssembly selectionAssembly = PartAssembly::FromSelection(gDataModel->GetService<Selection>());
|
||||||
|
|
||||||
|
|
@ -534,7 +538,7 @@ void renderRotationArcs() {
|
||||||
glCullFace(GL_BACK);
|
glCullFace(GL_BACK);
|
||||||
glFrontFace(GL_CW);
|
glFrontFace(GL_CW);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
// Use shader
|
// Use shader
|
||||||
handleShader->use();
|
handleShader->use();
|
||||||
|
|
@ -632,6 +636,7 @@ void renderMessages() {
|
||||||
// glEnable(GL_DEPTH_TEST);
|
// glEnable(GL_DEPTH_TEST);
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
// glEnable(GL_BLEND);
|
// glEnable(GL_BLEND);
|
||||||
|
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
for (auto it = gWorkspace()->GetDescendantsStart(); it != gWorkspace()->GetDescendantsEnd(); it++) {
|
for (auto it = gWorkspace()->GetDescendantsStart(); it != gWorkspace()->GetDescendantsEnd(); it++) {
|
||||||
if (!it->IsA<Message>()) continue;
|
if (!it->IsA<Message>()) continue;
|
||||||
|
|
@ -648,7 +653,7 @@ void renderMessages() {
|
||||||
if (message->text == "") continue;
|
if (message->text == "") continue;
|
||||||
|
|
||||||
float strokedTextWidth = calcTextWidth(sansSerif, message->text, true);
|
float strokedTextWidth = calcTextWidth(sansSerif, message->text, true);
|
||||||
drawRect(0, 0, viewportWidth, viewportHeight, glm::vec4(0.5, 0.5, 0.5, 0.5));
|
drawRect(0, 0, viewportWidth, viewportHeight, glm::vec4(0.5));
|
||||||
drawText(sansSerif, message->text, ((float)viewportWidth - textWidth) / 2, ((float)viewportHeight - sansSerif->height) / 2, 1.f, glm::vec3(0), true);
|
drawText(sansSerif, message->text, ((float)viewportWidth - textWidth) / 2, ((float)viewportHeight - sansSerif->height) / 2, 1.f, glm::vec3(0), true);
|
||||||
drawText(sansSerif, message->text, ((float)viewportWidth - strokedTextWidth) / 2, ((float)viewportHeight - sansSerif->height) / 2, 1.f, glm::vec3(1), false);
|
drawText(sansSerif, message->text, ((float)viewportWidth - strokedTextWidth) / 2, ((float)viewportHeight - sansSerif->height) / 2, 1.f, glm::vec3(1), false);
|
||||||
}
|
}
|
||||||
|
|
@ -661,8 +666,6 @@ void render() {
|
||||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
// For some reason this is unset by QPainter, so we override it here
|
|
||||||
glEnable(GL_MULTISAMPLE);
|
|
||||||
|
|
||||||
renderSkyBox();
|
renderSkyBox();
|
||||||
renderHandles();
|
renderHandles();
|
||||||
|
|
@ -681,25 +684,11 @@ void render() {
|
||||||
// renderAABB();
|
// renderAABB();
|
||||||
|
|
||||||
renderTime = tu_clock_micros() - startTime;
|
renderTime = tu_clock_micros() - startTime;
|
||||||
|
|
||||||
identityShader->use();
|
|
||||||
identityShader->set("aColor", glm::vec4(1,0,0,1));
|
|
||||||
// Unbinding both is important or else it will mess up QPainter
|
|
||||||
// https://stackoverflow.com/a/47417780/16255372
|
|
||||||
glBindVertexArray(0);
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER,0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawRect(int x, int y, int width, int height, glm::vec4 color) {
|
void drawRect(int x, int y, int width, int height, glm::vec4 color) {
|
||||||
// GL_CULL_FACE has to be disabled as we are flipping the order of the vertices here, besides we don't really care about it
|
// GL_CULL_FACE has to be disabled as we are flipping the order of the vertices here, besides we don't really care about it
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
// Multiply color
|
|
||||||
float a = color.a;
|
|
||||||
color *= a;
|
|
||||||
color.a = a;
|
|
||||||
|
|
||||||
glm::mat4 model(1.0f); // Same applies to this VV
|
glm::mat4 model(1.0f); // Same applies to this VV
|
||||||
// Make sure to cast these to floats, as mat4<i> is a different type that is not compatible
|
// Make sure to cast these to floats, as mat4<i> is a different type that is not compatible
|
||||||
glm::mat4 proj = glm::ortho(0.f, (float)viewportWidth, (float)viewportHeight, 0.f, -1.f, 1.f);
|
glm::mat4 proj = glm::ortho(0.f, (float)viewportWidth, (float)viewportHeight, 0.f, -1.f, 1.f);
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,29 @@
|
||||||
#include <glad/gl.h>
|
#include <glad/gl.h>
|
||||||
|
#include <glm/common.hpp>
|
||||||
|
#include <glm/vector_relational.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <miniaudio.h>
|
#include <miniaudio.h>
|
||||||
#include <qcursorconstraints.h>
|
#include <qcursorconstraints.h>
|
||||||
#include <QPainter>
|
#include <qnamespace.h>
|
||||||
|
#include <qguiapplication.h>
|
||||||
|
#include <string>
|
||||||
#include "./ui_mainwindow.h"
|
#include "./ui_mainwindow.h"
|
||||||
#include "common.h"
|
#include "mainglwidget.h"
|
||||||
|
#include "datatypes/vector.h"
|
||||||
|
#include "enum/surface.h"
|
||||||
|
#include "handles.h"
|
||||||
|
#include "logger.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "common.h"
|
||||||
#include "math_helper.h"
|
#include "math_helper.h"
|
||||||
|
#include "objects/base/instance.h"
|
||||||
|
#include "objects/pvinstance.h"
|
||||||
#include "objects/service/selection.h"
|
#include "objects/service/selection.h"
|
||||||
#include "partassembly.h"
|
#include "partassembly.h"
|
||||||
#include "rendering/renderer.h"
|
#include "rendering/renderer.h"
|
||||||
#include "mainglwidget.h"
|
#include "rendering/shader.h"
|
||||||
|
#include "datatypes/variant.h"
|
||||||
|
#include "undohistory.h"
|
||||||
|
|
||||||
#define PI 3.14159
|
#define PI 3.14159
|
||||||
#define M_mainWindow dynamic_cast<MainWindow*>(window())
|
#define M_mainWindow dynamic_cast<MainWindow*>(window())
|
||||||
|
|
@ -56,16 +68,9 @@ glm::vec2 secondPoint;
|
||||||
|
|
||||||
extern std::weak_ptr<BasePart> draggingObject;
|
extern std::weak_ptr<BasePart> draggingObject;
|
||||||
extern std::optional<HandleFace> draggingHandle;
|
extern std::optional<HandleFace> draggingHandle;
|
||||||
|
extern Shader* shader;
|
||||||
void MainGLWidget::paintGL() {
|
void MainGLWidget::paintGL() {
|
||||||
QPainter painter(this);
|
|
||||||
|
|
||||||
painter.beginNativePainting();
|
|
||||||
::render();
|
::render();
|
||||||
painter.endNativePainting();
|
|
||||||
|
|
||||||
painter.setPen(QColor(200, 200, 200));
|
|
||||||
painter.drawRect(selectionLasso);
|
|
||||||
painter.end();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMouseRightDragging = false;
|
bool isMouseRightDragging = false;
|
||||||
|
|
@ -321,7 +326,7 @@ std::optional<HandleFace> MainGLWidget::raycastHandle(glm::vec3 pointDir) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainGLWidget::handleCursorChange(QMouseEvent* evt) {
|
void MainGLWidget::handleCursorChange(QMouseEvent* evt) {
|
||||||
if (isMouseRightDragging || selectionLasso != QRect{0,0,0,0}) return; // Don't change the cursor while it is intentionally blank
|
if (isMouseRightDragging) return; // Don't change the cursor while it is intentionally blank
|
||||||
QPoint position = evt->pos();
|
QPoint position = evt->pos();
|
||||||
|
|
||||||
glm::vec3 pointDir = camera.getScreenDirection(glm::vec2(position.x(), position.y()), glm::vec2(width(), height()));
|
glm::vec3 pointDir = camera.getScreenDirection(glm::vec2(position.x(), position.y()), glm::vec2(width(), height()));
|
||||||
|
|
@ -364,85 +369,6 @@ void MainGLWidget::mouseMoveEvent(QMouseEvent* evt) {
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selectionLasso != QRect {0,0,0,0}) {
|
|
||||||
selectionLasso = {selectionLasso.topLeft(), evt->pos()};
|
|
||||||
|
|
||||||
float left = std::min(selectionLasso.left(), selectionLasso.right());
|
|
||||||
float right = std::max(selectionLasso.left(), selectionLasso.right());
|
|
||||||
float top = std::min(selectionLasso.top(), selectionLasso.bottom());
|
|
||||||
float bottom = std::max(selectionLasso.top(), selectionLasso.bottom());
|
|
||||||
|
|
||||||
Frustum selectionFrustum = Frustum::createSliced(camera, width(), height(), left, right, top, bottom, glm::radians(45.f), 0.1f, 1000.0f);
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Instance>> castedParts = gWorkspace()->CastFrustum(selectionFrustum);
|
|
||||||
gDataModel->GetService<Selection>()->Set(castedParts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MainGLWidget::handlePartClick(QMouseEvent* evt) {
|
|
||||||
QPoint position = evt->pos();
|
|
||||||
glm::vec3 pointDir = camera.getScreenDirection(glm::vec2(position.x(), position.y()), glm::vec2(width(), height()));
|
|
||||||
|
|
||||||
// raycast part
|
|
||||||
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
|
|
||||||
std::optional<const RaycastResult> rayHit = gWorkspace()->CastRayNearest(camera.cameraPos, pointDir, 50000);
|
|
||||||
if (!rayHit || !rayHit->hitPart) { selection->Set({}); return false; }
|
|
||||||
std::shared_ptr<BasePart> part = rayHit->hitPart;
|
|
||||||
if (part->locked) { selection->Set({}); return false; }
|
|
||||||
|
|
||||||
std::shared_ptr<PVInstance> selObject = part;
|
|
||||||
|
|
||||||
// Traverse to the root model
|
|
||||||
if (~evt->modifiers() & Qt::AltModifier) {
|
|
||||||
nullable std::shared_ptr<Instance> nextParent = selObject->GetParent();
|
|
||||||
while (nextParent && nextParent->IsA("Model")) {
|
|
||||||
selObject = std::dynamic_pointer_cast<PVInstance>(nextParent); nextParent = selObject->GetParent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
initialAssembly = PartAssembly::FromSelection({selObject});
|
|
||||||
initialFrame = initialAssembly.assemblyOrigin();
|
|
||||||
initialHitPos = rayHit->worldPoint;
|
|
||||||
initialHitNormal = rayHit->worldNormal;
|
|
||||||
|
|
||||||
// Handle surface tool
|
|
||||||
if (mainWindow()->selectedTool >= TOOL_SMOOTH) {
|
|
||||||
Vector3 localNormal = part->cframe.Inverse().Rotation() * rayHit->worldNormal;
|
|
||||||
NormalId face = faceFromNormal(localNormal);
|
|
||||||
SurfaceType surface = SurfaceType(mainWindow()->selectedTool - TOOL_SMOOTH);
|
|
||||||
std::string surfacePropertyName = EnumType::NormalId.FromValue(face)->Name() + "Surface";
|
|
||||||
|
|
||||||
// Get old surface and set new surface
|
|
||||||
EnumItem newSurface = EnumType::SurfaceType.FromValue((int)surface).value();
|
|
||||||
EnumItem oldSurface = part->GetProperty(surfacePropertyName).expect().get<EnumItem>();
|
|
||||||
part->SetProperty(surfacePropertyName, newSurface).expect();
|
|
||||||
|
|
||||||
M_mainWindow->undoManager.PushState({UndoStatePropertyChanged { part, surfacePropertyName, oldSurface, newSurface }});
|
|
||||||
|
|
||||||
if (mainWindow()->editSoundEffects && QFile::exists("./assets/excluded/electronicpingshort.wav"))
|
|
||||||
playSound("./assets/excluded/electronicpingshort.wav");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//part.selected = true;
|
|
||||||
isMouseDragging = true;
|
|
||||||
draggingObject = part;
|
|
||||||
initialTransforms = PartAssembly::FromSelection({part}).GetCurrentTransforms();
|
|
||||||
if (evt->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier)) {
|
|
||||||
auto sel = selection->Get();
|
|
||||||
if (std::find(sel.begin(), sel.end(), selObject) == sel.end())
|
|
||||||
selection->Add({ selObject });
|
|
||||||
else
|
|
||||||
selection->Remove({ selObject });
|
|
||||||
} else {
|
|
||||||
selection->Set({ selObject });
|
|
||||||
}
|
|
||||||
// Disable bit so that we can ignore the part while raycasting
|
|
||||||
// part->rigidBody->getCollider(0)->setCollisionCategoryBits(0b10);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
|
void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
|
||||||
|
|
@ -474,9 +400,63 @@ void MainGLWidget::mousePressEvent(QMouseEvent* evt) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (handlePartClick(evt)) return;
|
// raycast part
|
||||||
|
std::shared_ptr<Selection> selection = gDataModel->GetService<Selection>();
|
||||||
|
std::optional<const RaycastResult> rayHit = gWorkspace()->CastRayNearest(camera.cameraPos, pointDir, 50000);
|
||||||
|
if (!rayHit || !rayHit->hitPart) { selection->Set({}); return; }
|
||||||
|
std::shared_ptr<BasePart> part = rayHit->hitPart;
|
||||||
|
if (part->locked) { selection->Set({}); return; }
|
||||||
|
|
||||||
selectionLasso = {position, QSize {0, 0}};
|
std::shared_ptr<PVInstance> selObject = part;
|
||||||
|
|
||||||
|
// Traverse to the root model
|
||||||
|
if (~evt->modifiers() & Qt::AltModifier) {
|
||||||
|
nullable std::shared_ptr<Instance> nextParent = selObject->GetParent();
|
||||||
|
while (nextParent && nextParent->IsA("Model")) {
|
||||||
|
selObject = std::dynamic_pointer_cast<PVInstance>(nextParent); nextParent = selObject->GetParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
initialAssembly = PartAssembly::FromSelection({selObject});
|
||||||
|
initialFrame = initialAssembly.assemblyOrigin();
|
||||||
|
initialHitPos = rayHit->worldPoint;
|
||||||
|
initialHitNormal = rayHit->worldNormal;
|
||||||
|
|
||||||
|
// Handle surface tool
|
||||||
|
if (mainWindow()->selectedTool >= TOOL_SMOOTH) {
|
||||||
|
Vector3 localNormal = part->cframe.Inverse().Rotation() * rayHit->worldNormal;
|
||||||
|
NormalId face = faceFromNormal(localNormal);
|
||||||
|
SurfaceType surface = SurfaceType(mainWindow()->selectedTool - TOOL_SMOOTH);
|
||||||
|
std::string surfacePropertyName = EnumType::NormalId.FromValue(face)->Name() + "Surface";
|
||||||
|
|
||||||
|
// Get old surface and set new surface
|
||||||
|
EnumItem newSurface = EnumType::SurfaceType.FromValue((int)surface).value();
|
||||||
|
EnumItem oldSurface = part->GetProperty(surfacePropertyName).expect().get<EnumItem>();
|
||||||
|
part->SetProperty(surfacePropertyName, newSurface).expect();
|
||||||
|
|
||||||
|
M_mainWindow->undoManager.PushState({UndoStatePropertyChanged { part, surfacePropertyName, oldSurface, newSurface }});
|
||||||
|
|
||||||
|
if (mainWindow()->editSoundEffects && QFile::exists("./assets/excluded/electronicpingshort.wav"))
|
||||||
|
playSound("./assets/excluded/electronicpingshort.wav");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//part.selected = true;
|
||||||
|
isMouseDragging = true;
|
||||||
|
draggingObject = part;
|
||||||
|
initialTransforms = PartAssembly::FromSelection({part}).GetCurrentTransforms();
|
||||||
|
if (evt->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier)) {
|
||||||
|
auto sel = selection->Get();
|
||||||
|
if (std::find(sel.begin(), sel.end(), selObject) == sel.end())
|
||||||
|
selection->Add({ selObject });
|
||||||
|
else
|
||||||
|
selection->Remove({ selObject });
|
||||||
|
} else {
|
||||||
|
selection->Set({ selObject });
|
||||||
|
}
|
||||||
|
// Disable bit so that we can ignore the part while raycasting
|
||||||
|
// part->rigidBody->getCollider(0)->setCollisionCategoryBits(0b10);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} default:
|
} default:
|
||||||
|
|
@ -491,7 +471,6 @@ void MainGLWidget::mouseReleaseEvent(QMouseEvent* evt) {
|
||||||
isMouseDragging = false;
|
isMouseDragging = false;
|
||||||
draggingObject = {};
|
draggingObject = {};
|
||||||
draggingHandle = std::nullopt;
|
draggingHandle = std::nullopt;
|
||||||
selectionLasso = {0,0,0,0};
|
|
||||||
setCursor(Qt::ArrowCursor);
|
setCursor(Qt::ArrowCursor);
|
||||||
|
|
||||||
if (!initialTransforms.empty()) {
|
if (!initialTransforms.empty()) {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
#ifndef MAINGLWIDGET_H
|
#ifndef MAINGLWIDGET_H
|
||||||
#define MAINGLWIDGET_H
|
#define MAINGLWIDGET_H
|
||||||
|
|
||||||
#include <glm/fwd.hpp>
|
#include "objects/part/part.h"
|
||||||
#include <memory>
|
#include "qevent.h"
|
||||||
#include <QEvent>
|
|
||||||
#include <QOpenGLWidget>
|
#include <QOpenGLWidget>
|
||||||
#include <QMenu>
|
#include <QWidget>
|
||||||
|
#include <memory>
|
||||||
|
#include <qmenu.h>
|
||||||
|
|
||||||
class BasePart;
|
|
||||||
class HandleFace;
|
class HandleFace;
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
|
|
||||||
|
|
@ -28,7 +28,6 @@ protected:
|
||||||
void handleLinearTransform(QMouseEvent* evt);
|
void handleLinearTransform(QMouseEvent* evt);
|
||||||
void handleRotationalTransform(QMouseEvent* evt);
|
void handleRotationalTransform(QMouseEvent* evt);
|
||||||
void handleCursorChange(QMouseEvent* evt);
|
void handleCursorChange(QMouseEvent* evt);
|
||||||
bool handlePartClick(QMouseEvent* evt);
|
|
||||||
void startLinearTransform(QMouseEvent* evt);
|
void startLinearTransform(QMouseEvent* evt);
|
||||||
std::optional<HandleFace> raycastHandle(glm::vec3 pointDir);
|
std::optional<HandleFace> raycastHandle(glm::vec3 pointDir);
|
||||||
|
|
||||||
|
|
@ -43,8 +42,6 @@ protected:
|
||||||
|
|
||||||
MainWindow* mainWindow();
|
MainWindow* mainWindow();
|
||||||
float snappingFactor();
|
float snappingFactor();
|
||||||
|
|
||||||
QRect selectionLasso;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAINGLWIDGET_H
|
#endif // MAINGLWIDGET_H
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue