Files
2025-09-18 17:55:52 -04:00

151 lines
3.6 KiB
C++

/* Copyright 2003-2005 ROBLOX Corporation, All Rights Reserved */
#include "stdafx.h"
#include "V8World/PolyContact.h"
#include "V8Kernel/PolyConnectors.h"
#include "V8Kernel/Kernel.h"
#include "V8World/Primitive.h"
namespace RBX {
PolyContact::~PolyContact()
{
deleteConnectors(polyConnectors);
RBXASSERT(polyConnectors.size() == 0);
}
ContactConnector* PolyContact::getConnector(int i)
{
return polyConnectors[i];
}
void PolyContact::deleteAllConnectors()
{
deleteConnectors(polyConnectors);
}
void PolyContact::deleteConnectors(ConnectorArray& deleteConnectors)
{
removeAllConnectorsFromKernel();
for (size_t i = 0; i < deleteConnectors.size(); ++i) {
RBXASSERT(!deleteConnectors[i]->isInKernel());
delete deleteConnectors[i];
}
deleteConnectors.fastClear();
}
void PolyContact::removeAllConnectorsFromKernel()
{
Kernel* kernel = NULL;
for (size_t i = 0; i < polyConnectors.size(); ++i) {
if (polyConnectors[i]->isInKernel()) {
kernel = kernel ? kernel : getKernel(); // small optimization - getKernel walks the IPipelines
kernel->removeConnector(polyConnectors[i]);
}
}
}
void PolyContact::putAllConnectorsInKernel()
{
Kernel* kernel = NULL;
for (size_t i = 0; i < polyConnectors.size(); ++i) {
if (!polyConnectors[i]->isInKernel() &&
polyConnectors[i]->getContactPoint().length < -ContactConnector::overlapGoal()) {
kernel = kernel ? kernel : getKernel(); // small optimization - getKernel walks the IPipelines
kernel->insertConnector(polyConnectors[i]);
}
}
}
bool PolyContact::stepContact()
{
if (computeIsColliding(0.0f)) {
if (inKernel()) {
updateContactPoints();
putAllConnectorsInKernel();
}
return true;
}
else {
removeAllConnectorsFromKernel();
return false;
}
}
bool PolyContact::computeIsColliding(float overlapIgnored)
{
if (Primitive::aaBoxCollide(*getPrimitive(0), *getPrimitive(1))) {
updateClosestFeatures();
if (polyConnectors.size() > 0) {
float overlap = worstFeatureOverlap();
if (overlap > overlapIgnored) {
return true;
}
}
}
return false;
}
void PolyContact::updateClosestFeatures()
{
ConnectorArray newConnectors;
findClosestFeatures(newConnectors);
matchClosestFeatures(newConnectors); // new Connectors is now the deal!
RBXASSERT(newConnectors.size() <= 10);
deleteConnectors(polyConnectors); // any remaining not matched
polyConnectors = newConnectors; // transfer over the pointers
RBXASSERT(polyConnectors.size() <= 10);
}
float PolyContact::worstFeatureOverlap()
{
float worstOverlap = -FLT_MAX; // i.e. not overlapping
RBXASSERT(polyConnectors.size() > 0);
for (size_t i = 0; i < polyConnectors.size(); ++i) { // may not have any overlapping features!
float overlap = polyConnectors[i]->computeOverlap(); // computeLength returns negative
worstOverlap = std::max(worstOverlap, overlap);
}
return worstOverlap;
}
// TODO - turn optimizer back on here after fixed
void PolyContact::matchClosestFeatures(ConnectorArray& newConnectors)
{
for (size_t i = 0; i < newConnectors.size(); ++i) {
if (PolyConnector* match = matchClosestFeature(newConnectors[i])) {
delete newConnectors[i];
newConnectors.replace(i, match);
}
}
}
PolyConnector* PolyContact::matchClosestFeature(PolyConnector* newConnector)
{
for (size_t i = 0; i < polyConnectors.size(); ++i) {
PolyConnector* answer = polyConnectors[i];
if (PolyConnector::match(answer, newConnector)) {
polyConnectors.fastRemove(i);
return answer;
}
}
return NULL;
}
void PolyContact::updateContactPoints()
{
for (size_t i = 0; i < polyConnectors.size(); ++i)
polyConnectors[i]->updateContactPoint();
}
} // namespace