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
material InstancedMaterial {
receive_shadows on

View File

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

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- exporter: blender2ogre 0.8.3 -->
<!-- export_time: Thu, 20 Jul 2023 08:20:08 +0000 -->
<!-- previous_export_time: Mon, 17 Jul 2023 06:58:22 +0000 -->
<!-- export_time: Sat, 22 Jul 2023 02:01:11 +0000 -->
<!-- previous_export_time: Thu, 20 Jul 2023 08:20:08 +0000 -->
<scene author="caesium" formatVersion="1.1" >
<nodes >
<node name="Cube" >
@ -13,26 +13,7 @@
</entity>
</node>
</nodes>
<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>
<externals />
<environment >
<colourBackground b="0.050876" g="0.050876" r="0.050876" />
</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/World/World.hpp
Header/App/V8/World/Weld.hpp
Header/App/V8/World/JointsService.hpp
Header/App/V8/World/ComPlicitNgine.hpp
Header/App/CoordinateFrame.hpp
Header/App/BrickColor.hpp
@ -67,6 +68,7 @@ add_library(Engine STATIC
Source/App/InputManager.cpp
Source/App/V8/World/World.cpp
Source/App/V8/World/Weld.cpp
Source/App/V8/World/JointsService.cpp
Source/App/V8/World/ComPlicitNgine.cpp
Source/Network/GUID.cpp
Source/Network/Player.cpp

View File

@ -1,12 +1,42 @@
#pragma once
#include <App/V8/Tree/PVInstance.hpp>
#include <App/BrickColor.hpp>
#include <Helpers/NormalId.hpp>
#include <OGRE/Ogre.h>
#define STUD_HEIGHT 1.18
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
{
protected:
@ -14,6 +44,7 @@ namespace RNR
float m_transparency;
float m_reflectance;
bool m_anchored;
PartSurfaceInfo m_surfaces[__NORM_COUNT];
Ogre::Matrix4 m_matrix;
Ogre::Vector3 m_position;
Ogre::Vector3 m_size;
@ -25,9 +56,11 @@ namespace RNR
PartInstance();
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"; }
void setSize(Ogre::Vector3 size) { m_size = size; }
void setSize(Ogre::Vector3 size) { m_size = size; updateSurfaces(); }
Ogre::Vector3 getSize() { return m_size; }
Ogre::Vector4 getColor() { return m_color; }
@ -38,6 +71,10 @@ namespace RNR
void setAnchored(bool anchored) { m_anchored = anchored; }
bool getAnchored() { return m_anchored; }
void makeJoints();
void breakJoints();
void updateSurfaces();
Ogre::Vector3 getOgreCenter() { return m_position + (m_size / 2.f); }
void setBrickColor(int brickcolor) { m_brickColor = brickcolor; }

View File

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

View File

@ -30,6 +30,7 @@ namespace RNR
virtual void onDescendantRemoved(RNR::Instance* childRemoved);
void buildGeom();
void makeJoints();
Camera* getCurrentCamera() const;
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;
btFixedConstraint* m_constraint;
virtual void addProperties(std::vector<ReflectionProperty>& properties);
virtual void deserializeProperty(char* prop_name, pugi::xml_node prop);
public:
Weld();
~Weld();
virtual std::string getClassName() { return "Weld"; }
void weld(PartInstance* a, PartInstance* b);
void create();
bool create();
void destroy();
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 {
enum NormalId
{
NORM_X,
NORM_Y,
NORM_Z,
NORM_X_NEG,
NORM_Y_NEG,
NORM_Z_NEG,
NORM_UNDEFINED
NORM_X, NORM_RIGHT = NORM_X,
NORM_Y, NORM_UP = NORM_Y,
NORM_Z, NORM_BACK = NORM_Z,
NORM_X_NEG, NORM_LEFT = NORM_X_NEG,
NORM_Y_NEG, NORM_DOWN = NORM_Y_NEG,
NORM_Z_NEG, NORM_FRONT = NORM_Z_NEG,
__NORM_COUNT,
NORM_UNDEFINED,
};
bool validNormalId(NormalId normalId);

View File

@ -4,6 +4,36 @@
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)
{
setName("Part");
@ -16,6 +46,23 @@ namespace RNR
setObject(world->getOgreSceneManager()->createEntity("meshes/Cube.mesh"));
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();
}
@ -52,6 +99,51 @@ namespace RNR
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)
{
if(prop_name == std::string("size"))

View File

@ -16,6 +16,7 @@ namespace RNR
{
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->setNumCustomParams(2);
break;
case BATCH_STATIC_GEOMETRY:
m_geom = world->getOgreSceneManager()->createStaticGeometry("workspaceGeom");
@ -43,6 +44,7 @@ namespace RNR
replica->setOrientation(part->getCFrame().getRotation());
replica->setScale(part->getSize());
replica->setCastShadows(true);
replica->setCustomParam(0, Ogre::Vector4f(part->getSize().x, part->getSize().y, part->getSize().z, 0));
m_worldspawn->attachObject(replica);
childAdded->setObject(replica);
child_node->setVisible(false);
@ -56,6 +58,7 @@ namespace RNR
child_node->setVisible(false);
m_geomDirty = true;
break;
default:
case BATCH_DONT:
child_node->setVisible(true);
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);
}
void Weld::create()
bool Weld::create()
{
if(!m_aBody || !m_bBody)
{
printf("Weld::create: invalid body\n");
return;
return false;
}
btTransform frameInA, frameInB;
frameInA = btTransform::getIdentity();
frameInB = btTransform::getIdentity();
btTransform frameInA, frameInB;
frameInA = btTransform::getIdentity();
frameInB = btTransform::getIdentity();
m_constraint = new btFixedConstraint(*m_aBody, *m_bBody, frameInA, frameInB);
printf("Weld::create: welded\n");
return true;
}
void Weld::destroy()
@ -50,4 +51,25 @@ namespace RNR
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/JointsService.hpp>
#include <App/V8/Tree/InstanceFactory.hpp>
#include <App/V8/DataModel/PartInstance.hpp>
#include <App/V8/DataModel/Lighting.hpp>
@ -37,6 +38,7 @@ namespace RNR
m_instanceFactory->registerInstance("Players", InstanceFactory::instanceBuilder<Players>);
m_instanceFactory->registerInstance("Player", InstanceFactory::instanceBuilder<Player>);
m_instanceFactory->registerInstance("Lighting", InstanceFactory::instanceBuilder<Lighting>);
m_instanceFactory->registerInstance("JointsService", InstanceFactory::instanceBuilder<JointsService>);
m_ogreRoot = ogre;
m_ogreSceneManager = ogreSceneManager;
@ -107,6 +109,7 @@ namespace RNR
{
m_refs.clear();
JointsService* joints = (JointsService*)m_datamodel->getService("JointsService");
Camera* old_camera = m_workspace->getCurrentCamera();
if(old_camera)
{
@ -144,13 +147,19 @@ namespace RNR
ModelInstance* m = (ModelInstance*)s.instance;
m->build();
}
else if(s.instance->getClassName() == "Part")
{
PartInstance* p = (PartInstance*)s.instance;
joints->makeJoints(p);
}
}
}
else
{
printf("World::load: XML parsed with errors, description '%s', offset %i\n", result.description(), result.offset);
}
}
m_workspace->build();
joints->fixWelds();
}
void World::preRender(float timestep)