mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-04 20:57:49 +00:00
673 lines
25 KiB
C++
673 lines
25 KiB
C++
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
|
|
#include "stdafx.h"
|
|
|
|
#include "V8DataModel/ManualJointHelper.h"
|
|
#include "GfxBase/IAdornableCollector.h"
|
|
#include "V8World/World.h"
|
|
#include "Tool/DragUtilities.h"
|
|
#include "V8World/ContactManager.h"
|
|
#include "V8World/Contact.h"
|
|
#include "V8World/Joint.h"
|
|
#include "V8World/WeldJoint.h"
|
|
#include "V8World/MegaClusterPoly.h"
|
|
#include "Tool/ToolsArrow.h"
|
|
|
|
#include "Humanoid/Humanoid.h"
|
|
#include "V8DataModel/Workspace.h"
|
|
#include "V8DataModel/PartInstance.h"
|
|
#include "V8DataModel/PVInstance.h"
|
|
#include "V8DataModel/JointInstance.h"
|
|
#include "V8DataModel/MegaCluster.h"
|
|
|
|
namespace RBX {
|
|
|
|
const float autoJointLineThickness = 0.1f;
|
|
|
|
ManualJointHelper::~ManualJointHelper()
|
|
{
|
|
if( workspace && isAdornable )
|
|
workspace->getAdornableCollector()->onRenderableDescendantRemoving(this);
|
|
|
|
// Clear the existing part/surface pairs containers
|
|
for( unsigned int i = 0; i < jointSurfacePairs.size(); i++ )
|
|
delete jointSurfacePairs[i];
|
|
|
|
jointSurfacePairs.clear();
|
|
autoJointsDetected = false;
|
|
}
|
|
|
|
ManualJointHelper::ManualJointHelper(Workspace* ws)
|
|
{
|
|
workspace = NULL;
|
|
displayPotentialJoints = AdvArrowTool::advManualJointMode;
|
|
isAdornable = false;
|
|
autoJointsDetected = false;
|
|
targetPrimitive = NULL;
|
|
setWorkspace(ws);
|
|
}
|
|
|
|
ManualJointHelper::ManualJointHelper(void)
|
|
{
|
|
workspace = NULL;
|
|
displayPotentialJoints = AdvArrowTool::advManualJointMode;
|
|
isAdornable = false;
|
|
autoJointsDetected = false;
|
|
targetPrimitive = NULL;
|
|
}
|
|
|
|
void ManualJointHelper::clearAndDeleteJointSurfacePairs(void)
|
|
{
|
|
// Clear the existing part/surface pairs containers
|
|
for( unsigned int i = 0; i < jointSurfacePairs.size(); i++ )
|
|
delete jointSurfacePairs[i];
|
|
|
|
jointSurfacePairs.clear();
|
|
autoJointsDetected = false;
|
|
}
|
|
|
|
void ManualJointHelper::setWorkspace(Workspace* ws)
|
|
{
|
|
if( !workspace )
|
|
{
|
|
workspace = ws;
|
|
if( !isAdornable )
|
|
{
|
|
workspace->getAdornableCollector()->onRenderableDescendantAdded(this);
|
|
isAdornable = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
void ManualJointHelper::findPermissibleJointSurfacePairs(void)
|
|
{
|
|
// Clear the existing part/surface pairs containers
|
|
clearAndDeleteJointSurfacePairs();
|
|
|
|
// find other parts that are contacting the selected parts
|
|
for( unsigned int i = 0; i < selectedPrimitives.size(); i++ )
|
|
{
|
|
G3D::Array<Primitive*> found;
|
|
size_t selectedPrimSurf = (size_t)-1;
|
|
size_t foundPrimSurf = (size_t)-1;
|
|
if(workspace)
|
|
{
|
|
workspace->getWorld()->getContactManager()->getPrimitivesTouchingExtents(selectedPrimitives[i]->getFastFuzzyExtents(), selectedPrimitives[i], 0, found);
|
|
for( int j = 0; j < found.size(); j++ )
|
|
{
|
|
if( !selectedPrimitives[i]->getGeometry()->isTerrain() )
|
|
{
|
|
if( std::find(selectedPrimitives.begin(), selectedPrimitives.end(), found[j])== selectedPrimitives.end() )
|
|
{
|
|
if( found[j]->getConstGeometry()->findTouchingSurfacesConvex(found[j]->getCoordinateFrame(), foundPrimSurf,
|
|
*(selectedPrimitives[i]->getConstGeometry()), selectedPrimitives[i]->getCoordinateFrame(), selectedPrimSurf) )
|
|
createJointSurfacePair(*found[j], foundPrimSurf, *selectedPrimitives[i], selectedPrimSurf);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// add in joints with the terrain
|
|
Primitive* mCPrim = workspace->getWorld()->getContactManager()->getMegaClusterPrimitive();
|
|
|
|
if (mCPrim && mCPrim->getGeometryType() == Geometry::GEOMETRY_MEGACLUSTER)
|
|
{
|
|
for( unsigned int i = 0; i < selectedPrimitives.size(); i++ )
|
|
{
|
|
if( selectedPrimitives[i]->getGeometryType() != RBX::Geometry::GEOMETRY_MEGACLUSTER )
|
|
{
|
|
std::vector<Vector3int16> cells;
|
|
static_cast<const MegaClusterPoly*>(mCPrim->getConstGeometry())->findPlanarTouchesWithGeom(mCPrim->getCoordinateFrame(),
|
|
*(selectedPrimitives[i]->getConstGeometry()),
|
|
selectedPrimitives[i]->getCoordinateFrame(),
|
|
&cells);
|
|
|
|
// for each cell call createJointSurfacePair
|
|
for(size_t j = 0; j < cells.size(); ++j)
|
|
{
|
|
createTerrainJointSurfacePair(*mCPrim, *selectedPrimitives[i], cells[j]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mCPrim && mCPrim->getGeometryType() == Geometry::GEOMETRY_SMOOTHCLUSTER)
|
|
{
|
|
for( unsigned int i = 0; i < selectedPrimitives.size(); i++ )
|
|
{
|
|
Geometry::GeometryType geometryType = selectedPrimitives[i]->getGeometryType();
|
|
|
|
if (geometryType != Geometry::GEOMETRY_SMOOTHCLUSTER && geometryType != Geometry::GEOMETRY_BALL)
|
|
{
|
|
if (ManualWeldJoint::isTouchingTerrain(mCPrim, selectedPrimitives[i]))
|
|
createSmoothTerrainJointSurfacePair(*mCPrim, *selectedPrimitives[i]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ManualJointHelper::createTerrainJointSurfacePair(Primitive& p0, Primitive& p1, Vector3int16& cellIndex)
|
|
{
|
|
PartInstance* part0 = PartInstance::fromPrimitive(&p0);
|
|
RBXASSERT(part0->getParent());
|
|
PartInstance* part1 = PartInstance::fromPrimitive(&p1);
|
|
RBXASSERT(part1->getParent());
|
|
|
|
ConstraintSurfacePair* aPair = NULL;
|
|
|
|
RBXASSERT( p1.getConstGeometry()->getGeometryType() != RBX::Geometry::GEOMETRY_MEGACLUSTER );
|
|
size_t fix = -1;
|
|
// need to check if p1 is about to be joined to a no_join cell!
|
|
const MegaClusterPoly* terrainPoly = static_cast<const MegaClusterPoly*>(p0.getConstGeometry());
|
|
size_t otherFaceId;
|
|
std::vector<Vector3> intersectPolyInP0 = terrainPoly->findCellIntersectionWithGeom( cellIndex,
|
|
p0.getCoordinateFrame(),
|
|
*(p1.getConstGeometry()),
|
|
p1.getCoordinateFrame(),
|
|
otherFaceId);
|
|
SurfaceType t1 = Joint::getSurfaceTypeFromNormal(p1, (NormalId)otherFaceId);
|
|
if ( t1 == NO_JOIN )
|
|
{
|
|
DisallowedTerrainJointSurfacePair* pair = new DisallowedTerrainJointSurfacePair(p0, fix, p1, otherFaceId);
|
|
pair->setCellIndex(cellIndex);
|
|
aPair = pair;
|
|
}
|
|
else
|
|
{
|
|
TerrainManualJointSurfacePair* pair = new TerrainManualJointSurfacePair(p0, fix, p1, fix);
|
|
pair->setCellIndex(cellIndex);
|
|
aPair = pair;
|
|
}
|
|
|
|
jointSurfacePairs.push_back(aPair);
|
|
|
|
aPair->p0AncestorChangedConnection = part0->ancestryChangedSignal.connect(boost::bind(&ManualJointHelper::onPartAncestryChanged, this, _1, _2));
|
|
aPair->p1AncestorChangedConnection = part1->ancestryChangedSignal.connect(boost::bind(&ManualJointHelper::onPartAncestryChanged, this, _1, _2));
|
|
}
|
|
|
|
void ManualJointHelper::createSmoothTerrainJointSurfacePair(Primitive& p0, Primitive& p1)
|
|
{
|
|
PartInstance* part0 = PartInstance::fromPrimitive(&p0);
|
|
RBXASSERT(part0->getParent());
|
|
PartInstance* part1 = PartInstance::fromPrimitive(&p1);
|
|
RBXASSERT(part1->getParent());
|
|
|
|
size_t fix = -1;
|
|
SmoothTerrainManualJointSurfacePair* pair = new SmoothTerrainManualJointSurfacePair(p0, fix, p1, fix);
|
|
|
|
jointSurfacePairs.push_back(pair);
|
|
|
|
pair->p0AncestorChangedConnection = part0->ancestryChangedSignal.connect(boost::bind(&ManualJointHelper::onPartAncestryChanged, this, _1, _2));
|
|
pair->p1AncestorChangedConnection = part1->ancestryChangedSignal.connect(boost::bind(&ManualJointHelper::onPartAncestryChanged, this, _1, _2));
|
|
}
|
|
|
|
bool ManualJointHelper::surfaceIsNoJoin(const Primitive& p0, size_t& face0Id, const Primitive& p1, size_t& face1Id)
|
|
{
|
|
SurfaceType t0 = Joint::getSurfaceTypeFromNormal(p0, (NormalId)face0Id);
|
|
SurfaceType t1 = Joint::getSurfaceTypeFromNormal(p1, (NormalId)face1Id);
|
|
|
|
return ( t0 == NO_JOIN || t1 == NO_JOIN );
|
|
}
|
|
|
|
void ManualJointHelper::createJointSurfacePair(Primitive& p0, size_t& face0Id, Primitive& p1, size_t& face1Id)
|
|
{
|
|
PartInstance* part0 = PartInstance::fromPrimitive(&p0);
|
|
RBXASSERT(part0->getParent());
|
|
PartInstance* part1 = PartInstance::fromPrimitive(&p1);
|
|
RBXASSERT(part1->getParent());
|
|
|
|
ConstraintSurfacePair* aPair = NULL;
|
|
|
|
// First check if either part is associated with a humanoid (body part or child gear, hat, etc)
|
|
// If so, no joint allowed
|
|
const Instance* parent0 = PartInstance::fromConstPrimitive(&p0)->getParent();
|
|
const Humanoid* aHumanoidModel0 = NULL;
|
|
while( parent0 && !aHumanoidModel0 )
|
|
{
|
|
aHumanoidModel0 = Humanoid::modelIsConstCharacter(parent0);
|
|
parent0 = parent0->getParent();
|
|
}
|
|
const Instance* parent1 = PartInstance::fromConstPrimitive(&p1)->getParent();
|
|
const Humanoid* aHumanoidModel1 = NULL;
|
|
while( parent1 && !aHumanoidModel1 && !aHumanoidModel0 ) // don't bother walking p1's tree if we already found a character
|
|
{
|
|
aHumanoidModel1 = Humanoid::modelIsConstCharacter(parent1);
|
|
parent1 = parent1->getParent();
|
|
}
|
|
|
|
if( aHumanoidModel0 || aHumanoidModel1 || surfaceIsNoJoin(p0, face0Id, p1, face1Id) ) // also disallow if either surface type is NO_JOIN
|
|
aPair = new DisallowedJointSurfacePair(p0, face0Id, p1, face1Id);
|
|
else
|
|
{
|
|
RBXASSERT( p1.getConstGeometry()->getGeometryType() != RBX::Geometry::GEOMETRY_MEGACLUSTER );
|
|
if( p0.getConstGeometry()->getGeometryType() == RBX::Geometry::GEOMETRY_MEGACLUSTER )
|
|
aPair = new TerrainManualJointSurfacePair(p0, face0Id, p1, face1Id);
|
|
else if( Joint::compatibleForStudAutoJoint(p0, face0Id, p1, face1Id) )
|
|
if(Joint::positionedForStudAutoJoint(p0, face0Id, p1, face1Id))
|
|
{
|
|
aPair = new StudAutoJointSurfacePair(p0, face0Id, p1, face1Id);
|
|
autoJointsDetected = true;
|
|
}
|
|
else
|
|
#ifndef MACONLY_MANUAL_WELD_ALL_SURFACES
|
|
aPair = new DisallowedJointSurfacePair(p0, face0Id, p1, face1Id);
|
|
#else
|
|
aPair = new ManualJointSurfacePair(p0, face0Id, p1, face1Id);
|
|
#endif
|
|
else if(Joint::compatibleForGlueAutoJoint(p0, face0Id, p1, face1Id))
|
|
{
|
|
aPair = new GlueAutoJointSurfacePair(p0, face0Id, p1, face1Id);
|
|
autoJointsDetected = true;
|
|
}
|
|
else if(Joint::compatibleForWeldAutoJoint(p0, face0Id, p1, face1Id))
|
|
{
|
|
aPair = new WeldAutoJointSurfacePair(p0, face0Id, p1, face1Id);
|
|
autoJointsDetected = true;
|
|
}
|
|
else if(Joint::compatibleForHingeAutoJoint(p0, face0Id, p1, face1Id))
|
|
{
|
|
aPair = new HingeAutoJointSurfacePair(p0, face0Id, p1, face1Id);
|
|
autoJointsDetected = true;
|
|
}
|
|
#ifndef MACONLY_MANUAL_WELD_ALL_SURFACES
|
|
//this prevents welding of incompatible surfaces such as studs to smooth.
|
|
else if(Joint::inCompatibleForAnyJoint(p0, face0Id, p1, face1Id))
|
|
aPair = new DisallowedJointSurfacePair(p0, face0Id, p1, face1Id);
|
|
#endif
|
|
else
|
|
aPair = new ManualJointSurfacePair(p0, face0Id, p1, face1Id);
|
|
}
|
|
|
|
aPair->p0AncestorChangedConnection = part0->ancestryChangedSignal.connect(boost::bind(&ManualJointHelper::onPartAncestryChanged, this, _1, _2));
|
|
aPair->p1AncestorChangedConnection = part1->ancestryChangedSignal.connect(boost::bind(&ManualJointHelper::onPartAncestryChanged, this, _1, _2));
|
|
|
|
jointSurfacePairs.push_back(aPair);
|
|
}
|
|
|
|
void ManualJointHelper::setSelectedPrimitives(const std::vector<Instance*>& selectedInstances)
|
|
{
|
|
PartArray partInstances;
|
|
DragUtilities::instancesToParts(selectedInstances, partInstances);
|
|
selectedPrimitives.clear();
|
|
DragUtilities::partsToPrimitives(partInstances, selectedPrimitives);
|
|
}
|
|
|
|
void ManualJointHelper::setSelectedPrimitives(const Instances& selectedInstances)
|
|
{
|
|
PartArray partInstances;
|
|
DragUtilities::instancesToParts(selectedInstances, partInstances);
|
|
selectedPrimitives.clear();
|
|
DragUtilities::partsToPrimitives(partInstances, selectedPrimitives);
|
|
}
|
|
|
|
void ManualJointHelper::setPVInstanceToJoin(PVInstance& pVInstToJoin)
|
|
{
|
|
std::vector<PVInstance*> pvInstances;
|
|
pvInstances.push_back(&pVInstToJoin);
|
|
PartArray partInstances;
|
|
DragUtilities::pvsToParts(pvInstances, partInstances);
|
|
selectedPrimitives.clear();
|
|
DragUtilities::partsToPrimitives(partInstances, selectedPrimitives);
|
|
}
|
|
|
|
void ManualJointHelper::setPVInstanceTarget(PVInstance& pVInstToJoin)
|
|
{
|
|
PartInstance* part = dynamic_cast<PartInstance*>(&pVInstToJoin);
|
|
if(part)
|
|
targetPrimitive = part->getPartPrimitive();
|
|
else
|
|
targetPrimitive = NULL;
|
|
}
|
|
|
|
|
|
void ManualJointHelper::createJoints(void)
|
|
{
|
|
for( unsigned int i = 0; i < jointSurfacePairs.size(); i++ )
|
|
jointSurfacePairs[i]->createJoint();
|
|
}
|
|
|
|
void ManualJointHelper::createJointsIfEnabledFromGui(void)
|
|
{
|
|
if(AdvArrowTool::advManualJointMode)
|
|
{
|
|
for( unsigned int i = 0; i < jointSurfacePairs.size(); i++ )
|
|
jointSurfacePairs[i]->createJoint();
|
|
}
|
|
}
|
|
|
|
void ManualJointHelper::render3dAdorn(Adorn* adorn)
|
|
{
|
|
for( unsigned int i = 0; i < jointSurfacePairs.size(); i++ )
|
|
{
|
|
// if the target primitive is non NULL, then the client wants to only render the target body outline
|
|
// Otherwise, render all surface pairs
|
|
if(targetPrimitive)
|
|
{
|
|
if(jointSurfacePairs[i]->getP0() == targetPrimitive || jointSurfacePairs[i]->getP1() == targetPrimitive)
|
|
jointSurfacePairs[i]->dynamicDraw(adorn);
|
|
}
|
|
else
|
|
jointSurfacePairs[i]->dynamicDraw(adorn);
|
|
}
|
|
}
|
|
|
|
void ManualJointHelper::onPartAncestryChanged(shared_ptr<Instance> instance, shared_ptr<Instance> newParent)
|
|
{
|
|
if (!newParent)
|
|
{
|
|
if (PartInstance* part = instance->fastDynamicCast<PartInstance>())
|
|
{
|
|
Primitive * prim = PartInstance::getPrimitive(part);
|
|
|
|
if (prim == targetPrimitive)
|
|
targetPrimitive = NULL;
|
|
|
|
std::vector<ConstraintSurfacePair*>::iterator iter = jointSurfacePairs.begin();
|
|
for (; iter != jointSurfacePairs.end(); iter++)
|
|
{
|
|
if (prim == (*iter)->getP0() || prim == (*iter)->getP1())
|
|
{
|
|
// delete pair if one of the primitive has no parent, it's being deleted
|
|
delete *iter;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (iter != jointSurfacePairs.end())
|
|
jointSurfacePairs.erase(iter);
|
|
}
|
|
}
|
|
}
|
|
|
|
ConstraintSurfacePair::ConstraintSurfacePair()
|
|
{
|
|
p0 = NULL;
|
|
p1 = NULL;
|
|
s0 = (size_t)-1;
|
|
s1 = (size_t)-1;
|
|
}
|
|
|
|
ConstraintSurfacePair::ConstraintSurfacePair(const Primitive& prim0, size_t& face0Id, const Primitive& prim1, size_t& face1Id)
|
|
{
|
|
p0 = &prim0;
|
|
p1 = &prim1;
|
|
s0 = face0Id;
|
|
s1 = face1Id;
|
|
}
|
|
|
|
void StudAutoJointSurfacePair::dynamicDraw(Adorn* adorn)
|
|
{
|
|
std::vector<Vector3> polygon1;
|
|
if( p1 && p0 && p1->getConstGeometry() && p0->getConstGeometry() && s1 != (size_t)-1 && s0 != (size_t)-1 )
|
|
{
|
|
for( int i = 0; i < p1->getConstGeometry()->getNumVertsInSurface(s1); i++ )
|
|
{
|
|
Vector3 p1VertInWorld = p1->getCoordinateFrame().pointToWorldSpace(p1->getConstGeometry()->getSurfaceVertInBody(s1, i));
|
|
polygon1.push_back(p0->getCoordinateFrame().pointToObjectSpace(p1VertInWorld));
|
|
}
|
|
|
|
std::vector<Vector3> intersectPolyInP0 = p0->getConstGeometry()->polygonIntersectionWithFace(polygon1, s0);
|
|
|
|
DrawAdorn::polygonRelativeToCoord(adorn, p0->getCoordinateFrame(), intersectPolyInP0, Color3::blue(), autoJointLineThickness);
|
|
}
|
|
}
|
|
|
|
void GlueAutoJointSurfacePair::dynamicDraw(Adorn* adorn)
|
|
{
|
|
std::vector<Vector3> polygon1;
|
|
if( p1 && p0 && p1->getConstGeometry() && p0->getConstGeometry() && s1 != (size_t)-1 && s0 != (size_t)-1 )
|
|
{
|
|
for( int i = 0; i < p1->getConstGeometry()->getNumVertsInSurface(s1); i++ )
|
|
{
|
|
Vector3 p1VertInWorld = p1->getCoordinateFrame().pointToWorldSpace(p1->getConstGeometry()->getSurfaceVertInBody(s1, i));
|
|
polygon1.push_back(p0->getCoordinateFrame().pointToObjectSpace(p1VertInWorld));
|
|
}
|
|
|
|
std::vector<Vector3> intersectPolyInP0 = p0->getConstGeometry()->polygonIntersectionWithFace(polygon1, s0);
|
|
|
|
DrawAdorn::polygonRelativeToCoord(adorn, p0->getCoordinateFrame(), intersectPolyInP0, Color3::blue(), autoJointLineThickness);
|
|
}
|
|
}
|
|
|
|
void WeldAutoJointSurfacePair::dynamicDraw(Adorn* adorn)
|
|
{
|
|
std::vector<Vector3> polygon1;
|
|
if( p1 && p0 && p1->getConstGeometry() && p0->getConstGeometry() && s1 != (size_t)-1 && s0 != (size_t)-1 )
|
|
{
|
|
for( int i = 0; i < p1->getConstGeometry()->getNumVertsInSurface(s1); i++ )
|
|
{
|
|
Vector3 p1VertInWorld = p1->getCoordinateFrame().pointToWorldSpace(p1->getConstGeometry()->getSurfaceVertInBody(s1, i));
|
|
polygon1.push_back(p0->getCoordinateFrame().pointToObjectSpace(p1VertInWorld));
|
|
}
|
|
|
|
std::vector<Vector3> intersectPolyInP0 = p0->getConstGeometry()->polygonIntersectionWithFace(polygon1, s0);
|
|
|
|
DrawAdorn::polygonRelativeToCoord(adorn, p0->getCoordinateFrame(), intersectPolyInP0, Color3::blue(), autoJointLineThickness);
|
|
}
|
|
}
|
|
|
|
void HingeAutoJointSurfacePair::dynamicDraw(Adorn* adorn)
|
|
{
|
|
std::vector<Vector3> polygon1;
|
|
if( p1 && p0 && p1->getConstGeometry() && p0->getConstGeometry() && s1 != (size_t)-1 && s0 != (size_t)-1 )
|
|
{
|
|
for( int i = 0; i < p1->getConstGeometry()->getNumVertsInSurface(s1); i++ )
|
|
{
|
|
Vector3 p1VertInWorld = p1->getCoordinateFrame().pointToWorldSpace(p1->getConstGeometry()->getSurfaceVertInBody(s1, i));
|
|
polygon1.push_back(p0->getCoordinateFrame().pointToObjectSpace(p1VertInWorld));
|
|
}
|
|
|
|
std::vector<Vector3> intersectPolyInP0 = p0->getConstGeometry()->polygonIntersectionWithFace(polygon1, s0);
|
|
|
|
DrawAdorn::polygonRelativeToCoord(adorn, p0->getCoordinateFrame(), intersectPolyInP0, Color3::blue(), autoJointLineThickness);
|
|
}
|
|
}
|
|
|
|
void DisallowedJointSurfacePair::dynamicDraw(Adorn* adorn)
|
|
{
|
|
std::vector<Vector3> polygon1;
|
|
if( p1 && p0 && p1->getConstGeometry() && p0->getConstGeometry() && s1 != (size_t)-1 && s0 != (size_t)-1 )
|
|
{
|
|
for( int i = 0; i < p1->getConstGeometry()->getNumVertsInSurface(s1); i++ )
|
|
{
|
|
Vector3 p1VertInWorld = p1->getCoordinateFrame().pointToWorldSpace(p1->getConstGeometry()->getSurfaceVertInBody(s1, i));
|
|
polygon1.push_back(p0->getCoordinateFrame().pointToObjectSpace(p1VertInWorld));
|
|
}
|
|
|
|
std::vector<Vector3> intersectPolyInP0 = p0->getConstGeometry()->polygonIntersectionWithFace(polygon1, s0);
|
|
|
|
DrawAdorn::polygonRelativeToCoord(adorn, p0->getCoordinateFrame(), intersectPolyInP0, Color3::red(), autoJointLineThickness);
|
|
}
|
|
}
|
|
|
|
void ManualJointSurfacePair::dynamicDraw(Adorn* adorn)
|
|
{
|
|
if( p1 && p0 && p1->getConstGeometry() && p0->getConstGeometry() && s1 != (size_t)-1 && s0 != (size_t)-1 )
|
|
{
|
|
std::vector<Vector3> polygon1;
|
|
for( int i = 0; i < p1->getConstGeometry()->getNumVertsInSurface(s1); i++ )
|
|
{
|
|
Vector3 p1VertInWorld = p1->getCoordinateFrame().pointToWorldSpace(p1->getConstGeometry()->getSurfaceVertInBody(s1, i));
|
|
polygon1.push_back(p0->getCoordinateFrame().pointToObjectSpace(p1VertInWorld));
|
|
}
|
|
|
|
std::vector<Vector3> intersectPolyInP0 = p0->getConstGeometry()->polygonIntersectionWithFace(polygon1, s0);
|
|
|
|
Color3 color = AdvArrowTool::advManualJointType == DRAG::WEAK_MANUAL_JOINT ? Color3::brown() : Color3::white();
|
|
DrawAdorn::polygonRelativeToCoord(adorn, p0->getCoordinateFrame(), intersectPolyInP0, color, autoJointLineThickness);
|
|
}
|
|
}
|
|
|
|
void ManualJointSurfacePair::createJoint(void)
|
|
{
|
|
PartInstance* PartInst0 = (PartInstance*)PartInstance::fromConstPrimitive(p0);
|
|
PartInstance* PartInst1 = (PartInstance*)PartInstance::fromConstPrimitive(p1);
|
|
|
|
if(PartInst0 && PartInst1)
|
|
{
|
|
if( AdvArrowTool::advManualJointType == DRAG::STRONG_MANUAL_JOINT)
|
|
{
|
|
shared_ptr<ManualWeld> mJoint = Creatable<Instance>::create<ManualWeld>();
|
|
std::string jointPostPend = " Strong Joint";
|
|
// The joint will appear as a child of the drag part in the tree view
|
|
std::string p0Name = PartInst0->getName();
|
|
std::string p1Name = PartInst1->getName();
|
|
std::string jointName = p0Name + "-to-" + p1Name + jointPostPend;
|
|
mJoint->setName(jointName);
|
|
|
|
mJoint->setPart0(PartInst0);
|
|
mJoint->setPart1(PartInst1);
|
|
CoordinateFrame c0 = p0->getConstGeometry()->getSurfaceCoordInBody(s0);
|
|
CoordinateFrame worldC = p0->getCoordinateFrame() * c0;
|
|
CoordinateFrame c1 = p1->getCoordinateFrame().toObjectSpace(worldC);
|
|
|
|
mJoint->setC0(c0);
|
|
mJoint->setC1(c1);
|
|
mJoint->setSurface0(s0);
|
|
mJoint->setSurface1(s1);
|
|
mJoint->setParent(PartInst0);
|
|
}
|
|
else
|
|
{
|
|
shared_ptr<ManualGlue> mJoint = Creatable<Instance>::create<ManualGlue>();
|
|
std::string jointPostPend = " Glue Joint";
|
|
// The joint will appear as a child of the drag part in the tree view
|
|
std::string p0Name = PartInst0->getName();
|
|
std::string p1Name = PartInst1->getName();
|
|
std::string jointName = p0Name + "-to-" + p1Name + jointPostPend;
|
|
mJoint->setName(jointName);
|
|
|
|
mJoint->setPart0(PartInst0);
|
|
mJoint->setPart1(PartInst1);
|
|
CoordinateFrame c0 = p0->getConstGeometry()->getSurfaceCoordInBody(s0);
|
|
CoordinateFrame worldC = p0->getCoordinateFrame() * c0;
|
|
CoordinateFrame c1 = p1->getCoordinateFrame().toObjectSpace(worldC);
|
|
|
|
mJoint->setC0(c0);
|
|
mJoint->setC1(c1);
|
|
mJoint->setSurface0(s0);
|
|
mJoint->setSurface1(s1);
|
|
mJoint->setParent(PartInst0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TerrainManualJointSurfacePair::dynamicDraw(Adorn* adorn)
|
|
{
|
|
if( p1 && p0 && p1->getConstGeometry() && p0->getConstGeometry() )
|
|
{
|
|
|
|
const MegaClusterPoly* terrainPoly = static_cast<const MegaClusterPoly*>(p0->getConstGeometry());
|
|
size_t tempFaceId;
|
|
std::vector<Vector3> intersectPolyInP0 = terrainPoly->findCellIntersectionWithGeom( cellIndex,
|
|
p0->getCoordinateFrame(),
|
|
*(p1->getConstGeometry()),
|
|
p1->getCoordinateFrame(),
|
|
tempFaceId);
|
|
|
|
Color3 color = AdvArrowTool::advManualJointType == DRAG::WEAK_MANUAL_JOINT ? Color3::brown() : Color3::white();
|
|
DrawAdorn::polygonRelativeToCoord(adorn, p0->getCoordinateFrame(), intersectPolyInP0, color, autoJointLineThickness);
|
|
}
|
|
}
|
|
|
|
void DisallowedTerrainJointSurfacePair::dynamicDraw(Adorn* adorn)
|
|
{
|
|
if( p1 && p0 && p1->getConstGeometry() && p0->getConstGeometry() )
|
|
{
|
|
const MegaClusterPoly* terrainPoly = static_cast<const MegaClusterPoly*>(p0->getConstGeometry());
|
|
size_t tempFaceId;
|
|
std::vector<Vector3> intersectPolyInP0 = terrainPoly->findCellIntersectionWithGeom( cellIndex,
|
|
p0->getCoordinateFrame(),
|
|
*(p1->getConstGeometry()),
|
|
p1->getCoordinateFrame(),
|
|
tempFaceId);
|
|
|
|
DrawAdorn::polygonRelativeToCoord(adorn, p0->getCoordinateFrame(), intersectPolyInP0, Color3::red(), autoJointLineThickness);
|
|
}
|
|
}
|
|
|
|
void TerrainManualJointSurfacePair::createJoint(void)
|
|
{
|
|
// check if the non-terrain part, p1, is already welded to this terrain cell
|
|
// in this case, do not create it
|
|
RBXASSERT( p1->getConstGeometry()->getGeometryType() != RBX::Geometry::GEOMETRY_MEGACLUSTER );
|
|
for (int i = 0; i < p1->getNumJoints(); ++i)
|
|
{
|
|
const ManualWeldJoint* existingJoint = dynamic_cast<const ManualWeldJoint*>(p1->getConstJoint(i));
|
|
if( existingJoint && cellIndex == existingJoint->getCell() )
|
|
return;
|
|
}
|
|
|
|
PartInstance* PartInst0 = (PartInstance*)PartInstance::fromConstPrimitive(p0);
|
|
PartInstance* PartInst1 = (PartInstance*)PartInstance::fromConstPrimitive(p1);
|
|
|
|
if(PartInst0 && PartInst1)
|
|
{
|
|
if( AdvArrowTool::advManualJointType == DRAG::STRONG_MANUAL_JOINT)
|
|
{
|
|
shared_ptr<ManualWeld> mJoint = Creatable<Instance>::create<ManualWeld>();
|
|
std::string jointPostPend = " Terrain Joint";
|
|
// The joint will appear as a child of the drag part in the tree view
|
|
std::string p0Name = PartInst0->getName();
|
|
std::string p1Name = PartInst1->getName();
|
|
std::string jointName = p1Name + jointPostPend;
|
|
mJoint->setName(jointName);
|
|
|
|
mJoint->setPart0(PartInst0);
|
|
mJoint->setPart1(PartInst1);
|
|
CoordinateFrame c0 = p0->getCoordinateFrame();
|
|
CoordinateFrame worldC = p0->getCoordinateFrame() * c0;
|
|
CoordinateFrame c1 = p1->getCoordinateFrame().toObjectSpace(worldC);
|
|
|
|
mJoint->setC0(c0);
|
|
mJoint->setC1(c1);
|
|
mJoint->setParent(PartInst1);
|
|
|
|
RBXASSERT(mJoint->getJointType() == Joint::MANUAL_WELD_JOINT);
|
|
static_cast<ManualWeldJoint*>(mJoint->getJoint())->setCell(cellIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SmoothTerrainManualJointSurfacePair::dynamicDraw(Adorn* adorn)
|
|
{
|
|
}
|
|
|
|
void SmoothTerrainManualJointSurfacePair::createJoint(void)
|
|
{
|
|
// check if the non-terrain part, p1, is already welded to terrain
|
|
// in this case, do not create it
|
|
RBXASSERT( p1->getConstGeometry()->getGeometryType() != RBX::Geometry::GEOMETRY_MEGACLUSTER );
|
|
|
|
for (int i = 0; i < p1->getNumJoints(); ++i)
|
|
{
|
|
const Joint* existingJoint = p1->getConstJoint(i);
|
|
|
|
if (Joint::isManualJoint(existingJoint) && (existingJoint->getConstPrimitive(0) == p0 || existingJoint->getConstPrimitive(1) == p1))
|
|
return;
|
|
}
|
|
|
|
PartInstance* PartInst0 = (PartInstance*)PartInstance::fromConstPrimitive(p0);
|
|
PartInstance* PartInst1 = (PartInstance*)PartInstance::fromConstPrimitive(p1);
|
|
|
|
if (PartInst0 && PartInst1)
|
|
{
|
|
if (AdvArrowTool::advManualJointType == DRAG::STRONG_MANUAL_JOINT)
|
|
{
|
|
shared_ptr<ManualWeld> mJoint = Creatable<Instance>::create<ManualWeld>();
|
|
std::string jointPostPend = " Terrain Joint";
|
|
// The joint will appear as a child of the drag part in the tree view
|
|
std::string p0Name = PartInst0->getName();
|
|
std::string p1Name = PartInst1->getName();
|
|
std::string jointName = p1Name + jointPostPend;
|
|
mJoint->setName(jointName);
|
|
|
|
mJoint->setPart0(PartInst0);
|
|
mJoint->setPart1(PartInst1);
|
|
mJoint->setParent(PartInst1);
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace
|