WIP JointsService

This commit is contained in:
floralrainfall 2023-07-22 01:41:01 -04:00
parent 1eeaad9ebe
commit 2f34afd1ae
18 changed files with 342 additions and 40 deletions

View File

@ -1,3 +1,10 @@
vertex_program InstancedMaterial/VertexProgram glsl
{
source shaders/InstancedShaer_f.glsl
syntax glsl330
}
// generated by blender2ogre 0.8.3 on 2023-07-20 04:32:47 // generated by blender2ogre 0.8.3 on 2023-07-20 04:32:47
material InstancedMaterial { material InstancedMaterial {
receive_shadows on receive_shadows on

View File

@ -19,11 +19,10 @@ material materials/PartInstanced
technique technique
{ {
shadow_caster_material materials/PartInstanced/shadow_caster
pass pass
{ {
specular 1 1 1 1 12.5 specular 1 1 1 1 64.5
lighting on lighting on
texture_unit texture_unit

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- exporter: blender2ogre 0.8.3 --> <!-- exporter: blender2ogre 0.8.3 -->
<!-- export_time: Thu, 20 Jul 2023 08:20:08 +0000 --> <!-- export_time: Sat, 22 Jul 2023 02:01:11 +0000 -->
<!-- previous_export_time: Mon, 17 Jul 2023 06:58:22 +0000 --> <!-- previous_export_time: Thu, 20 Jul 2023 08:20:08 +0000 -->
<scene author="caesium" formatVersion="1.1" > <scene author="caesium" formatVersion="1.1" >
<nodes > <nodes >
<node name="Cube" > <node name="Cube" >
@ -13,26 +13,7 @@
</entity> </entity>
</node> </node>
</nodes> </nodes>
<externals > <externals />
<item type="material" >
<file name="TopMaterial.material" />
</item>
<item type="material" >
<file name="BackMaterial.material" />
</item>
<item type="material" >
<file name="BottomMaterial.material" />
</item>
<item type="material" >
<file name="FrontMaterial.material" />
</item>
<item type="material" >
<file name="LeftMaterial.material" />
</item>
<item type="material" >
<file name="RightMaterial.material" />
</item>
</externals>
<environment > <environment >
<colourBackground b="0.050876" g="0.050876" r="0.050876" /> <colourBackground b="0.050876" g="0.050876" r="0.050876" />
</environment> </environment>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 B

View File

@ -28,6 +28,7 @@ add_library(Engine STATIC
Header/App/V8/Tree/ModelInstance.hpp Header/App/V8/Tree/ModelInstance.hpp
Header/App/V8/World/World.hpp Header/App/V8/World/World.hpp
Header/App/V8/World/Weld.hpp Header/App/V8/World/Weld.hpp
Header/App/V8/World/JointsService.hpp
Header/App/V8/World/ComPlicitNgine.hpp Header/App/V8/World/ComPlicitNgine.hpp
Header/App/CoordinateFrame.hpp Header/App/CoordinateFrame.hpp
Header/App/BrickColor.hpp Header/App/BrickColor.hpp
@ -67,6 +68,7 @@ add_library(Engine STATIC
Source/App/InputManager.cpp Source/App/InputManager.cpp
Source/App/V8/World/World.cpp Source/App/V8/World/World.cpp
Source/App/V8/World/Weld.cpp Source/App/V8/World/Weld.cpp
Source/App/V8/World/JointsService.cpp
Source/App/V8/World/ComPlicitNgine.cpp Source/App/V8/World/ComPlicitNgine.cpp
Source/Network/GUID.cpp Source/Network/GUID.cpp
Source/Network/Player.cpp Source/Network/Player.cpp

View File

@ -1,12 +1,42 @@
#pragma once #pragma once
#include <App/V8/Tree/PVInstance.hpp> #include <App/V8/Tree/PVInstance.hpp>
#include <App/BrickColor.hpp> #include <App/BrickColor.hpp>
#include <Helpers/NormalId.hpp>
#include <OGRE/Ogre.h> #include <OGRE/Ogre.h>
#define STUD_HEIGHT 1.18 #define STUD_HEIGHT 1.18
namespace RNR namespace RNR
{ {
enum PartSurfaceType
{
SURFACE_SMOOTH,
SURFACE_GLUE,
SURFACE_WELD,
SURFACE_STUDS,
SURFACE_INLET,
SURFACE_UNIVERSAL,
SURFACE_HINGE,
SURFACE_MOTOR,
SURFACE_STEPPINGMOTOR,
SURFACE_UNJOINABLE,
__SURFACE_COUNT,
};
struct PartSurfaceInfo
{
public:
NormalId face;
PartSurfaceType type;
Ogre::Vector2 start;
Ogre::Vector2 end;
float plane;
bool intersects(PartSurfaceInfo other);
bool links(PartSurfaceInfo other);
};
class PartInstance : public PVInstance class PartInstance : public PVInstance
{ {
protected: protected:
@ -14,6 +44,7 @@ namespace RNR
float m_transparency; float m_transparency;
float m_reflectance; float m_reflectance;
bool m_anchored; bool m_anchored;
PartSurfaceInfo m_surfaces[__NORM_COUNT];
Ogre::Matrix4 m_matrix; Ogre::Matrix4 m_matrix;
Ogre::Vector3 m_position; Ogre::Vector3 m_position;
Ogre::Vector3 m_size; Ogre::Vector3 m_size;
@ -25,9 +56,11 @@ namespace RNR
PartInstance(); PartInstance();
void updateMatrix(); void updateMatrix();
PartSurfaceInfo& getSurface(NormalId normal) { return m_surfaces[normal]; };
void setSurface(NormalId normal, PartSurfaceInfo surface) { m_surfaces[normal] = surface; }
virtual std::string getClassName() { return "Part"; } virtual std::string getClassName() { return "Part"; }
void setSize(Ogre::Vector3 size) { m_size = size; } void setSize(Ogre::Vector3 size) { m_size = size; updateSurfaces(); }
Ogre::Vector3 getSize() { return m_size; } Ogre::Vector3 getSize() { return m_size; }
Ogre::Vector4 getColor() { return m_color; } Ogre::Vector4 getColor() { return m_color; }
@ -38,6 +71,10 @@ namespace RNR
void setAnchored(bool anchored) { m_anchored = anchored; } void setAnchored(bool anchored) { m_anchored = anchored; }
bool getAnchored() { return m_anchored; } bool getAnchored() { return m_anchored; }
void makeJoints();
void breakJoints();
void updateSurfaces();
Ogre::Vector3 getOgreCenter() { return m_position + (m_size / 2.f); } Ogre::Vector3 getOgreCenter() { return m_position + (m_size / 2.f); }
void setBrickColor(int brickcolor) { m_brickColor = brickcolor; } void setBrickColor(int brickcolor) { m_brickColor = brickcolor; }

View File

@ -14,7 +14,7 @@ namespace RNR
virtual void addProperties(std::vector<ReflectionProperty>& properties); virtual void addProperties(std::vector<ReflectionProperty>& properties);
public: public:
RunService(); RunService();
virtual std::string getClassName() { return "RunService"; } virtual std::string getClassName() { return "RunService"; }
bool getRunning() { return m_running; } bool getRunning() { return m_running; }

View File

@ -30,6 +30,7 @@ namespace RNR
virtual void onDescendantRemoved(RNR::Instance* childRemoved); virtual void onDescendantRemoved(RNR::Instance* childRemoved);
void buildGeom(); void buildGeom();
void makeJoints();
Camera* getCurrentCamera() const; Camera* getCurrentCamera() const;
void setCurrentCamera(Camera *value); void setCurrentCamera(Camera *value);

View File

@ -0,0 +1,23 @@
#pragma once
#include <App/V8/Tree/Instance.hpp>
#include <App/V8/DataModel/PartInstance.hpp>
#include <App/V8/World/Weld.hpp>
namespace RNR
{
class JointsService : public Instance
{
public:
JointsService();
virtual std::string getClassName() { return "JointsService"; }
Snap* snap(PartInstance* a, PartInstance* b);
void makeJoints(Instance* w, PartInstance* p);
void makeJoints(PartInstance* p);
void fixWelds();
void breakJoints(PartInstance* b);
bool isWelded(PartInstance* a, PartInstance* b);
};
}

View File

@ -14,15 +14,28 @@ namespace RNR
PartInstance* m_bInstance; PartInstance* m_bInstance;
btFixedConstraint* m_constraint; btFixedConstraint* m_constraint;
virtual void addProperties(std::vector<ReflectionProperty>& properties);
virtual void deserializeProperty(char* prop_name, pugi::xml_node prop);
public: public:
Weld(); Weld();
~Weld(); ~Weld();
virtual std::string getClassName() { return "Weld"; } virtual std::string getClassName() { return "Weld"; }
void weld(PartInstance* a, PartInstance* b); void weld(PartInstance* a, PartInstance* b);
void create(); bool create();
void destroy(); void destroy();
bool getBroken(); bool getBroken();
PartInstance* getPartA() { return m_aInstance; }
PartInstance* getPartB() { return m_bInstance; }
};
class Snap : public Weld
{
// they're basically the same
public:
virtual std::string getClassName() { return "Snap"; }
virtual std::string getExplorerIcon() { return "Weld"; }
}; };
} }

View File

@ -5,13 +5,14 @@
namespace RNR { namespace RNR {
enum NormalId enum NormalId
{ {
NORM_X, NORM_X, NORM_RIGHT = NORM_X,
NORM_Y, NORM_Y, NORM_UP = NORM_Y,
NORM_Z, NORM_Z, NORM_BACK = NORM_Z,
NORM_X_NEG, NORM_X_NEG, NORM_LEFT = NORM_X_NEG,
NORM_Y_NEG, NORM_Y_NEG, NORM_DOWN = NORM_Y_NEG,
NORM_Z_NEG, NORM_Z_NEG, NORM_FRONT = NORM_Z_NEG,
NORM_UNDEFINED __NORM_COUNT,
NORM_UNDEFINED,
}; };
bool validNormalId(NormalId normalId); bool validNormalId(NormalId normalId);

View File

@ -4,6 +4,36 @@
namespace RNR namespace RNR
{ {
bool PartSurfaceInfo::intersects(PartSurfaceInfo other)
{
if(other.plane != plane)
return false;
if(start.x > other.end.x || other.start.x > end.x)
return false;
if(end.y > other.start.y || other.end.y > start.y)
return false;
return true;
}
bool PartSurfaceInfo::links(PartSurfaceInfo other)
{
bool allowed_surf[__SURFACE_COUNT][__SURFACE_COUNT] = {
// SMOOTH, GLUE, WELD, STUDS, INLET, UNIVERSAL, HINGE, MOTOR, STEPPINGMOTOR, UNJOINABLE
{ false, false, false, false, false, false, false, false, false, false }, // SMOOTH
{ true, true, true, true, true, true, false, false, false, false }, // GLUE
{ true, true, true, true, true, true, false, false, false, false }, // WELD
{ false, false, false, false, true, true, false, false, false, false }, // STUDS
{ false, false, false, true, false, true, false, false, false, false }, // INLET
{ false, false, true, true, true, true, false, false, false, false }, // UNIVERSAL
{ true, true, true, true, true, true, false, false, false, false }, // HINGE
{ true, true, true, true, true, true, false, false, false, false }, // MOTOR
{ true, true, true, true, true, true, false, false, false, false }, // STEPPINGMOTOR
{ false, false, false, false, false, false, false, false, false, false }, // UNJOINABLE
};
return allowed_surf[type][other.type];
}
PartInstance::PartInstance() : m_matrix(), PVInstance(), m_size(2.f, STUD_HEIGHT, 4.f) PartInstance::PartInstance() : m_matrix(), PVInstance(), m_size(2.f, STUD_HEIGHT, 4.f)
{ {
setName("Part"); setName("Part");
@ -16,6 +46,23 @@ namespace RNR
setObject(world->getOgreSceneManager()->createEntity("meshes/Cube.mesh")); setObject(world->getOgreSceneManager()->createEntity("meshes/Cube.mesh"));
getNode()->attachObject(getObject()); getNode()->attachObject(getObject());
for(int i = 0; i < __NORM_COUNT; i++)
{
NormalId n = (NormalId)i;
switch(n)
{
case NORM_UP:
m_surfaces[i].type = SURFACE_STUDS;
break;
case NORM_DOWN:
m_surfaces[i].type = SURFACE_INLET;
break;
default:
m_surfaces[i].type = SURFACE_SMOOTH;
break;
}
}
updateMatrix(); updateMatrix();
} }
@ -52,6 +99,51 @@ namespace RNR
entity->setCastShadows(true); entity->setCastShadows(true);
} }
void PartInstance::updateSurfaces()
{
for(int i = 0; i < __NORM_COUNT; i++)
{
m_surfaces[i].face = (NormalId)i;
PartSurfaceInfo& surf = m_surfaces[i];
Ogre::Vector3 size = ((getSize() / 2.f) * getRotation());
Ogre::Vector3 pos = getPosition();
switch(m_surfaces[i].face)
{
case NORM_DOWN:
surf.start = Ogre::Vector2(pos.x-size.x,pos.z-size.z);
surf.end = Ogre::Vector2(pos.x+size.x,pos.z+size.z);
surf.plane = pos.y - size.y;
break;
case NORM_UP:
surf.start = Ogre::Vector2(pos.x-size.x,pos.z-size.z);
surf.end = Ogre::Vector2(pos.x+size.x,pos.z+size.z);
surf.plane = pos.y + size.y;
break;
case NORM_LEFT:
surf.start = Ogre::Vector2(pos.z-size.z,pos.y-size.y);
surf.end = Ogre::Vector2(pos.z+size.z,pos.y+size.y);
surf.plane = pos.z - size.z;
break;
case NORM_RIGHT:
surf.start = Ogre::Vector2(pos.z-size.z,pos.y-size.y);
surf.end = Ogre::Vector2(pos.z+size.z,pos.y+size.y);
surf.plane = pos.z + size.z;
break;
case NORM_FRONT:
surf.start = Ogre::Vector2(pos.z-size.z,pos.y-size.y);
surf.end = Ogre::Vector2(pos.z+size.z,pos.y+size.y);
surf.plane = pos.x + size.x;
break;
case NORM_BACK:
surf.start = Ogre::Vector2(pos.z-size.z,pos.y-size.y);
surf.end = Ogre::Vector2(pos.z+size.z,pos.y+size.y);
surf.plane = pos.x - size.x;
break;
}
}
}
void PartInstance::deserializeProperty(char* prop_name, pugi::xml_node node) void PartInstance::deserializeProperty(char* prop_name, pugi::xml_node node)
{ {
if(prop_name == std::string("size")) if(prop_name == std::string("size"))

View File

@ -16,6 +16,7 @@ namespace RNR
{ {
case BATCH_INSTANCED: case BATCH_INSTANCED:
m_instanceManager = world->getOgreSceneManager()->createInstanceManager("workspaceInstanceManager", "meshes/Cube_Instanced.mesh", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::InstanceManager::InstancingTechnique::HWInstancingBasic, 255); m_instanceManager = world->getOgreSceneManager()->createInstanceManager("workspaceInstanceManager", "meshes/Cube_Instanced.mesh", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::InstanceManager::InstancingTechnique::HWInstancingBasic, 255);
m_instanceManager->setNumCustomParams(2);
break; break;
case BATCH_STATIC_GEOMETRY: case BATCH_STATIC_GEOMETRY:
m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom"); m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom");
@ -43,6 +44,7 @@ namespace RNR
replica->setOrientation(part->getCFrame().getRotation()); replica->setOrientation(part->getCFrame().getRotation());
replica->setScale(part->getSize()); replica->setScale(part->getSize());
replica->setCastShadows(true); replica->setCastShadows(true);
replica->setCustomParam(0, Ogre::Vector4f(part->getSize().x, part->getSize().y, part->getSize().z, 0));
m_worldspawn->attachObject(replica); m_worldspawn->attachObject(replica);
childAdded->setObject(replica); childAdded->setObject(replica);
child_node->setVisible(false); child_node->setVisible(false);
@ -56,6 +58,7 @@ namespace RNR
child_node->setVisible(false); child_node->setVisible(false);
m_geomDirty = true; m_geomDirty = true;
break; break;
default:
case BATCH_DONT: case BATCH_DONT:
child_node->setVisible(true); child_node->setVisible(true);
break; break;

View File

@ -0,0 +1,112 @@
#include <App/V8/World/JointsService.hpp>
#include <App/V8/World/World.hpp>
namespace RNR
{
JointsService::JointsService()
{
setName("JointsService");
}
Snap* JointsService::snap(PartInstance* a, PartInstance* b)
{
Snap* snap = new Snap();
snap->weld(a, b);
snap->setParent(this);
return snap;
}
void JointsService::fixWelds()
{
for(auto& child : *getChildren())
{
Weld* weld = dynamic_cast<Weld*>(child);
weld->create();
}
}
void JointsService::makeJoints(Instance* w, PartInstance* p)
{
for(auto& child : *w->getChildren())
{
if(child == p)
continue;
PartInstance* child_p = dynamic_cast<PartInstance*>(child);
if(child_p)
{
if(isWelded(child_p, p))
continue;
if(p == child_p)
continue;
child_p->updateSurfaces();
for(int i = 0; i < __NORM_COUNT; i++)
{
NormalId n = (NormalId)i;
NormalId n_opp = normalIdOpposite(n);
PartSurfaceInfo n_surf = p->getSurface(n);
PartSurfaceInfo n_opp_surf = child_p->getSurface(n_opp);
if(n_surf.plane != n_opp_surf.plane)
continue;
if(n_surf.intersects(n_opp_surf))
{
if(n_surf.links(n_opp_surf))
{
// determine link
switch(n_surf.type)
{
case SURFACE_WELD:
case SURFACE_STUDS:
case SURFACE_INLET:
snap(p, child_p);
break;
}
}
}
}
}
makeJoints(child, p);
}
}
void JointsService::makeJoints(PartInstance* p)
{
p->updateSurfaces();
makeJoints(world->getWorkspace(), p);
}
void JointsService::breakJoints(PartInstance* p)
{
for(auto& child : *getChildren())
{
Snap* snap = dynamic_cast<Snap*>(child);
if(snap)
{
bool brk = false;
if(snap->getPartA() == p)
brk = true;
else if(snap->getPartB() == p)
brk = true;
if(brk)
{
}
}
}
}
bool JointsService::isWelded(PartInstance* a, PartInstance* b)
{
for(auto& child : *getChildren())
{
Weld* snap = dynamic_cast<Weld*>(child);
if(snap)
{
if(snap->getPartA() == a && snap->getPartB() == b)
return true;
else if(snap->getPartA() == b && snap->getPartB() == a)
return true;
}
}
return false;
}
}

View File

@ -22,20 +22,21 @@ namespace RNR
m_bBody = world->getComPlicitNgine()->getBody(b); m_bBody = world->getComPlicitNgine()->getBody(b);
} }
void Weld::create() bool Weld::create()
{ {
if(!m_aBody || !m_bBody) if(!m_aBody || !m_bBody)
{ {
printf("Weld::create: invalid body\n"); printf("Weld::create: invalid body\n");
return; return false;
} }
btTransform frameInA, frameInB; btTransform frameInA, frameInB;
frameInA = btTransform::getIdentity(); frameInA = btTransform::getIdentity();
frameInB = btTransform::getIdentity(); frameInB = btTransform::getIdentity();
m_constraint = new btFixedConstraint(*m_aBody, *m_bBody, frameInA, frameInB); m_constraint = new btFixedConstraint(*m_aBody, *m_bBody, frameInA, frameInB);
printf("Weld::create: welded\n"); printf("Weld::create: welded\n");
return true;
} }
void Weld::destroy() void Weld::destroy()
@ -50,4 +51,25 @@ namespace RNR
return false; return false;
} }
void Weld::addProperties(std::vector<ReflectionProperty>& properties)
{
ReflectionProperty _properties[] = {
{ this, std::string("Part0"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_INSTANCE,
REFLECTION_GETTER(Weld* instance = (Weld*)object; return instance->m_aInstance; ),
REFLECTION_SETTER(Weld* instance = (Weld*)object; ) },
{ this, std::string("Part1"), std::string(""),
ACCESS_NONE, OPERATION_READWRITE, PROPERTY_INSTANCE,
REFLECTION_GETTER(Weld* instance = (Weld*)object; return instance->m_bInstance; ),
REFLECTION_SETTER(Weld* instance = (Weld*)object; ) },
};
properties.insert(properties.end(), _properties, _properties+(sizeof(_properties)/sizeof(ReflectionProperty)));
}
void Weld::deserializeProperty(char* prop_name, pugi::xml_node prop)
{
}
} }

View File

@ -1,4 +1,5 @@
#include <App/V8/World/World.hpp> #include <App/V8/World/World.hpp>
#include <App/V8/World/JointsService.hpp>
#include <App/V8/Tree/InstanceFactory.hpp> #include <App/V8/Tree/InstanceFactory.hpp>
#include <App/V8/DataModel/PartInstance.hpp> #include <App/V8/DataModel/PartInstance.hpp>
#include <App/V8/DataModel/Lighting.hpp> #include <App/V8/DataModel/Lighting.hpp>
@ -37,6 +38,7 @@ namespace RNR
m_instanceFactory->registerInstance("Players", InstanceFactory::instanceBuilder<Players>); m_instanceFactory->registerInstance("Players", InstanceFactory::instanceBuilder<Players>);
m_instanceFactory->registerInstance("Player", InstanceFactory::instanceBuilder<Player>); m_instanceFactory->registerInstance("Player", InstanceFactory::instanceBuilder<Player>);
m_instanceFactory->registerInstance("Lighting", InstanceFactory::instanceBuilder<Lighting>); m_instanceFactory->registerInstance("Lighting", InstanceFactory::instanceBuilder<Lighting>);
m_instanceFactory->registerInstance("JointsService", InstanceFactory::instanceBuilder<JointsService>);
m_ogreRoot = ogre; m_ogreRoot = ogre;
m_ogreSceneManager = ogreSceneManager; m_ogreSceneManager = ogreSceneManager;
@ -107,6 +109,7 @@ namespace RNR
{ {
m_refs.clear(); m_refs.clear();
JointsService* joints = (JointsService*)m_datamodel->getService("JointsService");
Camera* old_camera = m_workspace->getCurrentCamera(); Camera* old_camera = m_workspace->getCurrentCamera();
if(old_camera) if(old_camera)
{ {
@ -144,13 +147,19 @@ namespace RNR
ModelInstance* m = (ModelInstance*)s.instance; ModelInstance* m = (ModelInstance*)s.instance;
m->build(); m->build();
} }
else if(s.instance->getClassName() == "Part")
{
PartInstance* p = (PartInstance*)s.instance;
joints->makeJoints(p);
}
} }
} }
else else
{ {
printf("World::load: XML parsed with errors, description '%s', offset %i\n", result.description(), result.offset); printf("World::load: XML parsed with errors, description '%s', offset %i\n", result.description(), result.offset);
} }
m_workspace->build(); m_workspace->build();
joints->fixWelds();
} }
void World::preRender(float timestep) void World::preRender(float timestep)