mirror of
https://foundry.openuru.org/gitblit/r/CWE-ou-minkata.git
synced 2025-07-14 02:27:40 -04:00
Hoikas' subworld fixes including PhysX support
1) Allow plSubWorldMsg to be sent over the network https://github.com/H-uru/Plasma/pull/107 2) Cleanup VolumeSensorConditionalObject https://github.com/H-uru/Plasma/pull/537 3) Add two new compiler feature tests - HeadSpin.h changes ONLY, as prerequisite for VolumeSensorConditionalObject45be91c0e3
4) Fix a crash and a silly identified by Coverity - changes for VolumeSensorConditionalObject ONLYa702cb9d3f
5) PXSubworld (Havok/CC subworld physics support ported to PhysX/MOULa) https://github.com/H-uru/Plasma/pull/555
This commit is contained in:
@ -61,6 +61,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "../pnKeyedObject/plKey.h"
|
||||
#include "../pnMessage/plCorrectionMsg.h"
|
||||
#include "../pnMessage/plNodeRefMsg.h"
|
||||
#include "../pnMessage/plObjRefMsg.h"
|
||||
#include "../pnMessage/plSDLModifierMsg.h"
|
||||
#include "../plMessage/plSimStateMsg.h"
|
||||
#include "../plMessage/plSimInfluenceMsg.h"
|
||||
@ -72,6 +73,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "../plStatusLog/plStatusLog.h"
|
||||
#include "plPXConvert.h"
|
||||
#include "plPXPhysicalControllerCore.h"
|
||||
#include "plPXSubWorld.h"
|
||||
|
||||
#include "../plModifier/plDetectorLog.h"
|
||||
|
||||
@ -84,25 +86,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
|
||||
#define LogActivate(func) if (fActor->isSleeping()) SimLog("%s activated by %s", GetKeyName(), func);
|
||||
|
||||
PhysRecipe::PhysRecipe()
|
||||
: mass(0.f)
|
||||
, friction(0.f)
|
||||
, restitution(0.f)
|
||||
, bounds(plSimDefs::kBoundsMax)
|
||||
, group(plSimDefs::kGroupMax)
|
||||
, reportsOn(0)
|
||||
, objectKey(nil)
|
||||
, sceneNode(nil)
|
||||
, worldKey(nil)
|
||||
, convexMesh(nil)
|
||||
, triMesh(nil)
|
||||
, radius(0.f)
|
||||
, offset(0.f, 0.f, 0.f)
|
||||
, meshStream(nil)
|
||||
{
|
||||
l2s.Reset();
|
||||
}
|
||||
|
||||
plProfile_Extern(MaySendLocation);
|
||||
plProfile_Extern(LocationsSent);
|
||||
plProfile_Extern(PhysicsUpdates);
|
||||
@ -128,19 +111,15 @@ int plPXPhysical::fNumberAnimatedActivators = 0;
|
||||
plPXPhysical::plPXPhysical()
|
||||
: fSDLMod(nil)
|
||||
, fActor(nil)
|
||||
, fBoundsType(plSimDefs::kBoundsMax)
|
||||
, fLOSDBs(plSimDefs::kLOSDBNone)
|
||||
, fGroup(plSimDefs::kGroupMax)
|
||||
, fReportsOn(0)
|
||||
, fLastSyncTime(0.0f)
|
||||
, fProxyGen(nil)
|
||||
, fSceneNode(nil)
|
||||
, fWorldKey(nil)
|
||||
, fSndGroup(nil)
|
||||
, fWorldHull(nil)
|
||||
, fSaveTriangles(nil)
|
||||
, fHullNumberPlanes(0)
|
||||
, fMass(0.f)
|
||||
, fWeWereHit(false)
|
||||
, fHitForce(0,0,0)
|
||||
, fHitPos(0,0,0)
|
||||
@ -354,15 +333,14 @@ hsBool plPXPhysical::Should_I_Trigger(hsBool enter, hsPoint3& pos)
|
||||
}
|
||||
|
||||
|
||||
hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
hsBool plPXPhysical::Init()
|
||||
{
|
||||
hsBool startAsleep = false;
|
||||
fBoundsType = recipe.bounds;
|
||||
fGroup = recipe.group;
|
||||
fReportsOn = recipe.reportsOn;
|
||||
fObjectKey = recipe.objectKey;
|
||||
fSceneNode = recipe.sceneNode;
|
||||
fWorldKey = recipe.worldKey;
|
||||
|
||||
fGroup = fRecipe.group;
|
||||
fReportsOn = fRecipe.reportsOn;
|
||||
fObjectKey = fRecipe.objectKey;
|
||||
fSceneNode = fRecipe.sceneNode;
|
||||
|
||||
NxActorDesc actorDesc;
|
||||
NxSphereShapeDesc sphereDesc;
|
||||
@ -370,19 +348,19 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
NxTriangleMeshShapeDesc trimeshShapeDesc;
|
||||
NxBoxShapeDesc boxDesc;
|
||||
|
||||
plPXConvert::Matrix(recipe.l2s, actorDesc.globalPose);
|
||||
plPXConvert::Matrix(fRecipe.l2s, actorDesc.globalPose);
|
||||
|
||||
switch (fBoundsType)
|
||||
switch (fRecipe.bounds)
|
||||
{
|
||||
case plSimDefs::kSphereBounds:
|
||||
{
|
||||
hsMatrix44 sphereL2W;
|
||||
sphereL2W.Reset();
|
||||
sphereL2W.SetTranslate(&recipe.offset);
|
||||
sphereL2W.SetTranslate(&fRecipe.offset);
|
||||
|
||||
sphereDesc.radius = recipe.radius;
|
||||
sphereDesc.radius = fRecipe.radius;
|
||||
plPXConvert::Matrix(sphereL2W, sphereDesc.localPose);
|
||||
sphereDesc.group = fGroup;
|
||||
sphereDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.pushBack(&sphereDesc);
|
||||
}
|
||||
break;
|
||||
@ -391,54 +369,54 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
// If this is read time (ie, meshStream is nil), turn the convex hull
|
||||
// into a box. That way the data won't have to change when convex hulls
|
||||
// actually work right.
|
||||
if (fGroup == plSimDefs::kGroupDetector && recipe.meshStream == nil)
|
||||
if (fRecipe.group == plSimDefs::kGroupDetector && fRecipe.meshStream == nil)
|
||||
{
|
||||
#ifdef USE_BOXES_FOR_DETECTOR_HULLS
|
||||
MakeBoxFromHull(recipe.convexMesh, boxDesc);
|
||||
plSimulationMgr::GetInstance()->GetSDK()->releaseConvexMesh(*recipe.convexMesh);
|
||||
boxDesc.group = fGroup;
|
||||
MakeBoxFromHull(fRecipe.convexMesh, boxDesc);
|
||||
plSimulationMgr::GetInstance()->GetSDK()->releaseConvexMesh(*fRecipe.convexMesh);
|
||||
boxDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.push_back(&boxDesc);
|
||||
#else
|
||||
#ifdef USE_PHYSX_CONVEXHULL_WORKAROUND
|
||||
// make a hull of planes for testing IsInside
|
||||
IMakeHull(recipe.convexMesh,recipe.l2s);
|
||||
IMakeHull(fRecipe.convexMesh,fRecipe.l2s);
|
||||
#endif // USE_PHYSX_CONVEXHULL_WORKAROUND
|
||||
convexShapeDesc.meshData = recipe.convexMesh;
|
||||
convexShapeDesc.userData = recipe.meshStream;
|
||||
convexShapeDesc.group = fGroup;
|
||||
convexShapeDesc.meshData = fRecipe.convexMesh;
|
||||
convexShapeDesc.userData = fRecipe.meshStream;
|
||||
convexShapeDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.pushBack(&convexShapeDesc);
|
||||
#endif // USE_BOXES_FOR_DETECTOR_HULLS
|
||||
}
|
||||
else
|
||||
{
|
||||
convexShapeDesc.meshData = recipe.convexMesh;
|
||||
convexShapeDesc.userData = recipe.meshStream;
|
||||
convexShapeDesc.group = fGroup;
|
||||
convexShapeDesc.meshData = fRecipe.convexMesh;
|
||||
convexShapeDesc.userData = fRecipe.meshStream;
|
||||
convexShapeDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.pushBack(&convexShapeDesc);
|
||||
}
|
||||
break;
|
||||
case plSimDefs::kBoxBounds:
|
||||
{
|
||||
boxDesc.dimensions = plPXConvert::Point(recipe.bDimensions);
|
||||
boxDesc.dimensions = plPXConvert::Point(fRecipe.bDimensions);
|
||||
|
||||
hsMatrix44 boxL2W;
|
||||
boxL2W.Reset();
|
||||
boxL2W.SetTranslate(&recipe.bOffset);
|
||||
boxL2W.SetTranslate(&fRecipe.bOffset);
|
||||
plPXConvert::Matrix(boxL2W, boxDesc.localPose);
|
||||
|
||||
boxDesc.group = fGroup;
|
||||
boxDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.push_back(&boxDesc);
|
||||
}
|
||||
break;
|
||||
case plSimDefs::kExplicitBounds:
|
||||
case plSimDefs::kProxyBounds:
|
||||
if (fGroup == plSimDefs::kGroupDetector)
|
||||
if (fRecipe.group == plSimDefs::kGroupDetector)
|
||||
{
|
||||
SimLog("Someone using an Exact on a detector region: %s", GetKeyName());
|
||||
}
|
||||
trimeshShapeDesc.meshData = recipe.triMesh;
|
||||
trimeshShapeDesc.userData = recipe.meshStream;
|
||||
trimeshShapeDesc.group = fGroup;
|
||||
trimeshShapeDesc.meshData = fRecipe.triMesh;
|
||||
trimeshShapeDesc.userData = fRecipe.meshStream;
|
||||
trimeshShapeDesc.group = fRecipe.group;
|
||||
actorDesc.shapes.pushBack(&trimeshShapeDesc);
|
||||
break;
|
||||
default:
|
||||
@ -449,10 +427,9 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
|
||||
// Now fill out the body, or dynamic part of the physical
|
||||
NxBodyDesc bodyDesc;
|
||||
fMass = recipe.mass;
|
||||
if (recipe.mass != 0)
|
||||
if (fRecipe.mass != 0)
|
||||
{
|
||||
bodyDesc.mass = recipe.mass;
|
||||
bodyDesc.mass = fRecipe.mass;
|
||||
actorDesc.body = &bodyDesc;
|
||||
|
||||
if (GetProperty(plSimulationInterface::kPinned))
|
||||
@ -461,13 +438,13 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
startAsleep = true; // put it to sleep if they are going to be frozen
|
||||
}
|
||||
|
||||
if (fGroup != plSimDefs::kGroupDynamic || GetProperty(plSimulationInterface::kPhysAnim))
|
||||
if (fRecipe.group != plSimDefs::kGroupDynamic || GetProperty(plSimulationInterface::kPhysAnim))
|
||||
{
|
||||
SetProperty(plSimulationInterface::kPassive, true);
|
||||
|
||||
// Even though the code for animated physicals and animated activators are the same
|
||||
// keep these code snippets separated for fine tuning. Thanks.
|
||||
if (fGroup == plSimDefs::kGroupDynamic)
|
||||
if (fRecipe.group == plSimDefs::kGroupDynamic)
|
||||
{
|
||||
// handle the animated physicals.... make kinematic for now.
|
||||
fNumberAnimatedPhysicals++;
|
||||
@ -495,7 +472,7 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
|
||||
// Put the dynamics into actor group 1. The actor groups are only used for
|
||||
// deciding who we get contact reports for.
|
||||
if (fGroup == plSimDefs::kGroupDynamic)
|
||||
if (fRecipe.group == plSimDefs::kGroupDynamic)
|
||||
actorDesc.group = 1;
|
||||
|
||||
NxScene* scene = plSimulationMgr::GetInstance()->GetScene(fWorldKey);
|
||||
@ -512,7 +489,7 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
return false;
|
||||
|
||||
NxShape* shape = fActor->getShapes()[0];
|
||||
shape->setMaterial(plSimulationMgr::GetInstance()->GetMaterialIdx(scene, recipe.friction, recipe.restitution));
|
||||
shape->setMaterial(plSimulationMgr::GetInstance()->GetMaterialIdx(scene, fRecipe.friction, fRecipe.restitution));
|
||||
|
||||
// Turn on the trigger flags for any detectors.
|
||||
//
|
||||
@ -523,7 +500,7 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
// problems trying to calculate an intertial tensor. By letting it be
|
||||
// created as a normal dynamic first, then setting the flags, we work around
|
||||
// that problem.
|
||||
if (fGroup == plSimDefs::kGroupDetector)
|
||||
if (fRecipe.group == plSimDefs::kGroupDetector)
|
||||
{
|
||||
shape->setFlag(NX_TRIGGER_ON_ENTER, true);
|
||||
shape->setFlag(NX_TRIGGER_ON_LEAVE, true);
|
||||
@ -547,14 +524,8 @@ hsBool plPXPhysical::Init(PhysRecipe& recipe)
|
||||
plNodeRefMsg* refMsg = TRACKED_NEW plNodeRefMsg(fSceneNode, plRefMsg::kOnCreate, -1, plNodeRefMsg::kPhysical);
|
||||
hsgResMgr::ResMgr()->AddViaNotify(GetKey(), refMsg, plRefFlags::kActiveRef);
|
||||
|
||||
if (fWorldKey)
|
||||
{
|
||||
plGenRefMsg* ref = TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kPhysRefWorld);
|
||||
hsgResMgr::ResMgr()->AddViaNotify(fWorldKey, ref, plRefFlags::kActiveRef);
|
||||
}
|
||||
|
||||
// only dynamic physicals without noSync need SDLs
|
||||
if ( fGroup == plSimDefs::kGroupDynamic && !fProps.IsBitSet(plSimulationInterface::kNoSynchronize) )
|
||||
if ( fRecipe.group == plSimDefs::kGroupDynamic && !fProps.IsBitSet(plSimulationInterface::kNoSynchronize) )
|
||||
{
|
||||
// add SDL modifier
|
||||
plSceneObject* sceneObj = plSceneObject::ConvertNoRef(fObjectKey->ObjectIsLoaded());
|
||||
@ -611,29 +582,66 @@ hsBool plPXPhysical::MsgReceive( plMessage* msg )
|
||||
hsBool plPXPhysical::HandleRefMsg(plGenRefMsg* refMsg)
|
||||
{
|
||||
UInt8 refCtxt = refMsg->GetContext();
|
||||
plKey refKey = refMsg->GetRef()->GetKey();
|
||||
plKey ourKey = GetKey();
|
||||
PhysRefType refType = PhysRefType(refMsg->fType);
|
||||
|
||||
const char* refKeyName = refKey ? refKey->GetName() : "MISSING";
|
||||
switch (refMsg->fType) {
|
||||
case kPhysRefWorld: {
|
||||
switch (refCtxt) {
|
||||
case plRefMsg::kOnCreate:
|
||||
case plRefMsg::kOnRequest:
|
||||
// PotS files specify a plHKSubWorld as the subworld key. For everything else,
|
||||
// the subworlds are a plSceneObject key. For sanity purposes, we will allow
|
||||
// references to the plPXSubWorld here. HOWEVER, we will need to grab the target
|
||||
// and replace our reference...
|
||||
if (plPXSubWorld* subWorldIface = plPXSubWorld::ConvertNoRef(refMsg->GetRef())) {
|
||||
hsAssert(subWorldIface->GetOwnerKey(), "subworld owner is NULL?! Uh oh...");
|
||||
plGenRefMsg* replaceRefMsg = new plGenRefMsg(GetKey(), plRefMsg::kOnReplace, 0, kPhysRefWorld);
|
||||
hsgResMgr::ResMgr()->AddViaNotify(subWorldIface->GetOwnerKey(), replaceRefMsg, plRefFlags::kActiveRef);
|
||||
}
|
||||
// fall-thru is intentional :)
|
||||
case plRefMsg::kOnReplace:
|
||||
// loading into a subworld
|
||||
if (plSceneObject* subSO = plSceneObject::ConvertNoRef(refMsg->GetRef())) {
|
||||
fWorldKey = subSO->GetKey();
|
||||
|
||||
if (refType == kPhysRefWorld)
|
||||
{
|
||||
if (refCtxt == plRefMsg::kOnCreate || refCtxt == plRefMsg::kOnRequest)
|
||||
{
|
||||
// Cache the initial transform, since we assume the sceneobject already knows
|
||||
// that and doesn't need to be told again
|
||||
IGetTransformGlobal(fCachedLocal2World);
|
||||
// Cyan produced files will never have plPXSubWorld as this is a H'uru-ism.
|
||||
// Let us make a default one such that we can play with default subworlds at runtime.
|
||||
// HAAAAAAAAAX!!!
|
||||
plPXSubWorld* subWorldIface = plPXSubWorld::ConvertNoRef(subSO->GetGenericInterface(plPXSubWorld::Index()));
|
||||
if (!subWorldIface) {
|
||||
subWorldIface = new plPXSubWorld();
|
||||
|
||||
// This can be simplified if/when incorporating zrax' String Theory library
|
||||
std::string strKeyName = subSO->GetKeyName();
|
||||
strKeyName += "_DefSubWorld";
|
||||
const char *cKeyName = strKeyName.c_str();
|
||||
|
||||
hsgResMgr::ResMgr()->NewKey(cKeyName,
|
||||
subWorldIface, GetKey()->GetUoid().GetLocation());
|
||||
|
||||
plObjRefMsg* subIfaceRef = new plObjRefMsg(subSO->GetKey(), plRefMsg::kOnCreate, 0, plObjRefMsg::kInterface);
|
||||
// this will send the reference immediately
|
||||
hsgResMgr::ResMgr()->SendRef(subWorldIface, subIfaceRef, plRefFlags::kActiveRef);
|
||||
}
|
||||
|
||||
// Now, we can initialize the physical...
|
||||
Init();
|
||||
IGetTransformGlobal(fCachedLocal2World);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (refCtxt == plRefMsg::kOnDestroy)
|
||||
{
|
||||
break;
|
||||
case plRefMsg::kOnDestroy: {
|
||||
// our world was deleted out from under us: move to the main world
|
||||
// NOTE: this was not implemented even before the PXSubWorld rewrite.
|
||||
// not going to bother!
|
||||
// hsAssert(0, "Lost world");
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (refType == kPhysRefSndGroup)
|
||||
{
|
||||
switch (refCtxt)
|
||||
break;
|
||||
|
||||
case kPhysRefSndGroup: {
|
||||
switch (refCtxt)
|
||||
{
|
||||
case plRefMsg::kOnCreate:
|
||||
case plRefMsg::kOnRequest:
|
||||
@ -645,9 +653,11 @@ hsBool plPXPhysical::HandleRefMsg(plGenRefMsg* refMsg)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
default:
|
||||
hsAssert(0, "Unknown ref type, who sent us this?");
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -878,7 +888,6 @@ void plPXPhysical::IGetTransformGlobal(hsMatrix44& l2w) const
|
||||
{
|
||||
plSceneObject* so = plSceneObject::ConvertNoRef(fWorldKey->ObjectIsLoaded());
|
||||
hsAssert(so, "Scene object not loaded while accessing subworld.");
|
||||
// We'll hit this at export time, when the ci isn't ready yet, so do a check
|
||||
if (so->GetCoordinateInterface())
|
||||
{
|
||||
const hsMatrix44& s2w = so->GetCoordinateInterface()->GetLocalToWorld();
|
||||
@ -1026,23 +1035,22 @@ void plPXPhysical::Read(hsStream* stream, hsResMgr* mgr)
|
||||
plPhysical::Read(stream, mgr);
|
||||
ClearMatrix(fCachedLocal2World);
|
||||
|
||||
PhysRecipe recipe;
|
||||
recipe.mass = stream->ReadSwapScalar();
|
||||
recipe.friction = stream->ReadSwapScalar();
|
||||
recipe.restitution = stream->ReadSwapScalar();
|
||||
recipe.bounds = (plSimDefs::Bounds)stream->ReadByte();
|
||||
recipe.group = (plSimDefs::Group)stream->ReadByte();
|
||||
recipe.reportsOn = stream->ReadSwap32();
|
||||
fRecipe.mass = stream->ReadSwapScalar();
|
||||
fRecipe.friction = stream->ReadSwapScalar();
|
||||
fRecipe.restitution = stream->ReadSwapScalar();
|
||||
fRecipe.bounds = (plSimDefs::Bounds)stream->ReadByte();
|
||||
fRecipe.group = (plSimDefs::Group)stream->ReadByte();
|
||||
fRecipe.reportsOn = stream->ReadSwap32();
|
||||
fLOSDBs = stream->ReadSwap16();
|
||||
//hack for swim regions currently they are labeled as static av blockers
|
||||
if(fLOSDBs==plSimDefs::kLOSDBSwimRegion)
|
||||
{
|
||||
recipe.group=plSimDefs::kGroupMax;
|
||||
fRecipe.group=plSimDefs::kGroupMax;
|
||||
}
|
||||
//
|
||||
recipe.objectKey = mgr->ReadKey(stream);
|
||||
recipe.sceneNode = mgr->ReadKey(stream);
|
||||
recipe.worldKey = mgr->ReadKey(stream);
|
||||
fRecipe.objectKey = mgr->ReadKey(stream);
|
||||
fRecipe.sceneNode = mgr->ReadKey(stream);
|
||||
fRecipe.worldKey = mgr->ReadKeyNotifyMe(stream, new plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kPhysRefWorld), plRefFlags::kActiveRef);
|
||||
|
||||
mgr->ReadKeyNotifyMe(stream, TRACKED_NEW plGenRefMsg(GetKey(), plRefMsg::kOnCreate, 0, kPhysRefSndGroup), plRefFlags::kActiveRef);
|
||||
|
||||
@ -1050,30 +1058,33 @@ void plPXPhysical::Read(hsStream* stream, hsResMgr* mgr)
|
||||
hsQuat rot;
|
||||
pos.Read(stream);
|
||||
rot.Read(stream);
|
||||
rot.MakeMatrix(&recipe.l2s);
|
||||
recipe.l2s.SetTranslate(&pos);
|
||||
rot.MakeMatrix(&fRecipe.l2s);
|
||||
fRecipe.l2s.SetTranslate(&pos);
|
||||
|
||||
fProps.Read(stream);
|
||||
|
||||
if (recipe.bounds == plSimDefs::kSphereBounds)
|
||||
if (fRecipe.bounds == plSimDefs::kSphereBounds)
|
||||
{
|
||||
recipe.radius = stream->ReadSwapScalar();
|
||||
recipe.offset.Read(stream);
|
||||
fRecipe.radius = stream->ReadSwapScalar();
|
||||
fRecipe.offset.Read(stream);
|
||||
}
|
||||
else if (recipe.bounds == plSimDefs::kBoxBounds)
|
||||
else if (fRecipe.bounds == plSimDefs::kBoxBounds)
|
||||
{
|
||||
recipe.bDimensions.Read(stream);
|
||||
recipe.bOffset.Read(stream);
|
||||
fRecipe.bDimensions.Read(stream);
|
||||
fRecipe.bOffset.Read(stream);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (recipe.bounds == plSimDefs::kHullBounds)
|
||||
recipe.convexMesh = IReadHull(stream);
|
||||
if (fRecipe.bounds == plSimDefs::kHullBounds)
|
||||
fRecipe.convexMesh = IReadHull(stream);
|
||||
else
|
||||
recipe.triMesh = IReadTriMesh(stream);
|
||||
fRecipe.triMesh = IReadTriMesh(stream);
|
||||
}
|
||||
|
||||
Init(recipe);
|
||||
// If we do not have a world, specified, we go ahead and init into the main world...
|
||||
// This will been done in MsgReceive otherwise
|
||||
if (!fRecipe.worldKey)
|
||||
Init();
|
||||
|
||||
hsAssert(!fProxyGen, "Already have proxy gen, double read?");
|
||||
|
||||
@ -1115,7 +1126,7 @@ void plPXPhysical::Read(hsStream* stream, hsResMgr* mgr)
|
||||
// Statics are yellow
|
||||
physColor.Set(1.f,0.8f,0.2f,1.f);
|
||||
// if in a subworld... slightly transparent
|
||||
if(fWorldKey)
|
||||
if(fRecipe.worldKey)
|
||||
opac = 0.6f;
|
||||
}
|
||||
else
|
||||
@ -1241,7 +1252,7 @@ void plPXPhysical::Write(hsStream* stream, hsResMgr* mgr)
|
||||
stream->WriteSwapScalar(fActor->getMass());
|
||||
stream->WriteSwapScalar(friction);
|
||||
stream->WriteSwapScalar(restitution);
|
||||
stream->WriteByte(fBoundsType);
|
||||
stream->WriteByte(fRecipe.bounds);
|
||||
stream->WriteByte(fGroup);
|
||||
stream->WriteSwap32(fReportsOn);
|
||||
stream->WriteSwap16(fLOSDBs);
|
||||
@ -1259,14 +1270,14 @@ void plPXPhysical::Write(hsStream* stream, hsResMgr* mgr)
|
||||
|
||||
fProps.Write(stream);
|
||||
|
||||
if (fBoundsType == plSimDefs::kSphereBounds)
|
||||
if (fRecipe.bounds == plSimDefs::kSphereBounds)
|
||||
{
|
||||
const NxSphereShape* sphereShape = shape->isSphere();
|
||||
stream->WriteSwapScalar(sphereShape->getRadius());
|
||||
hsPoint3 localPos = plPXConvert::Point(sphereShape->getLocalPosition());
|
||||
localPos.Write(stream);
|
||||
}
|
||||
else if (fBoundsType == plSimDefs::kBoxBounds)
|
||||
else if (fRecipe.bounds == plSimDefs::kBoxBounds)
|
||||
{
|
||||
const NxBoxShape* boxShape = shape->isBox();
|
||||
hsPoint3 dim = plPXConvert::Point(boxShape->getDimensions());
|
||||
@ -1276,7 +1287,7 @@ void plPXPhysical::Write(hsStream* stream, hsResMgr* mgr)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fBoundsType == plSimDefs::kHullBounds)
|
||||
if (fRecipe.bounds == plSimDefs::kHullBounds)
|
||||
hsAssert(shape->isConvexMesh(), "Hull shape isn't a convex mesh");
|
||||
else
|
||||
hsAssert(shape->isTriangleMesh(), "Exact shape isn't a trimesh");
|
||||
|
@ -47,6 +47,9 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "../plPhysical/plSimDefs.h"
|
||||
#include "hsBitVector.h"
|
||||
#include "hsUtils.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
class NxActor;
|
||||
class NxConvexMesh;
|
||||
@ -72,8 +75,6 @@ class NxCapsule;
|
||||
class PhysRecipe
|
||||
{
|
||||
public:
|
||||
PhysRecipe();
|
||||
|
||||
hsScalar mass;
|
||||
hsScalar friction;
|
||||
hsScalar restitution;
|
||||
@ -100,6 +101,12 @@ public:
|
||||
|
||||
// For export time only. The original data used to create the mesh
|
||||
hsVectorStream* meshStream;
|
||||
|
||||
PhysRecipe()
|
||||
: mass(0.f), friction(0.f), restitution(0.f), bounds(plSimDefs::kBoundsMax),
|
||||
group(plSimDefs::kGroupMax), reportsOn(0), convexMesh(nullptr), triMesh(nullptr),
|
||||
radius(0.f), offset(0.f, 0.f, 0.f), meshStream(nullptr)
|
||||
{ }
|
||||
};
|
||||
|
||||
class plPXPhysical : public plPhysical
|
||||
@ -120,7 +127,7 @@ public:
|
||||
GETINTERFACE_ANY(plPXPhysical, plPhysical);
|
||||
|
||||
// Export time and internal use only
|
||||
hsBool Init(PhysRecipe& recipe);
|
||||
hsBool Init();
|
||||
|
||||
virtual void Read(hsStream* s, hsResMgr* mgr);
|
||||
virtual void Write(hsStream* s, hsResMgr* mgr);
|
||||
@ -191,7 +198,11 @@ public:
|
||||
//this partially for exclude regions vs avatar capsule
|
||||
virtual hsBool OverlapWithCapsule(NxCapsule& cap);
|
||||
|
||||
virtual hsScalar GetMass() {return fMass;}
|
||||
virtual hsScalar GetMass() {return fRecipe.mass;}
|
||||
|
||||
PhysRecipe& GetRecipe() { return fRecipe; }
|
||||
const PhysRecipe& GetRecipe() const { return fRecipe; }
|
||||
|
||||
protected:
|
||||
class NxConvexMesh* IReadHull(hsStream* s);
|
||||
class NxTriangleMesh* IReadTriMesh(hsStream* s);
|
||||
@ -244,12 +255,11 @@ protected:
|
||||
NxActor* fActor;
|
||||
plKey fWorldKey; // either a subworld or nil
|
||||
|
||||
plSimDefs::Bounds fBoundsType;
|
||||
PhysRecipe fRecipe;
|
||||
plSimDefs::Group fGroup;
|
||||
UInt32 fReportsOn; // bit vector for groups we report interactions with
|
||||
UInt16 fLOSDBs; // Which LOS databases we get put into
|
||||
hsBitVector fProps; // plSimulationInterface::plSimulationProperties kept here
|
||||
float fMass;
|
||||
|
||||
plKey fObjectKey; // the key to our scene object
|
||||
plKey fSceneNode; // the room we're in
|
||||
|
52
Sources/Plasma/PubUtilLib/plPhysX/plPXSubWorld.cpp
Normal file
52
Sources/Plasma/PubUtilLib/plPhysX/plPXSubWorld.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/*==LICENSE==*
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
*==LICENSE==*/
|
||||
|
||||
#include "plPXSubWorld.h"
|
||||
|
||||
void plPXSubWorld::Read(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Read(s, mgr);
|
||||
fGravity.Read(s);
|
||||
}
|
||||
|
||||
void plPXSubWorld::Write(hsStream* s, hsResMgr* mgr)
|
||||
{
|
||||
plObjInterface::Write(s, mgr);
|
||||
fGravity.Write(s);
|
||||
}
|
||||
|
||||
void plPXSubWorld::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l)
|
||||
{
|
||||
// All this magick is handled elsewhere... Not asserting due to call spam.
|
||||
}
|
67
Sources/Plasma/PubUtilLib/plPhysX/plPXSubWorld.h
Normal file
67
Sources/Plasma/PubUtilLib/plPhysX/plPXSubWorld.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*==LICENSE==*
|
||||
CyanWorlds.com Engine - MMOG client, server and tools
|
||||
Copyright (C) 2011 Cyan Worlds, Inc.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
Additional permissions under GNU GPL version 3 section 7
|
||||
If you modify this Program, or any covered work, by linking or
|
||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
|
||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
|
||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
|
||||
(or a modified version of those libraries),
|
||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
|
||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
|
||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
|
||||
licensors of this Program grant you additional
|
||||
permission to convey the resulting work. Corresponding Source for a
|
||||
non-source form of such a combination shall include the source code for
|
||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
|
||||
work.
|
||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
or by snail mail at:
|
||||
Cyan Worlds, Inc.
|
||||
14617 N Newport Hwy
|
||||
Mead, WA 99021
|
||||
*==LICENSE==*/
|
||||
|
||||
#ifndef plPXSubWorld_h_inc
|
||||
#define plPXSubWorld_h_inc
|
||||
|
||||
#include "../../NucleusLib/pnSceneObject/plObjInterface.h"
|
||||
#include "hsGeometry3.h"
|
||||
|
||||
#define X_GRAVITY 0.f
|
||||
#define Y_GRAVITY 0.f
|
||||
#define Z_GRAVITY -32.174049f
|
||||
|
||||
class plPXSubWorld : public plObjInterface
|
||||
{
|
||||
hsVector3 fGravity;
|
||||
|
||||
public:
|
||||
plPXSubWorld() : fGravity(X_GRAVITY, Y_GRAVITY, Z_GRAVITY) { }
|
||||
plPXSubWorld(const hsVector3& gravity) : fGravity(gravity) { }
|
||||
|
||||
CLASSNAME_REGISTER(plPXSubWorld);
|
||||
GETINTERFACE_ANY(plPXSubWorld, plObjInterface);
|
||||
|
||||
void Read(hsStream* s, hsResMgr* mgr) HS_OVERRIDE;
|
||||
void Write(hsStream* s, hsResMgr* mgr) HS_OVERRIDE;
|
||||
|
||||
Int32 GetNumProperties() const HS_OVERRIDE { return 0; }
|
||||
void SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l) HS_OVERRIDE;
|
||||
|
||||
const hsVector3& GetGravity() const { return fGravity; }
|
||||
hsVector3& GetGravity() { return fGravity; }
|
||||
void SetGravity(const hsVector3& gravity) { fGravity = gravity; }
|
||||
};
|
||||
|
||||
#endif // plPXSubWorld_h_inc
|
@ -48,6 +48,9 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
|
||||
REGISTER_CREATABLE(plPXPhysical);
|
||||
|
||||
#include "plPXSubWorld.h"
|
||||
REGISTER_CREATABLE(plPXSubWorld);
|
||||
|
||||
//#include "plHKSimulationSynchMsg.h"
|
||||
//REGISTER_CREATABLE(plHKSimulationSynchMsg);
|
||||
|
||||
|
@ -49,6 +49,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
|
||||
#include "plPXPhysical.h"
|
||||
#include "plPXPhysicalControllerCore.h"
|
||||
#include "plPXConvert.h"
|
||||
#include "plPXSubWorld.h"
|
||||
#include "plLOSDispatch.h"
|
||||
#include "../plPhysical/plPhysicsSoundMgr.h"
|
||||
#include "../plStatusLog/plStatusLog.h"
|
||||
@ -424,8 +425,18 @@ NxScene* plSimulationMgr::GetScene(plKey world)
|
||||
{
|
||||
UInt32 maxSteps = (UInt32)hsCeil(fMaxDelta / fStepSize);
|
||||
|
||||
// The world key is assumed to be loaded (or null for main world) if we are here.
|
||||
// As such, let us grab the plSceneObject's PXSubWorld definition to figure out
|
||||
// what gravity should look like. Who knows, we might be in MC Escher land...
|
||||
NxVec3 gravity(X_GRAVITY, Y_GRAVITY, Z_GRAVITY);
|
||||
if (plSceneObject* so = plSceneObject::ConvertNoRef(world->VerifyLoaded())) {
|
||||
if (plPXSubWorld* subworld = plPXSubWorld::ConvertNoRef(so->GetGenericInterface(plPXSubWorld::Index()))) {
|
||||
gravity = plPXConvert::Vector(subworld->GetGravity());
|
||||
}
|
||||
}
|
||||
|
||||
NxSceneDesc sceneDesc;
|
||||
sceneDesc.gravity.set(0, 0, -32.174049f);
|
||||
sceneDesc.gravity = gravity;
|
||||
sceneDesc.userTriggerReport = &gSensorReport;
|
||||
sceneDesc.userContactReport = &gContactReport;
|
||||
sceneDesc.maxTimestep = fStepSize;
|
||||
|
Reference in New Issue
Block a user