Compare commits
No commits in common. "3052b376e2ca30d64f0c3d29468abb647f39c792" and "6f66b9540e82540478727c9f1f706640f5b2cfb3" have entirely different histories.
3052b376e2
...
6f66b9540e
26 changed files with 58 additions and 386 deletions
|
@ -1,22 +0,0 @@
|
||||||
#version 330 core
|
|
||||||
|
|
||||||
out vec4 FragColor;
|
|
||||||
in vec3 vPos;
|
|
||||||
in vec2 vTexCoord;
|
|
||||||
|
|
||||||
uniform sampler2D fontTex;
|
|
||||||
uniform int charIndex;
|
|
||||||
|
|
||||||
// Main
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
int x = (charIndex-32) % 16;
|
|
||||||
int y = (charIndex-32) / 16;
|
|
||||||
|
|
||||||
float fx = float(x) / 16;
|
|
||||||
float fy = float(y) / 8;
|
|
||||||
|
|
||||||
vec4 color = texture(fontTex, vec2(fx, fy) + vTexCoord * vec2(1.f/32, 1.f/16));
|
|
||||||
FragColor = vec3(color) == vec3(0, 0, 0) ? vec4(0, 0, 0, 0) : color;
|
|
||||||
// FragColor = color;
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
#version 330 core
|
|
||||||
in vec3 aPos;
|
|
||||||
in vec2 aTexCoord;
|
|
||||||
|
|
||||||
out vec3 vPos;
|
|
||||||
out vec2 vTexCoord;
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
gl_Position = vec4(aPos, 1.0);
|
|
||||||
vPos = aPos;
|
|
||||||
vTexCoord = aTexCoord;
|
|
||||||
}
|
|
|
@ -4,10 +4,10 @@
|
||||||
|
|
||||||
out vec4 FragColor;
|
out vec4 FragColor;
|
||||||
|
|
||||||
uniform vec4 aColor;
|
uniform vec3 aColor;
|
||||||
|
|
||||||
// Main
|
// Main
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
FragColor = aColor;
|
FragColor = vec4(aColor, 1);
|
||||||
}
|
}
|
|
@ -1 +0,0 @@
|
||||||
debugfnt.bmp is Iosevka NFM Thin generated via CBFG
|
|
Binary file not shown.
Before Width: | Height: | Size: 192 KiB |
|
@ -20,6 +20,7 @@ void Rotate::buildJoint() {
|
||||||
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return;
|
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return;
|
||||||
|
|
||||||
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value();
|
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value();
|
||||||
|
if (!workspace->physicsWorld) return;
|
||||||
|
|
||||||
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
|
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
|
||||||
// used to be rather than specifying an anchor rotation, so whatever.
|
// used to be rather than specifying an anchor rotation, so whatever.
|
||||||
|
@ -28,7 +29,7 @@ void Rotate::buildJoint() {
|
||||||
workspace->SyncPartPhysics(part1.lock());
|
workspace->SyncPartPhysics(part1.lock());
|
||||||
// Do NOT use Abs() in this scenario. For some reason that breaks it
|
// Do NOT use Abs() in this scenario. For some reason that breaks it
|
||||||
rp::HingeJointInfo jointInfo(part0.lock()->rigidBody, part1.lock()->rigidBody, (part0.lock()->cframe * c0).Position(), -(part0.lock()->cframe * c0).LookVector().Unit());
|
rp::HingeJointInfo jointInfo(part0.lock()->rigidBody, part1.lock()->rigidBody, (part0.lock()->cframe * c0).Position(), -(part0.lock()->cframe * c0).LookVector().Unit());
|
||||||
this->joint = dynamic_cast<rp::HingeJoint*>(workspace->CreateJoint(jointInfo));
|
this->joint = dynamic_cast<rp::HingeJoint*>(workspace->physicsWorld->createJoint(jointInfo));
|
||||||
jointWorkspace = workspace;
|
jointWorkspace = workspace;
|
||||||
|
|
||||||
// part1.lock()->rigidBody->getCollider(0)->setCollideWithMaskBits(0b10);
|
// part1.lock()->rigidBody->getCollider(0)->setCollideWithMaskBits(0b10);
|
||||||
|
@ -40,8 +41,8 @@ void Rotate::buildJoint() {
|
||||||
// !!! REMINDER: This has to be called manually when parts are destroyed/removed from the workspace, or joints will linger
|
// !!! REMINDER: This has to be called manually when parts are destroyed/removed from the workspace, or joints will linger
|
||||||
void Rotate::breakJoint() {
|
void Rotate::breakJoint() {
|
||||||
// If the joint doesn't exist, or its workspace expired (not our problem anymore), then no need to do anything
|
// If the joint doesn't exist, or its workspace expired (not our problem anymore), then no need to do anything
|
||||||
if (!this->joint || jointWorkspace.expired()) return;
|
if (!this->joint || jointWorkspace.expired() || !jointWorkspace.lock()->physicsWorld) return;
|
||||||
|
|
||||||
jointWorkspace.lock()->DestroyJoint(this->joint);
|
jointWorkspace.lock()->physicsWorld->destroyJoint(this->joint);
|
||||||
this->joint = nullptr;
|
this->joint = nullptr;
|
||||||
}
|
}
|
|
@ -22,6 +22,7 @@ void RotateV::buildJoint() {
|
||||||
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return;
|
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return;
|
||||||
|
|
||||||
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value();
|
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value();
|
||||||
|
if (!workspace->physicsWorld) return;
|
||||||
|
|
||||||
|
|
||||||
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
|
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
|
||||||
|
@ -34,7 +35,7 @@ void RotateV::buildJoint() {
|
||||||
|
|
||||||
jointInfo.isCollisionEnabled = false;
|
jointInfo.isCollisionEnabled = false;
|
||||||
|
|
||||||
this->joint = dynamic_cast<rp::HingeJoint*>(workspace->CreateJoint(jointInfo));
|
this->joint = dynamic_cast<rp::HingeJoint*>(workspace->physicsWorld->createJoint(jointInfo));
|
||||||
jointWorkspace = workspace;
|
jointWorkspace = workspace;
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,8 +47,8 @@ void RotateV::buildJoint() {
|
||||||
|
|
||||||
void RotateV::breakJoint() {
|
void RotateV::breakJoint() {
|
||||||
// If the joint doesn't exist, or its workspace expired (not our problem anymore), then no need to do anything
|
// If the joint doesn't exist, or its workspace expired (not our problem anymore), then no need to do anything
|
||||||
if (!this->joint || jointWorkspace.expired()) return;
|
if (!this->joint || jointWorkspace.expired() || !jointWorkspace.lock()->physicsWorld) return;
|
||||||
|
|
||||||
jointWorkspace.lock()->DestroyJoint(this->joint);
|
jointWorkspace.lock()->physicsWorld->destroyJoint(this->joint);
|
||||||
this->joint = nullptr;
|
this->joint = nullptr;
|
||||||
}
|
}
|
|
@ -24,6 +24,7 @@ void Snap::buildJoint() {
|
||||||
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return;
|
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return;
|
||||||
|
|
||||||
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value();
|
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value();
|
||||||
|
if (!workspace->physicsWorld) return;
|
||||||
|
|
||||||
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
|
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
|
||||||
// used to be rather than specifying an anchor rotation, so whatever.
|
// used to be rather than specifying an anchor rotation, so whatever.
|
||||||
|
@ -32,15 +33,15 @@ void Snap::buildJoint() {
|
||||||
workspace->SyncPartPhysics(part1.lock());
|
workspace->SyncPartPhysics(part1.lock());
|
||||||
|
|
||||||
rp::FixedJointInfo jointInfo(part0.lock()->rigidBody, part1.lock()->rigidBody, (c0.Inverse() * c1).Position());
|
rp::FixedJointInfo jointInfo(part0.lock()->rigidBody, part1.lock()->rigidBody, (c0.Inverse() * c1).Position());
|
||||||
this->joint = dynamic_cast<rp::FixedJoint*>(workspace->CreateJoint(jointInfo));
|
this->joint = dynamic_cast<rp::FixedJoint*>(workspace->physicsWorld->createJoint(jointInfo));
|
||||||
jointWorkspace = workspace;
|
jointWorkspace = workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
// !!! REMINDER: This has to be called manually when parts are destroyed/removed from the workspace, or joints will linger
|
// !!! REMINDER: This has to be called manually when parts are destroyed/removed from the workspace, or joints will linger
|
||||||
void Snap::breakJoint() {
|
void Snap::breakJoint() {
|
||||||
// If the joint doesn't exist, or its workspace expired (not our problem anymore), then no need to do anything
|
// If the joint doesn't exist, or its workspace expired (not our problem anymore), then no need to do anything
|
||||||
if (!this->joint || jointWorkspace.expired()) return;
|
if (!this->joint || jointWorkspace.expired() || !jointWorkspace.lock()->physicsWorld) return;
|
||||||
|
|
||||||
jointWorkspace.lock()->DestroyJoint(this->joint);
|
jointWorkspace.lock()->physicsWorld->destroyJoint(this->joint);
|
||||||
this->joint = nullptr;
|
this->joint = nullptr;
|
||||||
}
|
}
|
|
@ -24,6 +24,7 @@ void Weld::buildJoint() {
|
||||||
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return;
|
if ((!GetParent() || GetParent().value()->GetClass() != &JointsService::TYPE) && !workspace()) return;
|
||||||
|
|
||||||
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value();
|
std::shared_ptr<Workspace> workspace = workspaceOfPart(part0.lock()).value();
|
||||||
|
if (!workspace->physicsWorld) return;
|
||||||
|
|
||||||
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
|
// Update Part1's rotation and cframe prior to creating the joint as reactphysics3d locks rotation based on how it
|
||||||
// used to be rather than specifying an anchor rotation, so whatever.
|
// used to be rather than specifying an anchor rotation, so whatever.
|
||||||
|
@ -32,15 +33,15 @@ void Weld::buildJoint() {
|
||||||
workspace->SyncPartPhysics(part1.lock());
|
workspace->SyncPartPhysics(part1.lock());
|
||||||
|
|
||||||
rp::FixedJointInfo jointInfo(part0.lock()->rigidBody, part1.lock()->rigidBody, (c0.Inverse() * c1).Position());
|
rp::FixedJointInfo jointInfo(part0.lock()->rigidBody, part1.lock()->rigidBody, (c0.Inverse() * c1).Position());
|
||||||
this->joint = dynamic_cast<rp::FixedJoint*>(workspace->CreateJoint(jointInfo));
|
this->joint = dynamic_cast<rp::FixedJoint*>(workspace->physicsWorld->createJoint(jointInfo));
|
||||||
jointWorkspace = workspace;
|
jointWorkspace = workspace;
|
||||||
}
|
}
|
||||||
|
|
||||||
// !!! REMINDER: This has to be called manually when parts are destroyed/removed from the workspace, or joints will linger
|
// !!! REMINDER: This has to be called manually when parts are destroyed/removed from the workspace, or joints will linger
|
||||||
void Weld::breakJoint() {
|
void Weld::breakJoint() {
|
||||||
// If the joint doesn't exist, or its workspace expired (not our problem anymore), then no need to do anything
|
// If the joint doesn't exist, or its workspace expired (not our problem anymore), then no need to do anything
|
||||||
if (!this->joint || jointWorkspace.expired()) return;
|
if (!this->joint || jointWorkspace.expired() || !jointWorkspace.lock()->physicsWorld) return;
|
||||||
|
|
||||||
jointWorkspace.lock()->DestroyJoint(this->joint);
|
jointWorkspace.lock()->physicsWorld->destroyJoint(this->joint);
|
||||||
this->joint = nullptr;
|
this->joint = nullptr;
|
||||||
}
|
}
|
|
@ -49,15 +49,6 @@ void Part::OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std
|
||||||
// TODO: Sleeping bodies that touch this one also need to be updated
|
// TODO: Sleeping bodies that touch this one also need to be updated
|
||||||
}
|
}
|
||||||
|
|
||||||
void Part::OnWorkspaceAdded(std::optional<std::shared_ptr<Workspace>> oldWorkspace, std::shared_ptr<Workspace> newWorkspace) {
|
|
||||||
newWorkspace->AddBody(shared<Part>());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Part::OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace) {
|
|
||||||
if (simulationTicket->get() != nullptr)
|
|
||||||
oldWorkspace->RemoveBody(shared<Part>());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Part::onUpdated(std::string property) {
|
void Part::onUpdated(std::string property) {
|
||||||
// Reset velocity
|
// Reset velocity
|
||||||
if (property != "Velocity")
|
if (property != "Velocity")
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/ext.hpp>
|
#include <glm/ext.hpp>
|
||||||
|
@ -10,7 +9,6 @@
|
||||||
#include "datatypes/vector.h"
|
#include "datatypes/vector.h"
|
||||||
#include "objects/base/instance.h"
|
#include "objects/base/instance.h"
|
||||||
#include "enum/surface.h"
|
#include "enum/surface.h"
|
||||||
#include <mutex>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <reactphysics3d/reactphysics3d.h>
|
#include <reactphysics3d/reactphysics3d.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
@ -32,12 +30,6 @@ struct PartConstructParams {
|
||||||
|
|
||||||
class Workspace;
|
class Workspace;
|
||||||
|
|
||||||
#ifndef __SIMULATION_TICKET
|
|
||||||
#define __SIMULATION_TICKET
|
|
||||||
class Part;
|
|
||||||
typedef std::list<std::shared_ptr<Part>>::iterator SimulationTicket;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class DEF_INST_(explorer_icon="part") Part : public PVInstance {
|
class DEF_INST_(explorer_icon="part") Part : public PVInstance {
|
||||||
AUTOGEN_PREAMBLE
|
AUTOGEN_PREAMBLE
|
||||||
protected:
|
protected:
|
||||||
|
@ -58,8 +50,6 @@ protected:
|
||||||
friend JointInstance;
|
friend JointInstance;
|
||||||
friend Workspace;
|
friend Workspace;
|
||||||
|
|
||||||
virtual void OnWorkspaceAdded(std::optional<std::shared_ptr<Workspace>> oldWorkspace, std::shared_ptr<Workspace> newWorkspace) override;
|
|
||||||
virtual void OnWorkspaceRemoved(std::shared_ptr<Workspace> oldWorkspace) override;
|
|
||||||
void OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent) override;
|
void OnAncestryChanged(std::optional<std::shared_ptr<Instance>> child, std::optional<std::shared_ptr<Instance>> newParent) override;
|
||||||
void onUpdated(std::string);
|
void onUpdated(std::string);
|
||||||
public:
|
public:
|
||||||
|
@ -109,8 +99,6 @@ public:
|
||||||
DEF_SIGNAL SignalSource TouchEnded;
|
DEF_SIGNAL SignalSource TouchEnded;
|
||||||
|
|
||||||
rp::RigidBody* rigidBody = nullptr;
|
rp::RigidBody* rigidBody = nullptr;
|
||||||
SimulationTicket simulationTicket;
|
|
||||||
bool rigidBodyDirty = true;
|
|
||||||
|
|
||||||
inline SurfaceType GetSurfaceFromFace(NormalId face) { return surfaceFromFace(face); }
|
inline SurfaceType GetSurfaceFromFace(NormalId face) { return surfaceFromFace(face); }
|
||||||
float GetSurfaceParamA(Vector3 face);
|
float GetSurfaceParamA(Vector3 face);
|
||||||
|
|
|
@ -93,11 +93,8 @@ void ScriptContext::PushThreadSleep(lua_State* thread, float delay) {
|
||||||
lua_pop(state, 1); // pop sleepingThreads
|
lua_pop(state, 1); // pop sleepingThreads
|
||||||
}
|
}
|
||||||
|
|
||||||
tu_time_t schedTime;
|
|
||||||
void ScriptContext::RunSleepingThreads() {
|
void ScriptContext::RunSleepingThreads() {
|
||||||
tu_time_t startTime = tu_clock_micros();
|
for (size_t i = 0; i < sleepingThreads.size();) {
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < sleepingThreads.size();) {
|
|
||||||
bool deleted = false;
|
bool deleted = false;
|
||||||
|
|
||||||
SleepingThread sleep = sleepingThreads[i];
|
SleepingThread sleep = sleepingThreads[i];
|
||||||
|
@ -130,8 +127,6 @@ void ScriptContext::RunSleepingThreads() {
|
||||||
if (!deleted)
|
if (!deleted)
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i > 0)
|
|
||||||
schedTime = tu_clock_micros() - startTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ScriptContext::RegisterScriptSource(std::shared_ptr<Script> script) {
|
std::string ScriptContext::RegisterScriptSource(std::shared_ptr<Script> script) {
|
||||||
|
|
|
@ -2,14 +2,11 @@
|
||||||
#include "datatypes/variant.h"
|
#include "datatypes/variant.h"
|
||||||
#include "datatypes/ref.h"
|
#include "datatypes/ref.h"
|
||||||
#include "datatypes/vector.h"
|
#include "datatypes/vector.h"
|
||||||
#include "logger.h"
|
|
||||||
#include "objects/base/instance.h"
|
#include "objects/base/instance.h"
|
||||||
#include "objects/part.h"
|
|
||||||
#include "objects/service/jointsservice.h"
|
#include "objects/service/jointsservice.h"
|
||||||
#include "objects/joint/jointinstance.h"
|
#include "objects/joint/jointinstance.h"
|
||||||
#include "objects/datamodel.h"
|
#include "objects/datamodel.h"
|
||||||
#include "physics/util.h"
|
#include "physics/util.h"
|
||||||
#include "timeutil.h"
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <reactphysics3d/collision/CollisionCallback.h>
|
#include <reactphysics3d/collision/CollisionCallback.h>
|
||||||
#include <reactphysics3d/collision/OverlapCallback.h>
|
#include <reactphysics3d/collision/OverlapCallback.h>
|
||||||
|
@ -18,11 +15,10 @@
|
||||||
rp::PhysicsCommon* Workspace::physicsCommon = new rp::PhysicsCommon;
|
rp::PhysicsCommon* Workspace::physicsCommon = new rp::PhysicsCommon;
|
||||||
|
|
||||||
Workspace::Workspace(): Service(&TYPE), physicsEventListener(this) {
|
Workspace::Workspace(): Service(&TYPE), physicsEventListener(this) {
|
||||||
physicsWorld = physicsCommon->createPhysicsWorld();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Workspace::~Workspace() {
|
Workspace::~Workspace() {
|
||||||
if (physicsCommon)
|
if (physicsWorld && physicsCommon)
|
||||||
physicsCommon->destroyPhysicsWorld(physicsWorld);
|
physicsCommon->destroyPhysicsWorld(physicsWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +66,8 @@ void Workspace::InitService() {
|
||||||
if (initialized) return;
|
if (initialized) return;
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
|
physicsWorld = physicsCommon->createPhysicsWorld();
|
||||||
|
|
||||||
physicsWorld->setGravity(rp::Vector3(0, -196.2, 0));
|
physicsWorld->setGravity(rp::Vector3(0, -196.2, 0));
|
||||||
// world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::BAUMGARTE_CONTACTS);
|
// world->setContactsPositionCorrectionTechnique(rp3d::ContactsPositionCorrectionTechnique::BAUMGARTE_CONTACTS);
|
||||||
physicsWorld->setNbIterationsPositionSolver(2000);
|
physicsWorld->setNbIterationsPositionSolver(2000);
|
||||||
|
@ -84,6 +82,7 @@ void Workspace::InitService() {
|
||||||
std::shared_ptr<Instance> obj = *it;
|
std::shared_ptr<Instance> obj = *it;
|
||||||
if (!obj->IsA<Part>()) continue;
|
if (!obj->IsA<Part>()) continue;
|
||||||
std::shared_ptr<Part> part = obj->CastTo<Part>().expect();
|
std::shared_ptr<Part> part = obj->CastTo<Part>().expect();
|
||||||
|
this->SyncPartPhysics(part);
|
||||||
part->MakeJoints();
|
part->MakeJoints();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +101,9 @@ void Workspace::InitService() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::updatePartPhysics(std::shared_ptr<Part> part) {
|
void Workspace::SyncPartPhysics(std::shared_ptr<Part> part) {
|
||||||
|
if (!physicsWorld) return;
|
||||||
|
|
||||||
rp::Transform transform = part->cframe;
|
rp::Transform transform = part->cframe;
|
||||||
if (!part->rigidBody) {
|
if (!part->rigidBody) {
|
||||||
part->rigidBody = physicsWorld->createRigidBody(transform);
|
part->rigidBody = physicsWorld->createRigidBody(transform);
|
||||||
|
@ -143,45 +144,15 @@ void Workspace::updatePartPhysics(std::shared_ptr<Part> part) {
|
||||||
part->rigidBody->setUserData(&*part);
|
part->rigidBody->setUserData(&*part);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::SyncPartPhysics(std::shared_ptr<Part> part) {
|
|
||||||
if (globalPhysicsLock.try_lock()) {
|
|
||||||
updatePartPhysics(part);
|
|
||||||
globalPhysicsLock.unlock();
|
|
||||||
} else {
|
|
||||||
part->rigidBodyDirty = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tu_time_t physTime;
|
|
||||||
void Workspace::PhysicsStep(float deltaTime) {
|
void Workspace::PhysicsStep(float deltaTime) {
|
||||||
tu_time_t startTime = tu_clock_micros();
|
// Step the simulation a few steps
|
||||||
|
|
||||||
std::scoped_lock lock(globalPhysicsLock);
|
|
||||||
physicsWorld->update(std::min(deltaTime / 2, (1/60.f)));
|
physicsWorld->update(std::min(deltaTime / 2, (1/60.f)));
|
||||||
|
|
||||||
// Update queued objects
|
|
||||||
queueLock.lock();
|
|
||||||
for (QueueItem item : bodyQueue) {
|
|
||||||
if (item.action == QueueItem::QUEUEITEM_ADD) {
|
|
||||||
simulatedBodies.push_back(item.part);
|
|
||||||
item.part->simulationTicket = --simulatedBodies.end();
|
|
||||||
} else if (item.part->simulationTicket->get() != nullptr) {
|
|
||||||
simulatedBodies.erase(item.part->simulationTicket);
|
|
||||||
item.part->simulationTicket = {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
queueLock.unlock();
|
|
||||||
|
|
||||||
// TODO: Add list of tracked parts in workspace based on their ancestry using inWorkspace property of Instance
|
// TODO: Add list of tracked parts in workspace based on their ancestry using inWorkspace property of Instance
|
||||||
for (std::shared_ptr<Part> part : simulatedBodies) {
|
for (auto it = this->GetDescendantsStart(); it != this->GetDescendantsEnd(); it++) {
|
||||||
// If the part's body is dirty, update it now instead
|
std::shared_ptr<Instance> obj = *it;
|
||||||
if (part->rigidBodyDirty) {
|
if (!obj->IsA<Part>()) continue;
|
||||||
updatePartPhysics(part);
|
std::shared_ptr<Part> part = std::dynamic_pointer_cast<Part>(obj);
|
||||||
part->rigidBodyDirty = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!part->rigidBody) continue;
|
|
||||||
|
|
||||||
// Sync properties
|
// Sync properties
|
||||||
const rp::Transform& transform = part->rigidBody->getTransform();
|
const rp::Transform& transform = part->rigidBody->getTransform();
|
||||||
|
@ -209,8 +180,6 @@ void Workspace::PhysicsStep(float deltaTime) {
|
||||||
parent.value()->Destroy();
|
parent.value()->Destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
physTime = tu_clock_micros() - startTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -262,7 +231,6 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<const RaycastResult> Workspace::CastRayNearest(glm::vec3 point, glm::vec3 rotation, float maxLength, std::optional<RaycastFilter> filter, unsigned short categoryMaskBits) {
|
std::optional<const RaycastResult> Workspace::CastRayNearest(glm::vec3 point, glm::vec3 rotation, float maxLength, std::optional<RaycastFilter> filter, unsigned short categoryMaskBits) {
|
||||||
// std::scoped_lock lock(globalPhysicsLock);
|
|
||||||
rp::Ray ray(glmToRp(point), glmToRp(glm::normalize(rotation)) * maxLength);
|
rp::Ray ray(glmToRp(point), glmToRp(glm::normalize(rotation)) * maxLength);
|
||||||
NearestRayHit rayHit(glmToRp(point), filter);
|
NearestRayHit rayHit(glmToRp(point), filter);
|
||||||
physicsWorld->raycast(ray, &rayHit, categoryMaskBits);
|
physicsWorld->raycast(ray, &rayHit, categoryMaskBits);
|
||||||
|
@ -270,31 +238,5 @@ std::optional<const RaycastResult> Workspace::CastRayNearest(glm::vec3 point, gl
|
||||||
}
|
}
|
||||||
|
|
||||||
void Workspace::DestroyRigidBody(rp::RigidBody* rigidBody) {
|
void Workspace::DestroyRigidBody(rp::RigidBody* rigidBody) {
|
||||||
std::scoped_lock lock(globalPhysicsLock);
|
|
||||||
physicsWorld->destroyRigidBody(rigidBody);
|
physicsWorld->destroyRigidBody(rigidBody);
|
||||||
}
|
|
||||||
|
|
||||||
void Workspace::DestroyJoint(rp::Joint* joint) {
|
|
||||||
std::scoped_lock lock(globalPhysicsLock);
|
|
||||||
physicsWorld->destroyJoint(joint);
|
|
||||||
}
|
|
||||||
|
|
||||||
rp::Joint* Workspace::CreateJoint(const rp::JointInfo& jointInfo) {
|
|
||||||
std::scoped_lock lock(globalPhysicsLock);
|
|
||||||
rp::Joint* joint = physicsWorld->createJoint(jointInfo);
|
|
||||||
|
|
||||||
return joint;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Workspace::AddBody(std::shared_ptr<Part> part) {
|
|
||||||
queueLock.lock();
|
|
||||||
bodyQueue.push_back({part, QueueItem::QUEUEITEM_ADD});
|
|
||||||
part->rigidBodyDirty = true;
|
|
||||||
queueLock.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Workspace::RemoveBody(std::shared_ptr<Part> part) {
|
|
||||||
queueLock.lock();
|
|
||||||
bodyQueue.push_back({part, QueueItem::QUEUEITEM_REMOVE});
|
|
||||||
queueLock.unlock();
|
|
||||||
}
|
}
|
|
@ -2,11 +2,8 @@
|
||||||
|
|
||||||
#include "objects/annotation.h"
|
#include "objects/annotation.h"
|
||||||
#include "objects/base/service.h"
|
#include "objects/base/service.h"
|
||||||
#include "utils.h"
|
|
||||||
#include <glm/ext/vector_float3.hpp>
|
#include <glm/ext/vector_float3.hpp>
|
||||||
#include <list>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
#include <reactphysics3d/body/RigidBody.h>
|
#include <reactphysics3d/body/RigidBody.h>
|
||||||
#include <reactphysics3d/engine/EventListener.h>
|
#include <reactphysics3d/engine/EventListener.h>
|
||||||
#include <reactphysics3d/engine/PhysicsCommon.h>
|
#include <reactphysics3d/engine/PhysicsCommon.h>
|
||||||
|
@ -37,21 +34,8 @@ class Weld;
|
||||||
class Rotate;
|
class Rotate;
|
||||||
class RotateV;
|
class RotateV;
|
||||||
|
|
||||||
#ifndef __SIMULATION_TICKET
|
|
||||||
#define __SIMULATION_TICKET
|
|
||||||
typedef std::list<std::shared_ptr<Part>>::iterator SimulationTicket;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef std::function<FilterResult(std::shared_ptr<Part>)> RaycastFilter;
|
typedef std::function<FilterResult(std::shared_ptr<Part>)> RaycastFilter;
|
||||||
|
|
||||||
struct QueueItem {
|
|
||||||
std::shared_ptr<Part> part;
|
|
||||||
enum {
|
|
||||||
QUEUEITEM_ADD,
|
|
||||||
QUEUEITEM_REMOVE,
|
|
||||||
} action;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Workspace;
|
class Workspace;
|
||||||
class PhysicsEventListener : public rp::EventListener {
|
class PhysicsEventListener : public rp::EventListener {
|
||||||
friend Workspace;
|
friend Workspace;
|
||||||
|
@ -66,13 +50,15 @@ class PhysicsEventListener : public rp::EventListener {
|
||||||
class DEF_INST_SERVICE_(explorer_icon="workspace") Workspace : public Service {
|
class DEF_INST_SERVICE_(explorer_icon="workspace") Workspace : public Service {
|
||||||
AUTOGEN_PREAMBLE
|
AUTOGEN_PREAMBLE
|
||||||
|
|
||||||
std::list<std::shared_ptr<Part>> simulatedBodies;
|
rp::PhysicsWorld* physicsWorld = nullptr;
|
||||||
std::list<QueueItem> bodyQueue;
|
|
||||||
rp::PhysicsWorld* physicsWorld;
|
|
||||||
static rp::PhysicsCommon* physicsCommon;
|
static rp::PhysicsCommon* physicsCommon;
|
||||||
PhysicsEventListener physicsEventListener;
|
PhysicsEventListener physicsEventListener;
|
||||||
|
|
||||||
void updatePartPhysics(std::shared_ptr<Part> part);
|
friend Part;
|
||||||
|
friend Snap;
|
||||||
|
friend Weld;
|
||||||
|
friend Rotate;
|
||||||
|
friend RotateV;
|
||||||
protected:
|
protected:
|
||||||
void InitService() override;
|
void InitService() override;
|
||||||
bool initialized = false;
|
bool initialized = false;
|
||||||
|
@ -81,21 +67,13 @@ public:
|
||||||
Workspace();
|
Workspace();
|
||||||
~Workspace();
|
~Workspace();
|
||||||
|
|
||||||
std::mutex globalPhysicsLock;
|
|
||||||
std::recursive_mutex queueLock;
|
|
||||||
|
|
||||||
DEF_PROP float fallenPartsDestroyHeight = -500;
|
DEF_PROP float fallenPartsDestroyHeight = -500;
|
||||||
|
|
||||||
// static inline std::shared_ptr<Workspace> New() { return std::make_shared<Workspace>(); };
|
// static inline std::shared_ptr<Workspace> New() { return std::make_shared<Workspace>(); };
|
||||||
static inline std::shared_ptr<Instance> Create() { return std::make_shared<Workspace>(); };
|
static inline std::shared_ptr<Instance> Create() { return std::make_shared<Workspace>(); };
|
||||||
|
|
||||||
void AddBody(std::shared_ptr<Part> part);
|
|
||||||
void RemoveBody(std::shared_ptr<Part> part);
|
|
||||||
void DestroyRigidBody(rp::RigidBody* rigidBody);
|
|
||||||
void SyncPartPhysics(std::shared_ptr<Part> part);
|
void SyncPartPhysics(std::shared_ptr<Part> part);
|
||||||
|
void DestroyRigidBody(rp::RigidBody* rigidBody);
|
||||||
rp::Joint* CreateJoint(const rp::JointInfo& jointInfo);
|
|
||||||
void DestroyJoint(rp::Joint* joint);
|
|
||||||
|
|
||||||
void PhysicsStep(float deltaTime);
|
void PhysicsStep(float deltaTime);
|
||||||
std::optional<const RaycastResult> CastRayNearest(glm::vec3 point, glm::vec3 rotation, float maxLength, std::optional<RaycastFilter> filter = std::nullopt, unsigned short categoryMaskBits = 0xFFFF);
|
std::optional<const RaycastResult> CastRayNearest(glm::vec3 point, glm::vec3 rotation, float maxLength, std::optional<RaycastFilter> filter = std::nullopt, unsigned short categoryMaskBits = 0xFFFF);
|
||||||
|
|
|
@ -94,7 +94,7 @@ void PartAssembly::Scale(Vector3 newSize, bool scaleUp) {
|
||||||
parts[0]->size = newSize;
|
parts[0]->size = newSize;
|
||||||
parts[0]->UpdateProperty("Size");
|
parts[0]->UpdateProperty("Size");
|
||||||
sendPropertyUpdatedSignal(parts[0], "Size", Variant(parts[0]->size));
|
sendPropertyUpdatedSignal(parts[0], "Size", Variant(parts[0]->size));
|
||||||
_size = _bounds = newSize;
|
_bounds = newSize;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ void PartAssembly::Scale(Vector3 newSize, bool scaleUp) {
|
||||||
sendPropertyUpdatedSignal(part, "Size", Variant(part->size));
|
sendPropertyUpdatedSignal(part, "Size", Variant(part->size));
|
||||||
}
|
}
|
||||||
|
|
||||||
_size = _bounds = _bounds * factor;
|
_bounds = _bounds * factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<PartTransformState> PartAssembly::GetCurrentTransforms() {
|
std::vector<PartTransformState> PartAssembly::GetCurrentTransforms() {
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
#include "rendering/shader.h"
|
|
||||||
#include "rendering/texture3d.h"
|
|
||||||
#include "timeutil.h"
|
|
||||||
#include <GL/glew.h>
|
|
||||||
#include <GL/gl.h>
|
|
||||||
#include <glm/ext/vector_float4.hpp>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
extern int viewportWidth, viewportHeight;
|
|
||||||
extern Texture3D* fontTexture;
|
|
||||||
extern Shader* fontShader;
|
|
||||||
extern Shader* identityShader;
|
|
||||||
|
|
||||||
void drawChar(char c, int x, int y, float scale=1.f) {
|
|
||||||
fontShader->use();
|
|
||||||
fontTexture->activate(1);
|
|
||||||
fontShader->set("fontTex", 1);
|
|
||||||
|
|
||||||
fontShader->set("charIndex", (int)c);
|
|
||||||
|
|
||||||
// https://stackoverflow.com/a/10631263
|
|
||||||
int tex = fontShader->getAttribute("aTexCoord");
|
|
||||||
|
|
||||||
y = viewportHeight - y - 16*scale;
|
|
||||||
float x0 = float(x)/viewportWidth, y0 = float(y)/viewportHeight, x1 = ((float)x + 8*scale)/viewportWidth, y1 = ((float)y + 16*scale)/viewportHeight;
|
|
||||||
x0 *= 2, y0 *= 2, x1 *= 2, y1 *= 2;
|
|
||||||
x0 -= 1, y0 -= 1, x1 -= 1, y1 -= 1;
|
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
glVertex3f(x0, y0, 0); glVertexAttrib2f(tex, 1, 1);
|
|
||||||
glVertex3f(x1, y0, 0); glVertexAttrib2f(tex, 1, 0);
|
|
||||||
glVertex3f(x1, y1, 0); glVertexAttrib2f(tex, 0, 0);
|
|
||||||
glVertex3f(x0, y1, 0); glVertexAttrib2f(tex, 0, 1);
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawString(std::string str, int x, int y, float scale=1.f) {
|
|
||||||
for (int i = 0; i < (int)str.length(); i++) {
|
|
||||||
char c = str[i];
|
|
||||||
drawChar(c, x+i*8*scale, y, scale);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawRect(int x, int y, int w, int h, glm::vec4 color) {
|
|
||||||
identityShader->use();
|
|
||||||
identityShader->set("aColor", color);
|
|
||||||
|
|
||||||
float x0 = 2*float(x)/viewportWidth-1, y0 = 2*float(y)/viewportHeight-1, x1 = 2*float(x + w)/viewportWidth-1, y1 = 2*float(y + h)/viewportHeight-1;
|
|
||||||
float tmp;
|
|
||||||
tmp = -y0, y0 = -y1, y1 = tmp;
|
|
||||||
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
glVertex3f(x0, y0, 0);
|
|
||||||
glVertex3f(x1, y0, 0);
|
|
||||||
glVertex3f(x1, y1, 0);
|
|
||||||
glVertex3f(x0, y1, 0);
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
static tu_time_t lastTime;
|
|
||||||
extern tu_time_t renderTime;
|
|
||||||
extern tu_time_t physTime;
|
|
||||||
extern tu_time_t schedTime;
|
|
||||||
|
|
||||||
// Draws debug info window
|
|
||||||
// Including info about framerates, etc.
|
|
||||||
void renderDebugInfo() {
|
|
||||||
tu_time_t timePassed = tu_clock_micros() - lastTime;
|
|
||||||
float frames = 1/(((float)timePassed)/1'000'000);
|
|
||||||
|
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
|
|
||||||
drawRect(0, 0, 200, 16*8, glm::vec4(0.2f,0.2f,0.2f,0.8f));
|
|
||||||
drawString("FPS: " + std::to_string((int)frames), 0, 16*0);
|
|
||||||
drawString(" 1/: " + std::to_string((float)timePassed/1'000'000), 0, 16*1);
|
|
||||||
|
|
||||||
frames = 1/(((float)renderTime)/1'000'000);
|
|
||||||
drawString("RPS: " + std::to_string((int)frames), 0, 16*2);
|
|
||||||
drawString(" 1/: " + std::to_string((float)renderTime/1'000'000), 0, 16*3);
|
|
||||||
|
|
||||||
frames = 1/(((float)physTime)/1'000'000);
|
|
||||||
drawString("PPS: " + std::to_string((int)frames), 0, 16*4);
|
|
||||||
drawString(" 1/: " + std::to_string((float)physTime/1'000'000), 0, 16*5);
|
|
||||||
|
|
||||||
frames = 1/(((float)schedTime)/1'000'000);
|
|
||||||
drawString("SPS: " + std::to_string((int)frames), 0, 16*6);
|
|
||||||
drawString(" 1/: " + std::to_string((float)schedTime/1'000'000), 0, 16*7);
|
|
||||||
|
|
||||||
lastTime = tu_clock_micros();
|
|
||||||
}
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "math_helper.h"
|
#include "math_helper.h"
|
||||||
#include "objects/service/selection.h"
|
#include "objects/service/selection.h"
|
||||||
#include "partassembly.h"
|
#include "partassembly.h"
|
||||||
#include "rendering/texture.h"
|
|
||||||
#include "rendering/torus.h"
|
#include "rendering/torus.h"
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
|
@ -32,7 +31,6 @@
|
||||||
#include "skybox.h"
|
#include "skybox.h"
|
||||||
#include "enum/surface.h"
|
#include "enum/surface.h"
|
||||||
#include "texture3d.h"
|
#include "texture3d.h"
|
||||||
#include "timeutil.h"
|
|
||||||
|
|
||||||
#include "renderer.h"
|
#include "renderer.h"
|
||||||
|
|
||||||
|
@ -43,18 +41,13 @@ Shader* identityShader = NULL;
|
||||||
Shader* ghostShader = NULL;
|
Shader* ghostShader = NULL;
|
||||||
Shader* wireframeShader = NULL;
|
Shader* wireframeShader = NULL;
|
||||||
Shader* outlineShader = NULL;
|
Shader* outlineShader = NULL;
|
||||||
Shader* fontShader = NULL;
|
|
||||||
extern Camera camera;
|
extern Camera camera;
|
||||||
Skybox* skyboxTexture = NULL;
|
Skybox* skyboxTexture = NULL;
|
||||||
Texture3D* studsTexture = NULL;
|
Texture3D* studsTexture = NULL;
|
||||||
Texture* fontTexture = NULL;
|
|
||||||
|
|
||||||
bool debugRendererEnabled = false;
|
|
||||||
bool wireframeRendering = false;
|
bool wireframeRendering = false;
|
||||||
|
|
||||||
int viewportWidth, viewportHeight;
|
static int viewportWidth, viewportHeight;
|
||||||
|
|
||||||
void renderDebugInfo();
|
|
||||||
|
|
||||||
void renderInit(GLFWwindow* window, int width, int height) {
|
void renderInit(GLFWwindow* window, int width, int height) {
|
||||||
viewportWidth = width, viewportHeight = height;
|
viewportWidth = width, viewportHeight = height;
|
||||||
|
@ -67,8 +60,6 @@ void renderInit(GLFWwindow* window, int width, int height) {
|
||||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
fontTexture = new Texture("assets/textures/debugfnt.bmp", GL_RGB);
|
|
||||||
|
|
||||||
skyboxTexture = new Skybox({
|
skyboxTexture = new Skybox({
|
||||||
"assets/textures/skybox/null_plainsky512_lf.jpg",
|
"assets/textures/skybox/null_plainsky512_lf.jpg",
|
||||||
"assets/textures/skybox/null_plainsky512_rt.jpg",
|
"assets/textures/skybox/null_plainsky512_rt.jpg",
|
||||||
|
@ -88,7 +79,6 @@ void renderInit(GLFWwindow* window, int width, int height) {
|
||||||
ghostShader = new Shader("assets/shaders/ghost.vs", "assets/shaders/ghost.fs");
|
ghostShader = new Shader("assets/shaders/ghost.vs", "assets/shaders/ghost.fs");
|
||||||
wireframeShader = new Shader("assets/shaders/wireframe.vs", "assets/shaders/wireframe.fs");
|
wireframeShader = new Shader("assets/shaders/wireframe.vs", "assets/shaders/wireframe.fs");
|
||||||
outlineShader = new Shader("assets/shaders/outline.vs", "assets/shaders/outline.fs");
|
outlineShader = new Shader("assets/shaders/outline.vs", "assets/shaders/outline.fs");
|
||||||
fontShader = new Shader("assets/shaders/font.vs", "assets/shaders/font.fs");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderParts() {
|
void renderParts() {
|
||||||
|
@ -332,7 +322,7 @@ void renderHandles() {
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
identityShader->use();
|
identityShader->use();
|
||||||
identityShader->set("aColor", glm::vec4(0.f, 1.f, 1.f, 1.f));
|
identityShader->set("aColor", glm::vec3(0.f, 1.f, 1.f));
|
||||||
|
|
||||||
for (auto face : HandleFace::Faces) {
|
for (auto face : HandleFace::Faces) {
|
||||||
CFrame cframe = getHandleCFrame(face);
|
CFrame cframe = getHandleCFrame(face);
|
||||||
|
@ -635,12 +625,9 @@ void addDebugRenderCFrame(CFrame frame, Color3 color) {
|
||||||
DEBUG_CFRAMES.push_back(std::make_pair(frame, color));
|
DEBUG_CFRAMES.push_back(std::make_pair(frame, color));
|
||||||
}
|
}
|
||||||
|
|
||||||
tu_time_t renderTime;
|
|
||||||
void render(GLFWwindow* window) {
|
void render(GLFWwindow* window) {
|
||||||
tu_time_t startTime = tu_clock_micros();
|
|
||||||
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);
|
|
||||||
|
|
||||||
renderSkyBox();
|
renderSkyBox();
|
||||||
renderHandles();
|
renderHandles();
|
||||||
|
@ -652,17 +639,10 @@ void render(GLFWwindow* window) {
|
||||||
renderRotationArcs();
|
renderRotationArcs();
|
||||||
if (wireframeRendering)
|
if (wireframeRendering)
|
||||||
renderWireframe();
|
renderWireframe();
|
||||||
if (debugRendererEnabled)
|
|
||||||
renderDebugInfo();
|
|
||||||
// TODO: Make this a debug flag
|
// TODO: Make this a debug flag
|
||||||
// renderAABB();
|
// renderAABB();
|
||||||
renderTime = tu_clock_micros() - startTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setViewport(int width, int height) {
|
void setViewport(int width, int height) {
|
||||||
viewportWidth = width, viewportHeight = height;
|
viewportWidth = width, viewportHeight = height;
|
||||||
}
|
|
||||||
|
|
||||||
void setDebugRendererEnabled(bool enabled) {
|
|
||||||
debugRendererEnabled = enabled;
|
|
||||||
}
|
}
|
|
@ -3,12 +3,10 @@
|
||||||
|
|
||||||
extern bool wireframeRendering;
|
extern bool wireframeRendering;
|
||||||
|
|
||||||
class CFrame;
|
namespace Data { class CFrame; class Color3; };
|
||||||
class Color3;
|
|
||||||
|
|
||||||
void renderInit(GLFWwindow* window, int width, int height);
|
void renderInit(GLFWwindow* window, int width, int height);
|
||||||
void render(GLFWwindow* window);
|
void render(GLFWwindow* window);
|
||||||
void setViewport(int width, int height);
|
void setViewport(int width, int height);
|
||||||
void addDebugRenderCFrame(CFrame);
|
void addDebugRenderCFrame(CFrame);
|
||||||
void addDebugRenderCFrame(CFrame, Color3);
|
void addDebugRenderCFrame(CFrame, Color3);
|
||||||
void setDebugRendererEnabled(bool enabled);
|
|
|
@ -100,18 +100,10 @@ void Shader::set(std::string key, glm::vec3 value) {
|
||||||
glUniform3f(glGetUniformLocation(id, key.c_str()), value.x, value.y, value.z);
|
glUniform3f(glGetUniformLocation(id, key.c_str()), value.x, value.y, value.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::set(std::string key, glm::vec4 value) {
|
|
||||||
glUniform4f(glGetUniformLocation(id, key.c_str()), value.x, value.y, value.z, value.w);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shader::set(std::string key, glm::mat3 value) {
|
void Shader::set(std::string key, glm::mat3 value) {
|
||||||
glUniformMatrix3fv(glGetUniformLocation(id, key.c_str()), 1, GL_FALSE, glm::value_ptr(value));
|
glUniformMatrix3fv(glGetUniformLocation(id, key.c_str()), 1, GL_FALSE, glm::value_ptr(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::set(std::string key, glm::mat4 value) {
|
void Shader::set(std::string key, glm::mat4 value) {
|
||||||
glUniformMatrix4fv(glGetUniformLocation(id, key.c_str()), 1, GL_FALSE, glm::value_ptr(value));
|
glUniformMatrix4fv(glGetUniformLocation(id, key.c_str()), 1, GL_FALSE, glm::value_ptr(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
int Shader::getAttribute(std::string key) {
|
|
||||||
return glGetAttribLocation(id, key.c_str());
|
|
||||||
}
|
|
|
@ -19,9 +19,6 @@ public:
|
||||||
void set(std::string key, DirLight value);
|
void set(std::string key, DirLight value);
|
||||||
void set(std::string key, PointLight value);
|
void set(std::string key, PointLight value);
|
||||||
void set(std::string key, glm::vec3 value);
|
void set(std::string key, glm::vec3 value);
|
||||||
void set(std::string key, glm::vec4 value);
|
|
||||||
void set(std::string key, glm::mat3 value);
|
void set(std::string key, glm::mat3 value);
|
||||||
void set(std::string key, glm::mat4 value);
|
void set(std::string key, glm::mat4 value);
|
||||||
|
|
||||||
int getAttribute(std::string key);
|
|
||||||
};
|
};
|
|
@ -1,12 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(__clang__)
|
#ifdef __clang__
|
||||||
#pragma clang diagnostic ignored "-Wnullability-extension"
|
#pragma clang diagnostic ignored "-Wnullability-extension"
|
||||||
#define nullable _Nullable
|
#define nullable _Nullable
|
||||||
#define notnull _Nonnull
|
#define notnull _Nonnull
|
||||||
#elif defined(__GNUC__)
|
|
||||||
#define nullable
|
|
||||||
#define notnull __attribute__((nonnull))
|
|
||||||
#else
|
#else
|
||||||
#define nullable
|
#define nullable
|
||||||
#define notnull
|
#define notnull
|
||||||
|
|
|
@ -226,7 +226,6 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) {
|
||||||
if (editorToolHandles.handlesType == MoveHandles) {
|
if (editorToolHandles.handlesType == MoveHandles) {
|
||||||
selectionAssembly.TransformBy(CFrame() + absDiff);
|
selectionAssembly.TransformBy(CFrame() + absDiff);
|
||||||
} else if (editorToolHandles.handlesType == ScaleHandles) {
|
} else if (editorToolHandles.handlesType == ScaleHandles) {
|
||||||
Vector3 oldSize = selectionAssembly.size();
|
|
||||||
if (evt->modifiers() & Qt::AltModifier) {
|
if (evt->modifiers() & Qt::AltModifier) {
|
||||||
// If size gets too small, don't
|
// If size gets too small, don't
|
||||||
if (glm::any(glm::lessThan(glm::vec3(selectionAssembly.size() + abs(draggingHandle->normal) * diff * 2.f), glm::vec3(0.001f))))
|
if (glm::any(glm::lessThan(glm::vec3(selectionAssembly.size() + abs(draggingHandle->normal) * diff * 2.f), glm::vec3(0.001f))))
|
||||||
|
@ -241,9 +240,6 @@ void MainGLWidget::handleLinearTransform(QMouseEvent* evt) {
|
||||||
selectionAssembly.TransformBy(CFrame() + absDiff * 0.5f);
|
selectionAssembly.TransformBy(CFrame() + absDiff * 0.5f);
|
||||||
selectionAssembly.Scale(selectionAssembly.size() + abs(draggingHandle->normal) * diff, diff > 0);
|
selectionAssembly.Scale(selectionAssembly.size() + abs(draggingHandle->normal) * diff, diff > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snappingFactor() > 0 && oldSize != selectionAssembly.size() && mainWindow()->editSoundEffects && QFile::exists("./assets/excluded/switch.wav"))
|
|
||||||
playSound("./assets/excluded/switch.wav");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,12 +524,6 @@ void MainGLWidget::keyPressEvent(QKeyEvent* evt) {
|
||||||
lastPart->name = "Part" + std::to_string(partId++);
|
lastPart->name = "Part" + std::to_string(partId++);
|
||||||
M_mainWindow->undoManager.PushState({ UndoStateInstanceCreated { lastPart, gWorkspace() } });
|
M_mainWindow->undoManager.PushState({ UndoStateInstanceCreated { lastPart, gWorkspace() } });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (evt->key() == Qt::Key_BracketLeft) {
|
|
||||||
static bool debugRenderEnabled;
|
|
||||||
debugRenderEnabled = !debugRenderEnabled;
|
|
||||||
setDebugRendererEnabled(debugRenderEnabled);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainGLWidget::keyReleaseEvent(QKeyEvent* evt) {
|
void MainGLWidget::keyReleaseEvent(QKeyEvent* evt) {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1050</width>
|
<width>1027</width>
|
||||||
<height>750</height>
|
<height>750</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
|
|
@ -3,55 +3,21 @@
|
||||||
#include "datatypes/variant.h"
|
#include "datatypes/variant.h"
|
||||||
#include "mainglwidget.h"
|
#include "mainglwidget.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "objects/joint/snap.h"
|
||||||
|
#include "objects/script.h"
|
||||||
#include "objects/service/script/scriptcontext.h"
|
#include "objects/service/script/scriptcontext.h"
|
||||||
#include <chrono>
|
#include "enum/surface.h"
|
||||||
|
#include <cstdio>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
#include <qboxlayout.h>
|
#include <qboxlayout.h>
|
||||||
#include <qcoreevent.h>
|
|
||||||
#include <qdebug.h>
|
#include <qdebug.h>
|
||||||
#include <qevent.h>
|
#include <qevent.h>
|
||||||
#include <qglobal.h>
|
|
||||||
#include <qmargins.h>
|
#include <qmargins.h>
|
||||||
#include <qmdisubwindow.h>
|
#include <qmdisubwindow.h>
|
||||||
#include <qlayout.h>
|
#include <qlayout.h>
|
||||||
#include <qmimedata.h>
|
#include <qmimedata.h>
|
||||||
#include <qmutex.h>
|
|
||||||
#include <qwaitcondition.h>
|
|
||||||
#include <thread>
|
|
||||||
#include "../ui_mainwindow.h"
|
#include "../ui_mainwindow.h"
|
||||||
#include "objects/service/selection.h"
|
#include "objects/service/selection.h"
|
||||||
#include "timeutil.h"
|
|
||||||
|
|
||||||
class PlaceDocumentPhysicsWorker {
|
|
||||||
public:
|
|
||||||
std::mutex sync;
|
|
||||||
std::thread thread;
|
|
||||||
std::condition_variable runningCond;
|
|
||||||
bool running = false;
|
|
||||||
bool quit = false;
|
|
||||||
|
|
||||||
PlaceDocumentPhysicsWorker() : thread(&PlaceDocumentPhysicsWorker::doWork, this) {}
|
|
||||||
private:
|
|
||||||
tu_time_t lastTime = tu_clock_micros();
|
|
||||||
void doWork() {
|
|
||||||
do {
|
|
||||||
tu_time_t deltaTime = tu_clock_micros() - lastTime;
|
|
||||||
lastTime = tu_clock_micros();
|
|
||||||
|
|
||||||
// First frame is always empty
|
|
||||||
if (deltaTime > 100) {
|
|
||||||
gWorkspace()->PhysicsStep(float(deltaTime)/1'000'000);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(16'667 - deltaTime));
|
|
||||||
|
|
||||||
std::unique_lock lock(sync);
|
|
||||||
runningCond.wait(lock, [&]{ return running || quit; });
|
|
||||||
lock.unlock();
|
|
||||||
} while (!quit);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
PlaceDocument::PlaceDocument(QWidget* parent):
|
PlaceDocument::PlaceDocument(QWidget* parent):
|
||||||
QMdiSubWindow(parent) {
|
QMdiSubWindow(parent) {
|
||||||
|
@ -62,29 +28,15 @@ PlaceDocument::PlaceDocument(QWidget* parent):
|
||||||
|
|
||||||
_runState = RUN_STOPPED;
|
_runState = RUN_STOPPED;
|
||||||
updateSelectionListeners(gDataModel->GetService<Selection>());
|
updateSelectionListeners(gDataModel->GetService<Selection>());
|
||||||
|
|
||||||
worker = new PlaceDocumentPhysicsWorker();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaceDocument::~PlaceDocument() {
|
PlaceDocument::~PlaceDocument() {
|
||||||
worker->quit = true;
|
|
||||||
worker->runningCond.notify_all();
|
|
||||||
worker->thread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlaceDocument::updatePhysicsWorker() {
|
|
||||||
{
|
|
||||||
std::lock_guard lock(worker->sync);
|
|
||||||
worker->running = _runState == RUN_RUNNING;
|
|
||||||
}
|
|
||||||
worker->runningCond.notify_all();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaceDocument::setRunState(RunState newState) {
|
void PlaceDocument::setRunState(RunState newState) {
|
||||||
if (newState == RUN_RUNNING && _runState != RUN_RUNNING) {
|
if (newState == RUN_RUNNING && _runState != RUN_RUNNING) {
|
||||||
if (_runState == RUN_PAUSED) {
|
if (_runState == RUN_PAUSED) {
|
||||||
_runState = RUN_RUNNING;
|
_runState = RUN_RUNNING;
|
||||||
updatePhysicsWorker();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,8 +55,6 @@ void PlaceDocument::setRunState(RunState newState) {
|
||||||
gDataModel = editModeDataModel;
|
gDataModel = editModeDataModel;
|
||||||
updateSelectionListeners(gDataModel->GetService<Selection>());
|
updateSelectionListeners(gDataModel->GetService<Selection>());
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePhysicsWorker();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaceDocument::updateSelectionListeners(std::shared_ptr<Selection> selection) {
|
void PlaceDocument::updateSelectionListeners(std::shared_ptr<Selection> selection) {
|
||||||
|
@ -131,12 +81,18 @@ void PlaceDocument::closeEvent(QCloseEvent *closeEvent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Part> shit;
|
std::shared_ptr<Part> shit;
|
||||||
|
static std::chrono::time_point lastTime = std::chrono::steady_clock::now();
|
||||||
void PlaceDocument::timerEvent(QTimerEvent* evt) {
|
void PlaceDocument::timerEvent(QTimerEvent* evt) {
|
||||||
if (evt->timerId() != timer.timerId()) {
|
if (evt->timerId() != timer.timerId()) {
|
||||||
QWidget::timerEvent(evt);
|
QWidget::timerEvent(evt);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float deltaTime = std::chrono::duration_cast<std::chrono::duration<float>>(std::chrono::steady_clock::now() - lastTime).count();
|
||||||
|
lastTime = std::chrono::steady_clock::now();
|
||||||
|
|
||||||
|
if (_runState == RUN_RUNNING)
|
||||||
|
gWorkspace()->PhysicsStep(deltaTime);
|
||||||
placeWidget->repaint();
|
placeWidget->repaint();
|
||||||
placeWidget->updateCycle();
|
placeWidget->updateCycle();
|
||||||
gDataModel->GetService<ScriptContext>()->RunSleepingThreads();
|
gDataModel->GetService<ScriptContext>()->RunSleepingThreads();
|
||||||
|
|
|
@ -2,18 +2,11 @@
|
||||||
|
|
||||||
#include "datatypes/signal.h"
|
#include "datatypes/signal.h"
|
||||||
#include "mainglwidget.h"
|
#include "mainglwidget.h"
|
||||||
#include <condition_variable>
|
|
||||||
#include <mutex>
|
|
||||||
#include <qevent.h>
|
#include <qevent.h>
|
||||||
#include <qmdisubwindow.h>
|
#include <qmdisubwindow.h>
|
||||||
#include <qthread.h>
|
|
||||||
#include <qmutex.h>
|
|
||||||
#include <qwaitcondition.h>
|
|
||||||
#include <QBasicTimer>
|
#include <QBasicTimer>
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
class Selection;
|
class Selection;
|
||||||
class PlaceDocumentPhysicsWorker;
|
|
||||||
|
|
||||||
enum RunState {
|
enum RunState {
|
||||||
RUN_STOPPED,
|
RUN_STOPPED,
|
||||||
|
@ -25,14 +18,10 @@ class PlaceDocument : public QMdiSubWindow {
|
||||||
QBasicTimer timer;
|
QBasicTimer timer;
|
||||||
RunState _runState;
|
RunState _runState;
|
||||||
|
|
||||||
PlaceDocumentPhysicsWorker* worker;
|
|
||||||
|
|
||||||
std::weak_ptr<SignalConnection> selectionConnection;
|
std::weak_ptr<SignalConnection> selectionConnection;
|
||||||
|
|
||||||
void timerEvent(QTimerEvent*) override;
|
void timerEvent(QTimerEvent*) override;
|
||||||
void updateSelectionListeners(std::shared_ptr<Selection>);
|
void updateSelectionListeners(std::shared_ptr<Selection>);
|
||||||
|
|
||||||
void updatePhysicsWorker();
|
|
||||||
public:
|
public:
|
||||||
MainGLWidget* placeWidget;
|
MainGLWidget* placeWidget;
|
||||||
PlaceDocument(QWidget* parent = nullptr);
|
PlaceDocument(QWidget* parent = nullptr);
|
||||||
|
|
|
@ -7,7 +7,7 @@ void UndoHistory::PushState(UndoState state) {
|
||||||
redoHistory = {};
|
redoHistory = {};
|
||||||
|
|
||||||
if (maxBufferSize != -1 && (int)undoHistory.size() > maxBufferSize)
|
if (maxBufferSize != -1 && (int)undoHistory.size() > maxBufferSize)
|
||||||
undoHistory.pop_front();
|
undoHistory.erase(undoHistory.begin(), undoHistory.begin()+maxBufferSize-(int)undoHistory.size()-1);
|
||||||
|
|
||||||
undoHistory.push_back(state);
|
undoHistory.push_back(state);
|
||||||
undoStateListener();
|
undoStateListener();
|
||||||
|
|
Loading…
Add table
Reference in a new issue