6 Commits

Author SHA1 Message Date
NT_x86
e365f3ed6c Open new place crash workaround
Reloads jointsservice on place open
2023-03-31 14:31:34 +03:00
NT_x86
998a22a43f Improved snap solver
Uses ODE collision detection instead
2023-03-29 21:00:15 +03:00
NT_x86
abb1f76c71 Joint solver basic implementation (axis aligned)
Does not handle rotation at all. solveWorkspaceSnaps is called in the debug game creation (Application.cpp)
Added isA to instance class
2023-03-28 21:05:08 +03:00
NT_x86
85e84bfdf3 Fix the crashing issue when closing Blocks3d
Physics engine now destroys JointsService on destructor
2023-03-27 20:16:17 +03:00
NT_x86
f7a76511a8 Improved snap deletion and added remove function to instance class
The current issue is that sometimes after deleting a snap and closing the game it throws an access violation (race condition?)
2023-03-27 12:06:57 +03:00
NT_x86
9cee74baf4 Initial JointsService and Snap implementation
This is incomplete and some issues need to be fixed
2023-03-26 18:51:11 +03:00
18 changed files with 237 additions and 109 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8.00"
Version="8,00"
Name="Blocks3D"
ProjectGUID="{6C4D6EEF-B1D1-456A-B850-92CAB17124BE}"
RootNamespace="Blocks3D"
@@ -439,6 +439,10 @@
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\source\DataModelV2\JointsService.cpp"
>
</File>
<File
RelativePath=".\src\source\DataModelV2\LevelInstance.cpp"
>
@@ -510,11 +514,11 @@
</FileConfiguration>
</File>
<File
RelativePath=".\src\source\DataModelV2\RunServiceInstance.cpp"
RelativePath=".\src\source\DataModelV2\SelectionService.cpp"
>
</File>
<File
RelativePath=".\src\source\DataModelV2\SelectionService.cpp"
RelativePath=".\src\source\DataModelV2\SnapInstance.cpp"
>
</File>
<File
@@ -890,6 +894,10 @@
RelativePath=".\src\include\DataModelV2\Instance.h"
>
</File>
<File
RelativePath=".\src\include\DataModelV2\JointsService.h"
>
</File>
<File
RelativePath=".\src\include\DataModelV2\LevelInstance.h"
>
@@ -907,11 +915,11 @@
>
</File>
<File
RelativePath=".\src\include\DataModelV2\RunServiceInstance.h"
RelativePath=".\src\include\DataModelV2\SelectionService.h"
>
</File>
<File
RelativePath=".\src\include\DataModelV2\SelectionService.h"
RelativePath=".\src\include\DataModelV2\SnapInstance.h"
>
</File>
<File

View File

@@ -10,7 +10,7 @@
#include "XplicitNgine/XplicitNgine.h"
#include "SoundService.h"
#include "LightingInstance.h"
#include "RunServiceInstance.h"
#include "JointsService.h"
// Libraries
#include "rapidxml/rapidxml.hpp"
@@ -38,8 +38,8 @@ public:
XplicitNgine* getEngine();
ThumbnailGeneratorInstance* getThumbnailGenerator();
SoundService* getSoundService();
JointsService* getJointsService();
LightingInstance* getLighting();
RunService* getRunService();
std::string message;
std::string _loadedFileName;
@@ -49,7 +49,7 @@ public:
SelectionService* getSelectionService();
PartInstance* makePart();
void clearLevel();
void toggleRun(bool doRun);
void toggleRun();
bool isRunning();
void resetEngine();
#if _DEBUG
@@ -74,8 +74,7 @@ private:
XplicitNgine* xplicitNgine;
SoundService* soundService;
LightingInstance* lightingInstance;
RunService* runService;
JointsService* jointsService;
bool running;
};

View File

@@ -16,6 +16,7 @@ public:
virtual void update();
std::vector<Instance*> children; // All children.
std::string getClassName();
bool Instance::isA(std::string name);
Instance* findFirstChild(std::string);
std::vector<Instance* > getChildren();
std::vector<Instance* > getAllChildren();
@@ -25,6 +26,7 @@ public:
void removeChild(Instance*);
void clearChildren();
Instance* getParent();
void remove();
virtual Instance* clone() const { return new Instance(*this); }
virtual std::vector<PROPGRIDITEM> getProperties();
virtual void PropUpdate(LPPROPGRIDITEM &pItem);

View File

@@ -0,0 +1,15 @@
#pragma once
#include "Instance.h"
#include "PartInstance.h"
class JointsService:
public Instance
{
public:
JointsService(void);
~JointsService(void);
void createSnap(PartInstance* Part1, PartInstance* Part2);
void destroyPartSnap(PartInstance* Part);
void JointsService::solvePartSnap(PartInstance* Part, PartInstance* Part2);
void JointsService::solveWorkspaceSnaps();
};

View File

@@ -1,14 +0,0 @@
#pragma once
#include "Instance.h"
class RunService :
public Instance
{
public:
RunService(void);
~RunService(void);
void run();
void pause();
void reset();
};

View File

@@ -0,0 +1,14 @@
#pragma once
#include "Instance.h"
#include "PartInstance.h"
class SnapInstance:
public Instance
{
public:
SnapInstance(PartInstance* Part1, PartInstance* Part2);
~SnapInstance(void);
PartInstance* jPart1;
PartInstance* jPart2;
dJointID JointID;
};

View File

@@ -12,4 +12,3 @@ public:
void zoomToExtents();
std::vector<PartInstance *> partObjects;
};

View File

@@ -17,4 +17,6 @@ public:
void deleteBody(PartInstance* partInstance);
void updateBody(PartInstance* partInstance);
void resetBody(PartInstance* partInstance);
dJointID createJoint(PartInstance *part1, PartInstance *part2);
void destroyJoints(PartInstance *part);
};

View File

@@ -9,6 +9,7 @@
#include "DataModelV2/DataModelInstance.h"
#include "DataModelV2/GuiRootInstance.h"
#include "XplicitNgine/XplicitNgine.h"
#include "DataModelV2/JointsService.h"
#include "CameraController.h"
#include "AudioPlayer.h"
#include "Globals.h"
@@ -192,8 +193,6 @@ void Application::onInit() {
tool = new Tool();
// Called before Application::run() beings
cameraController.setFrame(Vector3(0,2,10));
cameraController.Zoom(-1);
_dataModel = new DataModelInstance();
_dataModel->setParent(NULL);
_dataModel->setName("undefined");
@@ -202,11 +201,16 @@ void Application::onInit() {
#ifdef LEGACY_LOAD_G3DFUN_LEVEL
// Anchored this baseplate for XplicitNgine tests
//XplicitNgine ngine;
PartInstance* test = makePart();
PartInstance* test2;
PartInstance* test3;
JointsService* JointsSvc = g_dataModel->getJointsService();
test->setParent(_dataModel->getWorkspace());
test->color = Color3(0.2F,0.3F,1);
test->setSize(Vector3(24,1,24));
test->setPosition(Vector3(0,0,0));
test->setPosition(Vector3(0,-10,0));
test->setCFrame(test->getCFrame() * Matrix3::fromEulerAnglesXYZ(0,toRadians(0),toRadians(0)));
test->setSurface(TOP, Enum::SurfaceType::Bumps);
test->setAnchored(true);
@@ -225,12 +229,12 @@ void Application::onInit() {
test->setPosition(Vector3(10,1,0));
test->setSurface(TOP, Enum::SurfaceType::Bumps);
test = makePart();
test->setParent(_dataModel->getWorkspace());
test->color = Color3::gray();
test->setSize(Vector3(4,1,2));
test->setPosition(Vector3(7,2,0));
test->setSurface(TOP, Enum::SurfaceType::Bumps);
test2 = makePart();
test2->setParent(_dataModel->getWorkspace());
test2->color = Color3::red();
test2->setSize(Vector3(4,1,2));
test2->setPosition(Vector3(7,2,0));
test2->setSurface(TOP, Enum::SurfaceType::Bumps);
test = makePart();
test->setParent(_dataModel->getWorkspace());
@@ -239,12 +243,14 @@ void Application::onInit() {
test->setPosition(Vector3(-7,2,0));
test->setSurface(TOP, Enum::SurfaceType::Bumps);
test = makePart();
test->setParent(_dataModel->getWorkspace());
test->color = Color3::gray();
test->setSize(Vector3(4,1,2));
test->setPosition(Vector3(4,3,0));
test->setSurface(TOP, Enum::SurfaceType::Bumps);
test3 = makePart();
test3->setParent(_dataModel->getWorkspace());
test3->color = Color3::red();
test3->setSize(Vector3(4,1,2));
test3->setPosition(Vector3(4,3,0));
test3->setSurface(TOP, Enum::SurfaceType::Bumps);
//JointsSvc->createSnap(test2, test3);
test = makePart();
test->setParent(_dataModel->getWorkspace());
@@ -255,10 +261,12 @@ void Application::onInit() {
test = makePart();
test->setParent(_dataModel->getWorkspace());
test->color = Color3::gray();
test->color = Color3::red();
test->setSize(Vector3(4,1,2));
test->setPosition(Vector3(1,4,0));
test->setSurface(TOP, Enum::SurfaceType::Bumps);
//JointsSvc->createSnap(test, test3);
//JointsSvc->solvePartSnap(test3, test);
test = makePart();
test->setParent(_dataModel->getWorkspace());
@@ -287,6 +295,8 @@ void Application::onInit() {
test->setSize(Vector3(4,1,2));
test->setPosition(Vector3(2,7,0));
test->setSurface(TOP, Enum::SurfaceType::Bumps);
JointsSvc->solveWorkspaceSnaps();
#else
_dataModel->debugGetOpen();
#endif
@@ -340,7 +350,6 @@ void Application::onSimulation(RealTime rdt, SimTime sdt, SimTime idt) {
_dataModel->getEngine()->step(0.03F);
}
onLogic();
}
_dataModel->getGuiRoot()->update();

View File

@@ -25,12 +25,10 @@ DataModelInstance::DataModelInstance(void)
workspace = new WorkspaceInstance();
guiRoot = new GuiRootInstance();
level = new LevelInstance();
runService = new RunService();
//thumbnailGenerator = new ThumbnailGeneratorInstance();
thumbnailGenerator = new ThumbnailGeneratorInstance();
soundService = new SoundService();
lightingInstance = new LightingInstance();
jointsService = new JointsService();
selectionService = new SelectionService();
selectionService->setPropertyWindow(g_usableApp->_propWindow);
@@ -44,6 +42,7 @@ DataModelInstance::DataModelInstance(void)
level->setParent(this);
soundService->setParent(this);
lightingInstance->setParent(this);
jointsService->setParent(this);
_loadedFileName="..//skooter.rbxm";
listicon = 5;
@@ -70,10 +69,9 @@ XplicitNgine * DataModelInstance::getEngine()
return xplicitNgine;
}
// Please use RunService->run(); & RunService->pause(); instead
void DataModelInstance::toggleRun(bool doRun)
void DataModelInstance::toggleRun()
{
running = doRun;
running = !running;
//if(!running)
//resetEngine();
}
@@ -94,6 +92,7 @@ void DataModelInstance::modXMLLevel(float modY)
_modY += modY;
clearLevel();
debugGetOpen();
}
#endif
@@ -505,8 +504,12 @@ bool DataModelInstance::load(const char* filename, bool clearObjects)
std::string tname = hname.substr(0, hname.length() - 5);
name = tname;
resetEngine();
//HACK: we need to reset JointsService but there is no good way to do it in XplicitNgine code
jointsService = new JointsService();
jointsService->setParent(this);
selectionService->clearSelection();
selectionService->addSelected(this);
jointsService->solveWorkspaceSnaps();
return true;
}
else
@@ -645,7 +648,6 @@ void DataModelInstance::drawMessage(RenderDevice* rd)
}
}
// Instance getters
WorkspaceInstance* DataModelInstance::getWorkspace()
{
return workspace;
@@ -676,12 +678,12 @@ SoundService* DataModelInstance::getSoundService()
return soundService;
}
JointsService* DataModelInstance::getJointsService()
{
return jointsService;
}
LightingInstance* DataModelInstance::getLighting()
{
return lightingInstance;
}
RunService* DataModelInstance::getRunService()
{
return runService;
}

View File

@@ -87,6 +87,7 @@ Instance::~Instance(void)
{
delete children.at(i);
}
setParent(NULL);
}
void Instance::setName(std::string newName)
@@ -99,6 +100,13 @@ std::string Instance::getClassName()
return className;
}
bool Instance::isA(std::string name)
{
if (className == name)
return true;
return false;
}
std::vector<Instance* > Instance::getChildren()
{
return children;
@@ -174,5 +182,7 @@ Instance* Instance::findFirstChild(std::string name)
return NULL;
}
void Instance::remove()
{
delete this;
}

View File

@@ -0,0 +1,69 @@
#include "DataModelV2/JointsService.h"
#include "DataModelV2/SnapInstance.h"
#include "StringFunctions.h"
#include "Globals.h"
JointsService::JointsService()
{
name = "JointsService";
className = "JointsService";
canDelete = false;
}
JointsService::~JointsService(void)
{
}
void JointsService::createSnap(PartInstance* Part1, PartInstance* Part2)
{
SnapInstance* Snap = new SnapInstance(Part1, Part2);
Snap->setParent(this);
}
void JointsService::destroyPartSnap(PartInstance* Part)
{
std::vector<Instance* > children = getChildren();
for(size_t i = 0; i < children.size(); i++)
{
SnapInstance* Snap = (SnapInstance*)children.at(i);
if((Snap->jPart1 == Part) || (Snap->jPart2 == Part))
{
Snap->remove();
}
}
}
void JointsService::solvePartSnap(PartInstance* Part1, PartInstance* Part2)
{
XplicitNgine* Phys = g_dataModel->getEngine();
float TopSurface = (Part1->getPosition().y + Part1->getSize().y / 2);
float BottomSurface2 = (Part2->getPosition().y - Part2->getSize().y / 2);
const int N = 4;
if (TopSurface == BottomSurface2)
{
Phys->createBody(Part1);
Phys->createBody(Part2);
dContact contact[N];
int n = dCollide (Part1->physGeom[0],Part2->physGeom[0],N,&contact[0].geom,sizeof(dContact));
if (n > 0)
createSnap(Part1, Part2);
}
}
void JointsService::solveWorkspaceSnaps()
{
std::vector<Instance* > children = g_dataModel->getWorkspace()->getAllChildren();
for(size_t i = 0; i < children.size(); i++)
{
PartInstance* Part1 = (PartInstance*)children.at(i);
if (Part1->isA("Part"))
{
for(size_t c = 0; c < children.size(); c++) //horrible
{
PartInstance* Part2 = (PartInstance*)children.at(c);
if (Part1 != Part2)
solvePartSnap(Part1, Part2);
}
}
}
}

View File

@@ -183,26 +183,26 @@ void LevelInstance::winCondition()
{
DataModelInstance* DataModel = (DataModelInstance*)getParent(); //If level parent gets changed to something other than Datamodel it could cause nasty data corruption bugs
DataModel->setMessage(winMessage);
DataModel->getRunService()->pause();
DataModel->toggleRun();
}
void LevelInstance::loseCondition()
{
DataModelInstance* DataModel = (DataModelInstance*)getParent();
DataModel->setMessage(loseMessage);
DataModel->getRunService()->pause();
DataModel->toggleRun();
}
void LevelInstance::pauseCondition()
{
DataModelInstance* DataModel = (DataModelInstance*)getParent();
DataModel->getRunService()->pause();
DataModel->toggleRun();
}
void LevelInstance::drawCondition()
{
DataModelInstance* DataModel = (DataModelInstance*)getParent();
DataModel->getRunService()->pause();
DataModel->toggleRun();
}
void LevelInstance::Step(SimTime sdt)

View File

@@ -398,6 +398,7 @@ void PartInstance::render(RenderDevice* rd) {
PartInstance::~PartInstance(void)
{
glDeleteLists(glList, 1);
/*
// Causes some weird ODE error
// Someone, please look into this

View File

@@ -1,36 +0,0 @@
#include "DataModelV2/RunServiceInstance.h"
#include "DataModelV2/ToggleImageButtonInstance.h"
#include "Globals.h"
RunService::RunService()
{
// Run Service, not RunService, because Roblox themselves did it. Why? IDK!
name = "Run Service";
className = "RunService";
canDelete = false;
}
RunService::~RunService(void)
{
}
void RunService::run()
{
// Tell GUI that we are running
Instance* go = g_dataModel->getGuiRoot()->findFirstChild("go");
g_dataModel->toggleRun(true);
((ToggleImageButtonInstance*)go)->checked = true;
}
void RunService::pause()
{
// Tell GUI that we paused
Instance* go = g_dataModel->getGuiRoot()->findFirstChild("go");
g_dataModel->toggleRun(false);
((ToggleImageButtonInstance*)go)->checked = false;
}
void RunService::reset()
{
// Can't really implement right now
}

View File

@@ -0,0 +1,29 @@
#include "DataModelV2/SnapInstance.h"
#include "XplicitNgine/XplicitNgine.h"
#include "StringFunctions.h"
#include "Globals.h"
SnapInstance::SnapInstance(PartInstance* Part1, PartInstance* Part2)
{
XplicitNgine* Phys = g_xplicitNgine;
name = "Snap";
className = "Snap";
jPart1 = Part1;
jPart2 = Part2;
if (Part1->physBody == NULL)
Phys->createBody(Part1);
if (Part2->physBody == NULL)
Phys->createBody(Part2);
JointID = Phys->createJoint(Part1, Part2);
}
SnapInstance::~SnapInstance(void)
{
//XplicitNgine* Phys = g_xplicitNgine;
printf("SnapInstance destroyed...");
if (JointID != NULL)
dJointDestroy(JointID);
}

View File

@@ -6,12 +6,8 @@ void MenuButtonListener::onButton1MouseClick(BaseButtonInstance* button)
{
if(button->name == "go")
{
bool isRunning = g_dataModel->isRunning();
if(isRunning)
g_dataModel->getRunService()->pause();
else
g_dataModel->getRunService()->run();
//((ToggleImageButtonInstance*)button)->checked = !isRunning;
g_dataModel->toggleRun();
((ToggleImageButtonInstance*)button)->checked = g_dataModel->isRunning();
}
else if(button->name == "file")
{

View File

@@ -1,9 +1,9 @@
#include "XplicitNgine/XplicitNgine.h"
#include "DataModelV2/JointsService.h"
#include "Globals.h"
XplicitNgine::XplicitNgine()
{
physWorld = dWorldCreate();
physSpace = dHashSpaceCreate(0);
contactgroup = dJointGroupCreate(0);
@@ -19,10 +19,11 @@ XplicitNgine::XplicitNgine()
XplicitNgine::~XplicitNgine()
{
dJointGroupDestroy (contactgroup);
dSpaceDestroy (physSpace);
dWorldDestroy (physWorld);
dCloseODE();
g_dataModel->getJointsService()->remove();
dJointGroupDestroy (contactgroup);
dSpaceDestroy (physSpace);
dWorldDestroy (physWorld);
dCloseODE();
}
void XplicitNgine::resetBody(PartInstance* partInstance)
@@ -81,6 +82,7 @@ void collisionCallback(void *data, dGeomID o1, dGeomID o2)
void XplicitNgine::deleteBody(PartInstance* partInstance)
{
g_dataModel->getJointsService()->destroyPartSnap(partInstance);
if(partInstance->physBody != NULL)
{
dBodyEnable(partInstance->physBody);
@@ -156,7 +158,8 @@ void XplicitNgine::createBody(PartInstance* partInstance)
dGeomSetData(partInstance->physGeom[0], partInstance);
dMass mass;
mass.setBox(sqrt(partSize.x*2), sqrt(partSize.y*2), sqrt(partSize.z*2), 0.7F);
mass.setBox(sqrt(partSize.x*20), sqrt(partSize.y*20), sqrt(partSize.z*20), 0.01F);
//mass.setBox(sqrt(partSize.x*2), sqrt(partSize.y*2), sqrt(partSize.z*2), 0.7F);
dBodySetMass(partInstance->physBody, &mass);
// Create rigid body
@@ -233,4 +236,24 @@ void XplicitNgine::updateBody(PartInstance *partInstance)
dBodySetRotation(partInstance->physBody, rotation);
}
}
dJointID XplicitNgine::createJoint(PartInstance *part1, PartInstance *part2)
{
printf("XplicitNgine::createJoint called\n");
if((part1->physBody != NULL) & (part2->physBody != NULL)){
printf("creating a fixed joint\n");
dJointID c = dJointCreateFixed(physWorld, 0);
dJointAttach(c, part1->physBody, part2->physBody);
dJointSetFixed(c);
return c;
}
return NULL;
}
void XplicitNgine::destroyJoints(PartInstance *part)
{
for(int i = 0; i < dBodyGetNumJoints(part->physBody); i++)
dJointDestroy(dBodyGetJoint(part->physBody, i));
}