mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-04 20:57:49 +00:00
228 lines
5.2 KiB
C++
228 lines
5.2 KiB
C++
/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
|
|
#include "stdafx.h"
|
|
|
|
#include "V8World/EdgeBuffer.h"
|
|
#include "V8World/MovingAssemblyStage.h"
|
|
#include "V8World/Edge.h"
|
|
#include "V8World/Joint.h"
|
|
#include "V8World/Contact.h"
|
|
#include "V8World/Primitive.h"
|
|
#include "V8world/World.h"
|
|
#include "V8world/ContactManager.h"
|
|
#include "V8world/ContactManagerSpatialHash.h"
|
|
#include "V8Kernel/Debug.h"
|
|
|
|
namespace RBX {
|
|
|
|
EdgeBuffer::~EdgeBuffer()
|
|
{
|
|
RBXASSERT(assemblyEdges.empty());
|
|
}
|
|
|
|
|
|
|
|
void EdgeBuffer::afterAssemblyAdded(Assembly* a)
|
|
{
|
|
RBXASSERT_SLOW(debugAddAssembly(a));
|
|
|
|
a->visitPrimitives(boost::bind(&EdgeBuffer::assemblyPrimitiveAdded, this, _1));
|
|
}
|
|
|
|
void EdgeBuffer::beforeAssemblyRemoving(Assembly* a)
|
|
{
|
|
a->visitPrimitives(boost::bind(&EdgeBuffer::assemblyPrimitiveRemoved, this, _1));
|
|
|
|
RBXASSERT_SLOW(debugRemoveAssembly(a));
|
|
}
|
|
|
|
|
|
void EdgeBuffer::assemblyPrimitiveAdded(Primitive* p)
|
|
{
|
|
if (p->getWorld() && p != p->getWorld()->getGroundPrimitive()) {
|
|
p->getWorld()->getContactManager()->onPrimitiveAssembled(p);
|
|
}
|
|
for (int i = 0; i < p->getNumContacts(); ++i) { // this is faster than p->forEachEdge
|
|
pushEdgeIfOk(p->getContact(i));
|
|
}
|
|
for (int i = 0; i < p->getNumJoints(); ++i) {
|
|
pushEdgeIfOk(p->getJoint(i));
|
|
}
|
|
}
|
|
|
|
|
|
void EdgeBuffer::assemblyPrimitiveRemoved(Primitive* p)
|
|
{
|
|
for (int i = 0; i < p->getNumContacts(); ++i) { // this is faster than p->forEachEdge
|
|
removeEdgeIfDownstream(p->getContact(i));
|
|
}
|
|
for (int i = 0; i < p->getNumJoints(); ++i) {
|
|
removeEdgeIfDownstream(p->getJoint(i));
|
|
}
|
|
}
|
|
|
|
|
|
bool EdgeBuffer::assemblyIsHere(Assembly* a)
|
|
{
|
|
return ( a
|
|
&& a->inPipeline()
|
|
&& a->inOrDownstreamOfStage(this) );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
//
|
|
// Note - for now, everyone does kinematic joints, both clients and server
|
|
|
|
void EdgeBuffer::pushEdgeIfOk(Edge* e)
|
|
{
|
|
if (e->inStage(this)) {
|
|
RBXASSERT(Joint::isKinematicJoint(e) == Joint::isMotorJoint(e));
|
|
|
|
bool ok = Joint::isKinematicJoint(e) ? pushKinematicOk(e) : pushSpringOk(e); // this is asserting in some places, but needed to allow animation of leg joints after sitting
|
|
|
|
if (ok) {
|
|
e->generateDataForMovingAssemblyStage();
|
|
getDownstreamWS()->onEdgeAdded(e);
|
|
RBXASSERT_SLOW(debugPushEdgeToDownstream(e));
|
|
}
|
|
}
|
|
}
|
|
|
|
bool EdgeBuffer::pushSpringOk(Edge* e)
|
|
{
|
|
RBXASSERT(e->inStage(this));
|
|
|
|
Assembly* a0 = e->getPrimitive(0)->getAssembly();
|
|
Assembly* a1 = e->getPrimitive(1)->getAssembly();
|
|
|
|
bool ok = ( (assemblyIsHere(a0) && assemblyIsHere(a1)) // 1. Both here
|
|
&& (a0->downstreamOfStage(this) || a1->downstreamOfStage(this)) // 2. One assembly is downstream
|
|
&& (a0 != a1) ); // 3. Either a kinematic joint (motor), or different assemblies
|
|
return ok;
|
|
}
|
|
|
|
|
|
/*
|
|
Kinematic joints should go for two reasons:
|
|
|
|
Both Assemblies Grounded?
|
|
* this implies no simulation - everyone does it
|
|
* otherwise, use
|
|
1. pushSpringOK - i.e. - both assemblies here, at least one downstream (simulating). Will only happen on the dPhysics owner.
|
|
2.
|
|
*/
|
|
|
|
bool EdgeBuffer::pushKinematicOk(Edge* e)
|
|
{
|
|
RBXASSERT(e->inStage(this));
|
|
RBXASSERT(Joint::isMotorJoint(e));
|
|
|
|
Assembly* a0 = e->getPrimitive(0)->getAssembly();
|
|
|
|
RBX_ENGINE_ASSERT(a0 == e->getPrimitive(1)->getAssembly());
|
|
|
|
bool allClientsStepUi = a0->computeIsGrounded();
|
|
bool thisClientDoDPhysics = (assemblyIsHere(a0) && a0->downstreamOfStage(this));
|
|
|
|
return (allClientsStepUi || thisClientDoDPhysics);
|
|
}
|
|
|
|
|
|
void EdgeBuffer::removeEdgeIfDownstream(Edge* e)
|
|
{
|
|
if (e->downstreamOfStage(this)) {
|
|
getDownstreamWS()->onEdgeRemoving(e);
|
|
RBXASSERT_SLOW(debugRemoveEdgeFromDownstream(e));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
void EdgeBuffer::onEdgeAdded(Edge* e)
|
|
{
|
|
RBXASSERT(!Joint::isGroundJoint(e));
|
|
RBXASSERT(!Joint::isRigidJoint(e));
|
|
e->putInStage(this);
|
|
pushEdgeIfOk(e);
|
|
}
|
|
|
|
|
|
|
|
void EdgeBuffer::onEdgeRemoving(Edge* e)
|
|
{
|
|
removeEdgeIfDownstream(e);
|
|
e->removeFromStage(this);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
bool EdgeBuffer::debugPushEdgeToDownstream(Edge* e)
|
|
{
|
|
RBXASSERT_NOT_RELEASE();
|
|
|
|
RBXASSERT(e->downstreamOfStage(this));
|
|
|
|
Assembly* a0 = e->getPrimitive(0)->getAssembly();
|
|
Assembly* a1 = e->getPrimitive(1)->getAssembly();
|
|
RBXASSERT(a0 && a1);
|
|
|
|
if (a0 != a1) {
|
|
assemblyEdges.insertPair(a0, e);
|
|
assemblyEdges.insertPair(a1, e);
|
|
}
|
|
else {
|
|
RBXASSERT(Joint::isMotorJoint(e));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool EdgeBuffer::debugRemoveEdgeFromDownstream(Edge* e)
|
|
{
|
|
RBXASSERT_NOT_RELEASE();
|
|
|
|
Assembly* a0 = e->getPrimitive(0)->getAssembly();
|
|
Assembly* a1 = e->getPrimitive(1)->getAssembly();
|
|
RBXASSERT(a0 && a1);
|
|
|
|
if (a0 != a1) {
|
|
assemblyEdges.removePair(a0, e);
|
|
assemblyEdges.removePair(a1, e);
|
|
}
|
|
else {
|
|
RBXASSERT(Joint::isMotorJoint(e));
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool EdgeBuffer::debugAddAssembly(Assembly* a)
|
|
{
|
|
RBXASSERT_NOT_RELEASE();
|
|
|
|
//RBXASSERT(assemblyEdges.emptyLeft(a));
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
bool EdgeBuffer::debugRemoveAssembly(Assembly* a)
|
|
{
|
|
RBXASSERT_NOT_RELEASE();
|
|
|
|
RBXASSERT(assemblyEdges.emptyLeft(a));
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
} // namespace
|