Browse Source

Merged in Skoader/cwe-ou/avatar-physics (pull request #20)

Avatar physics update

A significant and much needed cleanup of the avatar physics code. It resolves numerous issue with and greatly simplifies the physx character controller implementation.

While there is still room for improvement, this is a good starting point.

Avatars now jump consistently, regardless of cpu speed. Fixes unexpected camera transitions with entering/exiting some subworlds. (Teledahn elevator) Fixes a jitter in animated subworlds. (Er'cana harvester) Dynamic controllers are correctly positioned on the ground. (Jalak) Much improved interaction with dynamic physicals.

Other physics related issues may or may not be addressed.
lostlogins
Christian Walther 12 years ago
parent
commit
96ae8a88ed
  1. 4
      MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj
  2. 12
      MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj.filters
  3. 46
      MOULOpenSourceClientPlugin/Plasma20/MsDevProjects/Plasma/PubUtilLib/plAvatar/plAvatar.vcproj
  4. 2
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfAudio/plListener.cpp
  5. 2
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfCamera/plCameraModifier.cpp
  6. 2
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfPython/pySceneObject.cpp
  7. 1
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAnimStage.cpp
  8. 171
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.cpp
  9. 79
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.h
  10. 1
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureEffects.cpp
  11. 19
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp
  12. 1
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.h
  13. 20
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp
  14. 6
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h
  15. 1
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainDrive.cpp
  16. 4
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.cpp
  17. 2
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.h
  18. 157
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.cpp
  19. 4
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.h
  20. 13
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.cpp
  21. 2
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.h
  22. 137
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.cpp
  23. 7
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.h
  24. 579
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.cpp
  25. 217
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.h
  26. 4
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvLadderModifier.cpp
  27. 6
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvTaskSeek.cpp
  28. 2
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarSDLModifier.cpp
  29. 4
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarTasks.cpp
  30. 1289
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp
  31. 418
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.h
  32. 2
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.cpp
  33. 1
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plModifier/plExcludeRegionModifier.cpp
  34. 3
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plLOSDispatch.cpp
  35. 1279
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysicalController.cpp
  36. 211
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysicalController.h
  37. 1447
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysicalControllerCore.cpp
  38. 158
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysicalControllerCore.h
  39. 113
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp
  40. 5
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.h
  41. 448
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp
  42. 65
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.h
  43. 23
      MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plSimDefs.h

4
MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj

@ -328,7 +328,6 @@
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release_Internal|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release_Internal|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAntiGravAction.cpp" />
<ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.cpp"> <ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug_Internal|Win32'">Disabled</Optimization> <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug_Internal|Win32'">Disabled</Optimization>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization> <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
@ -555,7 +554,6 @@
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release_Internal|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release_Internal|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvCallbackAction.cpp" />
<ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvLadderModifier.cpp"> <ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvLadderModifier.cpp">
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug_Internal|Win32'">Disabled</Optimization> <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug_Internal|Win32'">Disabled</Optimization>
<Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization> <Optimization Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Disabled</Optimization>
@ -807,7 +805,6 @@
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAGMasterSDLModifier.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAGMasterSDLModifier.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAGModifier.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAGModifier.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAnimStage.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAnimStage.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAntiGravAction.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureMod.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureMod.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvatarClothing.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvatarClothing.h" />
@ -825,7 +822,6 @@
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainHuman.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainHuman.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainRideAnimatedPhysical.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainRideAnimatedPhysical.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainSwim.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainSwim.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvCallbackAction.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvDefs.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvDefs.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvLadderModifier.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvLadderModifier.h" />
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvTask.h" /> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvTask.h" />

12
MOULOpenSourceClientPlugin/Plasma20/MSVC10Projects/Plasma/PubUtilLib/plAvatar/plAvatar.vcxproj.filters

@ -35,9 +35,6 @@
<ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAnimStage.cpp"> <ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAnimStage.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAntiGravAction.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.cpp"> <ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -86,9 +83,6 @@
<ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainSwim.cpp"> <ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainSwim.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvCallbackAction.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvLadderModifier.cpp"> <ClCompile Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvLadderModifier.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -163,9 +157,6 @@
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAnimStage.h"> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAnimStage.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAntiGravAction.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.h"> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -217,9 +208,6 @@
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainSwim.h"> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainSwim.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvCallbackAction.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvDefs.h"> <ClInclude Include="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvDefs.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>

46
MOULOpenSourceClientPlugin/Plasma20/MsDevProjects/Plasma/PubUtilLib/plAvatar/plAvatar.vcproj

@ -282,26 +282,6 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAntiGravAction.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
BasicRuntimeChecks="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File <File
RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.cpp"> RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.cpp">
<FileConfiguration <FileConfiguration
@ -588,26 +568,6 @@
PreprocessorDefinitions=""/> PreprocessorDefinitions=""/>
</FileConfiguration> </FileConfiguration>
</File> </File>
<File
RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvCallbackAction.cpp">
<FileConfiguration
Name="Debug|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""
BasicRuntimeChecks="3"/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32">
<Tool
Name="VCCLCompilerTool"
Optimization="2"
AdditionalIncludeDirectories=""
PreprocessorDefinitions=""/>
</FileConfiguration>
</File>
<File <File
RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvLadderModifier.cpp"> RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvLadderModifier.cpp">
<FileConfiguration <FileConfiguration
@ -939,9 +899,6 @@
<File <File
RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAnimStage.h"> RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAnimStage.h">
</File> </File>
<File
RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAntiGravAction.h">
</File>
<File <File
RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.h"> RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plArmatureEffects.h">
</File> </File>
@ -993,9 +950,6 @@
<File <File
RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainSwim.h"> RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvBrainSwim.h">
</File> </File>
<File
RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvCallbackAction.h">
</File>
<File <File
RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvDefs.h"> RelativePath="..\..\..\..\Sources\Plasma\PubUtilLib\plAvatar\plAvDefs.h">
</File> </File>

2
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfAudio/plListener.cpp

@ -57,7 +57,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plAvatar/plAvatarMgr.h" #include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plArmatureMod.h" #include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvCallbackAction.h" #include "../plAvatar/plPhysicalControllerCore.h"
hsBool plListener::fPrintDbgInfo = false; hsBool plListener::fPrintDbgInfo = false;

2
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfCamera/plCameraModifier.cpp

@ -63,7 +63,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../pnSceneObject/plSimulationInterface.h" #include "../pnSceneObject/plSimulationInterface.h"
#include "../plAvatar/plAvatarMgr.h" #include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plArmatureMod.h" #include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvCallbackAction.h" #include "../plAvatar/plPhysicalControllerCore.h"
// new stuff // new stuff

2
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/FeatureLib/pfPython/pySceneObject.cpp

@ -545,7 +545,7 @@ hsBool pySceneObject::IsAvatar()
return false; return false;
} }
#include "../plAvatar/plAvCallbackAction.h" #include "../plAvatar/plPhysicalControllerCore.h"
PyObject* pySceneObject::GetAvatarVelocity() PyObject* pySceneObject::GetAvatarVelocity()
{ {

1
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAnimStage.cpp

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021 Mead, WA 99021
*==LICENSE==*/ *==LICENSE==*/
#include "plAvCallbackAction.h" // must be first: references havok new
// singular // singular
#include "plAnimStage.h" #include "plAnimStage.h"

171
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.cpp

@ -1,171 +0,0 @@
/*==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==*/
#if 0
// havok first
#include <hkdynamics/entity/rigidbody.h>
#include <hkdynamics/world/subspace.h>
#include "plAntiGravAction.h"
#include "../pnSceneObject/plSceneObject.h"
#include "../plHavok1/plHKPhysical.h"
#include "../plAvatar/plSwimRegion.h"
#include "hsTimer.h"
// This is meant to be a specific physicsAction for the swim behavior
plAntiGravAction::plAntiGravAction(plHKPhysical *physical, plAGApplicator *rootApp) :
plAnimatedCallbackAction(physical, rootApp),
fOnGround(false),
fBuoyancy(1.f),
fSurfaceHeight(0.f),
fCurrentRegion(nil),
fHadContacts(false)
{
}
plSimDefs::ActionType plAntiGravAction::GetType()
{
return plSimDefs::kAntiGravAction;
}
void plAntiGravAction::apply(Havok::Subspace &space, Havok::hkTime time)
{
double elapsed = time.asDouble() - getRefresh().asDouble();
setRefresh(time);
IAdjustBuoyancy();
Havok::RigidBody *body = fPhysical->GetBody();
float mass = body->getMass();
Havok::Vector3 gravity = space.getGravity();
Havok::Vector3 force = -gravity * (mass * fBuoyancy);
body->applyForce(force);
hsVector3 vel;
fPhysical->GetLinearVelocitySim(vel);
fAnimPosVel.fZ = vel.fZ;
hsVector3 linCurrent(0.f, 0.f, 0.f);
hsScalar angCurrent = 0.f;
if (fCurrentRegion != nil)
fCurrentRegion->GetCurrent(fPhysical, linCurrent, angCurrent, (hsScalar)elapsed);
int numContacts = fPhysical->GetNumContacts();
fHadContacts = (numContacts > 0);
const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f);
fOnGround = false;
int i;
for (i = 0; i < numContacts; i++)
{
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
hsScalar dotUp = straightUp.dot(contact->m_normal);
if (dotUp > .5)
{
fOnGround = true;
break;
}
}
fPhysical->SetLinearVelocitySim(fAnimPosVel + linCurrent);
fPhysical->SetAngularVelocitySim(hsVector3(0.f, 0.f, fAnimAngVel + fTurnStr + angCurrent));
}
void plAntiGravAction::SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight)
{
fCurrentRegion = region;
if (region != nil)
fSurfaceHeight = surfaceHeight;
}
void plAntiGravAction::IAdjustBuoyancy()
{
// "surface depth" refers to the depth our handle object should be below
// the surface for the avatar to be "at the surface"
static const float surfaceDepth = 4.0f;
// 1.0 = neutral buoyancy
// 0 = no buoyancy (normal gravity)
// 2.0 = opposite of gravity, floating upwards
static const float buoyancyAtSurface = 1.0f;
if (fCurrentRegion == nil)
{
fBuoyancy = 0.f;
return;
}
hsMatrix44 l2w, w2l;
fPhysical->GetTransform(l2w, w2l);
float depth = fSurfaceHeight - surfaceDepth - l2w.GetTranslate().fZ;
if (depth < -1)
fBuoyancy = 0.f; // Same as being above ground. Plain old gravity.
else if (depth < 0)
fBuoyancy = 1 + depth;
else
{
hsVector3 vel;
fPhysical->GetLinearVelocitySim(vel);
if (vel.fZ > 0)
{
if (vel.fZ > fCurrentRegion->fMaxUpwardVel)
{
vel.fZ = fCurrentRegion->fMaxUpwardVel;
fPhysical->SetLinearVelocitySim(vel);
}
else
{
if (depth > 1)
fBuoyancy = fCurrentRegion->fUpBuoyancy;
else
fBuoyancy = (fCurrentRegion->fUpBuoyancy - 1) * depth + 1;
}
}
else
{
if (depth > 1)
fBuoyancy = fCurrentRegion->fDownBuoyancy;
else
fBuoyancy = (fCurrentRegion->fDownBuoyancy - 1) * depth + 1;
}
}
}
#endif

79
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAntiGravAction.h

@ -1,79 +0,0 @@
/*==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==*/
#if 0//ndef PL_ANTI_GRAV_ACTION_H
#define PL_ANTI_GRAV_ACTION_H
#include "plAvCallbackAction.h"
class plSwimRegionInterface;
class plAntiGravAction : public plAnimatedCallbackAction
{
public:
plAntiGravAction(plHKPhysical *physical, plAGApplicator *rootApp);
/** Return the type of the action as defined in the enum plSimDefs::ActionType.
Used to retrieve actions by entity/type indexing, and to
reuse actions that can be shared between entities. */
virtual plSimDefs::ActionType GetType();
/** Called by Havok at substep frequency. */
void apply(Havok::Subspace &s, Havok::hkTime time);
void SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight);
hsScalar GetBuoyancy() { return fBuoyancy; }
hsBool IsOnGround() { return fOnGround; }
hsBool HadContacts() { return fHadContacts; }
protected:
void IAdjustBuoyancy();
hsBool fOnGround;
hsBool fHadContacts;
hsScalar fBuoyancy;
hsScalar fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion;
};
#endif

1
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureEffects.cpp

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021 Mead, WA 99021
*==LICENSE==*/ *==LICENSE==*/
#include "plAvCallbackAction.h"
#include "../plStatusLog/plStatusLog.h" #include "../plStatusLog/plStatusLog.h"
#include "plArmatureEffects.h" #include "plArmatureEffects.h"

19
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.cpp

@ -54,7 +54,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAvBrainHuman.h" #include "plAvBrainHuman.h"
#include "plMatrixChannel.h" #include "plMatrixChannel.h"
#include "plAvatarTasks.h" #include "plAvatarTasks.h"
#include "plAvCallbackAction.h" #include "plPhysicalControllerCore.h"
#include "plAvBrainCritter.h" #include "plAvBrainCritter.h"
// global // global
@ -534,8 +534,7 @@ void plArmatureModBase::EnablePhysics(hsBool status, UInt16 reason /* = kDisable
// i.e. normal enabled physical // i.e. normal enabled physical
void plArmatureModBase::EnablePhysicsKinematic(hsBool status) void plArmatureModBase::EnablePhysicsKinematic(hsBool status)
{ {
if (fController) EnablePhysics(!status, kDisableReasonKinematic);
fController->Kinematic(status);
} }
void plArmatureModBase::EnableDrawing(hsBool status, UInt16 reason /* = kDisableReasonUnknown */) void plArmatureModBase::EnableDrawing(hsBool status, UInt16 reason /* = kDisableReasonUnknown */)
@ -2007,7 +2006,7 @@ hsBool plArmatureMod::ValidatePhysics()
return false; return false;
if (!fController) if (!fController)
fController = plPhysicalControllerCore::Create(GetTarget(0)->GetKey(), fPhysHeight, fPhysWidth); fController = plPhysicalControllerCore::Create(GetTarget(0)->GetKey(), fPhysHeight, fPhysWidth, (fBodyType == kBoneBaseMale || fBodyType == kBoneBaseFemale));
if (fController) if (fController)
{ {
@ -2684,19 +2683,7 @@ void plArmatureMod::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *str
debugTxt.DrawString(x, y, strBuf); debugTxt.DrawString(x, y, strBuf);
y += lineHeight; y += lineHeight;
hsPoint3 kPos;
char *kinematic = "n.a.";
const char* frozen = "n.a."; const char* frozen = "n.a.";
if (fController)
{
fController->GetKinematicPosition(kPos);
kinematic = fController->IsKinematic() ? "on" : "off";
}
sprintf(strBuf, "kinematc(world): %.2f, %.2f, %.2f Kinematic: %3s",
kPos.fX, kPos.fY, kPos.fZ,kinematic);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
if (fController) if (fController)
frozen = fController->IsEnabled() ? "no" : "yes"; frozen = fController->IsEnabled() ? "no" : "yes";

1
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plArmatureMod.h

@ -145,6 +145,7 @@ public:
kDisableReasonCCR = 0x0008, kDisableReasonCCR = 0x0008,
kDisableReasonVehicle = 0x0010, kDisableReasonVehicle = 0x0010,
kDisableReasonGenericBrain = 0x0020, kDisableReasonGenericBrain = 0x0020,
kDisableReasonKinematic = 0x0040
}; };
void EnablePhysics(hsBool status, UInt16 reason = kDisableReasonUnknown); void EnablePhysics(hsBool status, UInt16 reason = kDisableReasonUnknown);
void EnablePhysicsKinematic(hsBool status); void EnablePhysicsKinematic(hsBool status);

20
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.cpp

@ -42,7 +42,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsConfig.h" #include "hsConfig.h"
#include "hsWindows.h" #include "hsWindows.h"
#include "plAvCallbackAction.h" #include "plPhysicalControllerCore.h"
#include "plAvBrainCritter.h" #include "plAvBrainCritter.h"
#include "plAvBrainHuman.h" #include "plAvBrainHuman.h"
#include "plArmatureMod.h" #include "plArmatureMod.h"
@ -127,7 +127,7 @@ protected:
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
plAvBrainCritter::plAvBrainCritter(): fCallbackAction(nil), fCurMode(kIdle), fNextMode(kIdle), fFadingNextBehavior(true), plAvBrainCritter::plAvBrainCritter(): fWalkingStrategy(nil), fCurMode(kIdle), fNextMode(kIdle), fFadingNextBehavior(true),
fLocallyControlled(false), fAvoidingAvatars(false), fFinalGoalPos(0, 0, 0), fImmediateGoalPos(0, 0, 0), fDotGoal(0), fLocallyControlled(false), fAvoidingAvatars(false), fFinalGoalPos(0, 0, 0), fImmediateGoalPos(0, 0, 0), fDotGoal(0),
fAngRight(0) fAngRight(0)
{ {
@ -145,8 +145,8 @@ plAvBrainCritter::~plAvBrainCritter()
fBehaviors[i] = nil; fBehaviors[i] = nil;
} }
delete fCallbackAction; delete fWalkingStrategy;
fCallbackAction = nil; fWalkingStrategy = nil;
fUserBehaviors.clear(); fUserBehaviors.clear();
fReceivers.clear(); fReceivers.clear();
@ -169,8 +169,8 @@ hsBool plAvBrainCritter::Apply(double time, hsScalar elapsed)
IProcessBehavior(time, elapsed); // just continue with the currently running one IProcessBehavior(time, elapsed); // just continue with the currently running one
// update our controller to keep us turned and moving to where we want to go // update our controller to keep us turned and moving to where we want to go
fCallbackAction->RecalcVelocity(time, time - elapsed); fWalkingStrategy->SetTurnStrength(IGetTurnStrength(time));
fCallbackAction->SetTurnStrength(IGetTurnStrength(time)); fWalkingStrategy->RecalcVelocity(time, elapsed);
return plArmatureBrain::Apply(time, elapsed); return plArmatureBrain::Apply(time, elapsed);
} }
@ -190,13 +190,13 @@ void plAvBrainCritter::Activate(plArmatureModBase* avMod)
IInitBaseAnimations(); IInitBaseAnimations();
// create the controller if we haven't done so already // create the controller if we haven't done so already
if (!fCallbackAction) if (!fWalkingStrategy)
{ {
plSceneObject* avObj = fArmature->GetTarget(0); plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = avMod->GetController(); plPhysicalControllerCore* controller = avMod->GetController();
fCallbackAction = TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller); fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController(); controller->SetMovementStrategy(fWalkingStrategy);
} }
// tell people that care that we are good to go // tell people that care that we are good to go
@ -226,7 +226,7 @@ void plAvBrainCritter::Resume()
// fade in the idle // fade in the idle
fNextMode = kIdle; fNextMode = kIdle;
fCallbackAction->Reset(false); fWalkingStrategy->Reset(false);
plArmatureBrain::Resume(); plArmatureBrain::Resume();
} }

6
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainCritter.h

@ -47,7 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../pnKeyedObject/plKey.h" #include "../pnKeyedObject/plKey.h"
class plArmatureMod; class plArmatureMod;
class plWalkingController; class plWalkingStrategy;
class plAIMsg; class plAIMsg;
class plAvBrainCritter : public plArmatureBrain class plAvBrainCritter : public plArmatureBrain
@ -127,8 +127,6 @@ public:
virtual void DumpToDebugDisplay(int& x, int& y, int lineHeight, char* strBuf, plDebugText& debugTxt); virtual void DumpToDebugDisplay(int& x, int& y, int lineHeight, char* strBuf, plDebugText& debugTxt);
plWalkingController* GetCallbackAction() {return fCallbackAction;}
// For the console // For the console
static bool fDrawDebug; static bool fDrawDebug;
@ -152,7 +150,7 @@ protected:
std::vector<plArmatureMod*> IAvatarsICanSee() const; std::vector<plArmatureMod*> IAvatarsICanSee() const;
std::vector<plArmatureMod*> IAvatarsICanHear() const; std::vector<plArmatureMod*> IAvatarsICanHear() const;
plWalkingController* fCallbackAction; plWalkingStrategy* fWalkingStrategy;
int fCurMode; // current behavior we are running int fCurMode; // current behavior we are running
int fNextMode; // the next behavior to run (-1 if we aren't switching on next eval) int fNextMode; // the next behavior to run (-1 if we aren't switching on next eval)
bool fFadingNextBehavior; // is the next behavior supposed to blend? bool fFadingNextBehavior; // is the next behavior supposed to blend?

1
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainDrive.cpp

@ -42,7 +42,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
// local includes // local includes
#include "plAvBrainDrive.h" #include "plAvBrainDrive.h"
#include "plArmatureMod.h" #include "plArmatureMod.h"
#include "plAvCallbackAction.h"
// global includes // global includes
#include "hsTimer.h" #include "hsTimer.h"

4
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.cpp

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021 Mead, WA 99021
*==LICENSE==*/ *==LICENSE==*/
#include "plAvCallbackAction.h" // havok-contaminated file: must go first
// singular // singular
#include "plAvBrainGeneric.h" #include "plAvBrainGeneric.h"
@ -94,7 +93,6 @@ plAvBrainGeneric::plAvBrainGeneric()
fFadeIn(0.0f), fFadeIn(0.0f),
fFadeOut(0.0f), fFadeOut(0.0f),
fMoveMode(kMoveRelative), fMoveMode(kMoveRelative),
fCallbackAction(nil),
fBodyUsage(plAGAnim::kBodyUnknown) fBodyUsage(plAGAnim::kBodyUnknown)
{ {
} }
@ -122,7 +120,6 @@ plAvBrainGeneric::plAvBrainGeneric(plAnimStageVec *stages,
fFadeIn(fadeIn), fFadeIn(fadeIn),
fFadeOut(fadeOut), fFadeOut(fadeOut),
fMoveMode(moveMode), fMoveMode(moveMode),
fCallbackAction(nil),
fBodyUsage(plAGAnim::kBodyUnknown) fBodyUsage(plAGAnim::kBodyUnknown)
{ {
} }
@ -141,7 +138,6 @@ plAvBrainGeneric::plAvBrainGeneric(UInt32 exitFlags, float fadeIn, float fadeOut
fFadeIn(fadeIn), fFadeIn(fadeIn),
fFadeOut(fadeOut), fFadeOut(fadeOut),
fMoveMode(moveMode), fMoveMode(moveMode),
fCallbackAction(nil),
fBodyUsage(plAGAnim::kBodyUnknown) fBodyUsage(plAGAnim::kBodyUnknown)
{ {

2
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainGeneric.h

@ -49,7 +49,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
class plAnimStage; class plAnimStage;
class plAnimStageVec; class plAnimStageVec;
class plAvBrainGenericMsg; class plAvBrainGenericMsg;
class plHorizontalFreezeAction;
class plNotifyMsg; class plNotifyMsg;
/** \class plAvBrainGeneric /** \class plAvBrainGeneric
@ -300,7 +299,6 @@ protected:
int fCurStage; // which stage are we playing? (zero-based) int fCurStage; // which stage are we playing? (zero-based)
BrainType fType; // what type of brain are we? BrainType fType; // what type of brain are we?
UInt32 fExitFlags; // what will cause us to exit? UInt32 fExitFlags; // what will cause us to exit?
plHorizontalFreezeAction *fCallbackAction;
bool fForward; // are we currently moving forward or backward through the stages? bool fForward; // are we currently moving forward or backward through the stages?
// this is used by the "auto-" movement types in the stages // this is used by the "auto-" movement types in the stages

157
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.cpp

@ -42,9 +42,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsConfig.h" #include "hsConfig.h"
#include "hsWindows.h" #include "hsWindows.h"
#include "plAvCallbackAction.h" // subclasses a havok object; must be in first include section #include "plPhysicalControllerCore.h"
#include "plAvBrainHuman.h" #include "plAvBrainHuman.h"
#include "plAvBrainClimb.h" #include "plAvBrainClimb.h"
#include "plAvBrainDrive.h" #include "plAvBrainDrive.h"
@ -142,7 +140,7 @@ plAvBrainHuman::TurnCurve plAvBrainHuman::GetTurnCurve(hsBool walk)
plAvBrainHuman::plAvBrainHuman(bool isActor /* = false */) : plAvBrainHuman::plAvBrainHuman(bool isActor /* = false */) :
fHandleAGMod(nil), fHandleAGMod(nil),
fStartedTurning(-1.0f), fStartedTurning(-1.0f),
fCallbackAction(nil), fWalkingStrategy(nil),
fPreconditions(0), fPreconditions(0),
fIsActor(isActor) fIsActor(isActor)
{ {
@ -156,9 +154,9 @@ hsBool plAvBrainHuman::Apply(double timeNow, hsScalar elapsed)
#endif #endif
// SetTurnStrength runs first to make sure it's set to a sane value // SetTurnStrength runs first to make sure it's set to a sane value
// (or cleared). RunStandardBehaviors may overwrite it. // (or cleared). RunStandardBehaviors may overwrite it.
fCallbackAction->SetTurnStrength(IGetTurnStrength(timeNow)); fWalkingStrategy->SetTurnStrength(IGetTurnStrength(timeNow));
RunStandardBehaviors(timeNow, elapsed); RunStandardBehaviors(timeNow, elapsed);
fCallbackAction->RecalcVelocity(timeNow, timeNow - elapsed, (fPreconditions & plHBehavior::kBehaviorTypeNeedsRecalcMask)); fWalkingStrategy->RecalcVelocity(timeNow, elapsed, (fPreconditions & plHBehavior::kBehaviorTypeNeedsRecalcMask));
plArmatureBrain::Apply(timeNow, elapsed); plArmatureBrain::Apply(timeNow, elapsed);
#ifndef _DEBUG #ifndef _DEBUG
@ -179,13 +177,13 @@ void plAvBrainHuman::Activate(plArmatureModBase *avMod)
IInitBoneMap(); IInitBoneMap();
IInitAnimations(); IInitAnimations();
if (!fCallbackAction) if (!fWalkingStrategy)
{ {
plSceneObject* avObj = fArmature->GetTarget(0); plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = avMod->GetController(); plPhysicalControllerCore* controller = avMod->GetController();
fCallbackAction = TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller); fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController(); controller->SetMovementStrategy(fWalkingStrategy);
} }
@ -330,8 +328,8 @@ plAvBrainHuman::~plAvBrainHuman()
delete fBehaviors[i]; delete fBehaviors[i];
fBehaviors.Reset(); fBehaviors.Reset();
delete fCallbackAction; delete fWalkingStrategy;
fCallbackAction = nil; fWalkingStrategy = nil;
} }
void plAvBrainHuman::Deactivate() void plAvBrainHuman::Deactivate()
@ -364,7 +362,7 @@ void plAvBrainHuman::Resume()
if (fAvMod->GetInputFlag(S_PUSH_TO_TALK)) if (fAvMod->GetInputFlag(S_PUSH_TO_TALK))
IChatOn(); IChatOn();
fCallbackAction->Reset(false); fWalkingStrategy->Reset(false);
plArmatureBrain::Resume(); plArmatureBrain::Resume();
} }
@ -468,25 +466,23 @@ hsBool plAvBrainHuman::MsgReceive(plMessage * msg)
{ {
if(ride->Entering()) if(ride->Entering())
{ {
//plAvBrainRideAnimatedPhysical *rideBrain = TRACKED_NEW plAvBrainRideAnimatedPhysical(); // Switch to dynamic walking strategy
//fAvMod->PushBrain(rideBrain); delete fWalkingStrategy;
delete fCallbackAction;
plSceneObject* avObj = fArmature->GetTarget(0); plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = fAvMod->GetController(); plPhysicalControllerCore* controller = fAvMod->GetController();
fCallbackAction= TRACKED_NEW plRidingAnimatedPhysicalController(avObj, agMod->GetApplicator(kAGPinTransform), controller); fWalkingStrategy = TRACKED_NEW plDynamicWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController(); controller->SetMovementStrategy(fWalkingStrategy);
} }
else else
{ {
delete fCallbackAction; // Restore default walking strategy
delete fWalkingStrategy;
plSceneObject* avObj = fArmature->GetTarget(0); plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = fAvMod->GetController(); plPhysicalControllerCore* controller = fAvMod->GetController();
fCallbackAction= TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller); fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController(); controller->SetMovementStrategy(fWalkingStrategy);
//hsStatusMessage("Got an exiting ride animated physical message");
} }
} }
@ -560,8 +556,8 @@ hsScalar plAvBrainHuman::IGetTurnStrength(double timeNow)
// Turning based on keypress // Turning based on keypress
if ((turnLeftStrength > 0.f) if ((turnLeftStrength > 0.f)
|| (turnRightStrength > 0.f) || (turnRightStrength > 0.f)
|| (!fCallbackAction->IsOnGround() || (!fWalkingStrategy->IsOnGround()
&& !fCallbackAction->IsControlledFlight()) && !fWalkingStrategy->IsControlledFlight())
) { ) {
float t = (float)(timeNow - fStartedTurning); float t = (float)(timeNow - fStartedTurning);
float turnSpeed; float turnSpeed;
@ -593,7 +589,7 @@ hsScalar plAvBrainHuman::IGetTurnStrength(double timeNow)
result += fAvMod->GetKeyTurnStrength() * turnSpeed; result += fAvMod->GetKeyTurnStrength() * turnSpeed;
} }
if (!fCallbackAction->IsControlledFlight()) if (!fWalkingStrategy->IsControlledFlight())
result += fAvMod->GetAnalogTurnStrength() * maxTurnSpeed; result += fAvMod->GetAnalogTurnStrength() * maxTurnSpeed;
return result; return result;
@ -650,7 +646,7 @@ void plAvBrainHuman::ResetIdle()
void plAvBrainHuman::IdleOnly(bool instantOff) void plAvBrainHuman::IdleOnly(bool instantOff)
{ {
if (!fCallbackAction) if (!fWalkingStrategy)
return; return;
hsScalar rate = instantOff ? 0.f : 1.f; hsScalar rate = instantOff ? 0.f : 1.f;
@ -676,7 +672,7 @@ bool plAvBrainHuman::IsMovementZeroBlend()
void plAvBrainHuman::TurnToPoint(hsPoint3 point) void plAvBrainHuman::TurnToPoint(hsPoint3 point)
{ {
if (!fCallbackAction->IsOnGround() || IsRunningTask() || fAvMod->GetCurrentBrain() != this || !IsMovementZeroBlend()) if (!fWalkingStrategy->IsOnGround() || IsRunningTask() || fAvMod->GetCurrentBrain() != this || !IsMovementZeroBlend())
return; return;
hsPoint3 avPos; hsPoint3 avPos;
@ -875,23 +871,23 @@ void plAvBrainHuman::Spawn(double timeNow)
hsBool plAvBrainHuman::LeaveAge() hsBool plAvBrainHuman::LeaveAge()
{ {
plPhysicalControllerCore* controller = fAvMod->GetController(); plPhysicalControllerCore* controller = fAvMod->GetController();
if(!controller->BehavingLikeAnAnimatedPhysical())
// If our current walking strategy is dynamic, restore the default kinematic strategy.
if (!fWalkingStrategy->IsKinematic())
{ {
controller->BehaveLikeAnimatedPhysical(true); delete fWalkingStrategy;
delete fCallbackAction;
plSceneObject* avObj = fArmature->GetTarget(0); plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
fCallbackAction= TRACKED_NEW plWalkingController(avObj, agMod->GetApplicator(kAGPinTransform), controller); fWalkingStrategy = TRACKED_NEW plWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController();
} }
plArmatureBrain::LeaveAge();
fWalkingStrategy->Reset(true);
plArmatureBrain::LeaveAge();
// pin the physical so it doesn't fall when the world is deleted // pin the physical so it doesn't fall when the world is deleted
fAvMod->EnablePhysics(false); fAvMod->EnablePhysics(false);
// this will get set to true when we hit ground
fCallbackAction->Reset(true);
return false; return false;
} }
@ -901,11 +897,10 @@ void plAvBrainHuman::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *st
debugTxt.DrawString(x, y, strBuf); debugTxt.DrawString(x, y, strBuf);
y += lineHeight; y += lineHeight;
const char *grounded = fCallbackAction->IsOnGround() ? "yes" : "no"; const char *grounded = fWalkingStrategy->IsOnGround() ? "yes" : "no";
const char *falseGrounded = fCallbackAction->IsOnFalseGround() ? "yes" : "no"; const char *pushing = (fWalkingStrategy->GetPushingPhysical() ? (fWalkingStrategy->GetFacingPushingPhysical() ? "facing" : "behind") : "none");
const char *pushing = (fCallbackAction->GetPushingPhysical() ? (fCallbackAction->GetFacingPushingPhysical() ? "facing" : "behind") : "none"); sprintf(strBuf, "Ground: %3s, AirTime: %5.2f (Peak: %5.2f), PushingPhys: %6s",
sprintf(strBuf, "Ground: %3s, FalseGround: %3s, AirTime: %5.2f (Peak: %5.2f), PushingPhys: %6s", grounded, fWalkingStrategy->GetAirTime(), fWalkingStrategy->GetImpactTime(), pushing);
grounded, falseGrounded, fCallbackAction->GetAirTime(), fCallbackAction->GetImpactTime(), pushing);
debugTxt.DrawString(x, y, strBuf); debugTxt.DrawString(x, y, strBuf);
y += lineHeight; y += lineHeight;
@ -1018,8 +1013,8 @@ hsBool Run::PreCondition(double time, float elapsed)
{ {
if (fAnim) if (fAnim)
{ {
if (fAvMod->ForwardKeyDown() && fAvMod->FastKeyDown() && fHuBrain->fCallbackAction->IsOnGround() && if (fAvMod->ForwardKeyDown() && fAvMod->FastKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true; return true;
} }
return false; return false;
@ -1029,8 +1024,8 @@ hsBool Walk::PreCondition(double time, float elapsed)
{ {
if (fAnim) if (fAnim)
{ {
if (fAvMod->ForwardKeyDown() && !fAvMod->FastKeyDown() && fHuBrain->fCallbackAction->IsOnGround() && if (fAvMod->ForwardKeyDown() && !fAvMod->FastKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true; return true;
} }
return false; return false;
@ -1040,8 +1035,8 @@ hsBool WalkBack::PreCondition(double time, float elapsed)
{ {
if (fAnim) if (fAnim)
{ {
if (fAvMod->BackwardKeyDown() && !fAvMod->ForwardKeyDown() && fHuBrain->fCallbackAction->IsOnGround() && if (fAvMod->BackwardKeyDown() && !fAvMod->ForwardKeyDown() && fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || fHuBrain->fCallbackAction->GetFacingPushingPhysical())) (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true; return true;
} }
return false; return false;
@ -1054,7 +1049,7 @@ hsBool StepLeft::PreCondition(double time, float elapsed)
return ((fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) && return ((fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) &&
!(fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) && !(fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) &&
!(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) && !(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
fHuBrain->fCallbackAction->IsOnGround()); fHuBrain->fWalkingStrategy->IsOnGround());
} }
return false; return false;
} }
@ -1066,7 +1061,7 @@ hsBool StepRight::PreCondition(double time, float elapsed)
return ((fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) && return ((fAvMod->StrafeRightKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnRightKeyDown())) &&
!(fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) && !(fAvMod->StrafeLeftKeyDown() || (fAvMod->StrafeKeyDown() && fAvMod->TurnLeftKeyDown())) &&
!(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) && !(fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
fHuBrain->fCallbackAction->IsOnGround()); fHuBrain->fWalkingStrategy->IsOnGround());
} }
return false; return false;
} }
@ -1107,8 +1102,8 @@ hsBool MovingTurnLeft::PreCondition(double time, float elapsed)
{ {
if (fAvMod->GetTurnStrength() > 0) if (fAvMod->GetTurnStrength() > 0)
{ {
if (fHuBrain->fCallbackAction->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) && if (fHuBrain->fWalkingStrategy->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true; return true;
} }
return false; return false;
@ -1118,8 +1113,8 @@ hsBool MovingTurnRight::PreCondition(double time, float elapsed)
{ {
if (fAvMod->GetTurnStrength() < 0) if (fAvMod->GetTurnStrength() < 0)
{ {
if (fHuBrain->fCallbackAction->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) && if (fHuBrain->fWalkingStrategy->IsOnGround() && (fAvMod->ForwardKeyDown() || fAvMod->BackwardKeyDown()) &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
return true; return true;
} }
@ -1128,14 +1123,14 @@ hsBool MovingTurnRight::PreCondition(double time, float elapsed)
void Jump::IStart() void Jump::IStart()
{ {
fHuBrain->fCallbackAction->EnableControlledFlight(true); fHuBrain->fWalkingStrategy->EnableControlledFlight(true);
plHBehavior::IStart(); plHBehavior::IStart();
} }
void Jump::IStop() void Jump::IStop()
{ {
fHuBrain->fCallbackAction->EnableControlledFlight(false); fHuBrain->fWalkingStrategy->EnableControlledFlight(false);
plHBehavior::IStop(); plHBehavior::IStop();
} }
@ -1146,7 +1141,7 @@ hsBool StandingJump::PreCondition(double time, float elapsed)
{ {
if (GetStrength() > 0.f) if (GetStrength() > 0.f)
{ {
if (!fHuBrain->fCallbackAction->IsControlledFlight() || if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd()) fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
{ {
return false; return false;
@ -1158,7 +1153,7 @@ hsBool StandingJump::PreCondition(double time, float elapsed)
if (fAvMod->JumpKeyDown() && if (fAvMod->JumpKeyDown() &&
!fAvMod->ForwardKeyDown() && !fAvMod->ForwardKeyDown() &&
fAnim->GetBlend() == 0.0f && fAnim->GetBlend() == 0.0f &&
fHuBrain->fCallbackAction->IsOnGround()) fHuBrain->fWalkingStrategy->IsOnGround())
{ {
if (fAvMod->ConsumeJump()) if (fAvMod->ConsumeJump())
return true; return true;
@ -1174,7 +1169,7 @@ hsBool WalkingJump::PreCondition(double time, float elapsed)
{ {
if (GetStrength() > 0.f) if (GetStrength() > 0.f)
{ {
if (!fHuBrain->fCallbackAction->IsControlledFlight() || if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd()) fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
{ {
return false; return false;
@ -1187,8 +1182,8 @@ hsBool WalkingJump::PreCondition(double time, float elapsed)
!fAvMod->FastKeyDown() && !fAvMod->FastKeyDown() &&
fAvMod->ForwardKeyDown() && fAvMod->ForwardKeyDown() &&
fAnim->GetBlend() == 0.0f && fAnim->GetBlend() == 0.0f &&
fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
{ {
if (fAvMod->ConsumeJump()) if (fAvMod->ConsumeJump())
return true; return true;
@ -1204,7 +1199,7 @@ hsBool RunningJump::PreCondition(double time, float elapsed)
{ {
if (GetStrength() > 0.f) if (GetStrength() > 0.f)
{ {
if (!fHuBrain->fCallbackAction->IsControlledFlight() || if (!fHuBrain->fWalkingStrategy->IsControlledFlight() ||
fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd()) fAnim->GetTimeConvert()->WorldToAnimTimeNoUpdate(time) >= fAnim->GetTimeConvert()->GetEnd())
{ {
return false; return false;
@ -1217,8 +1212,8 @@ hsBool RunningJump::PreCondition(double time, float elapsed)
fAvMod->ForwardKeyDown() && fAvMod->ForwardKeyDown() &&
fAvMod->FastKeyDown() && fAvMod->FastKeyDown() &&
fAnim->GetBlend() == 0.0f && fAnim->GetBlend() == 0.0f &&
fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fWalkingStrategy->IsOnGround() &&
(!fHuBrain->fCallbackAction->GetPushingPhysical() || !fHuBrain->fCallbackAction->GetFacingPushingPhysical())) (!fHuBrain->fWalkingStrategy->GetPushingPhysical() || !fHuBrain->fWalkingStrategy->GetFacingPushingPhysical()))
{ {
if (fAvMod->ConsumeJump()) if (fAvMod->ConsumeJump())
return true; return true;
@ -1243,13 +1238,13 @@ hsBool RunningImpact::PreCondition(double time, float elapsed)
{ {
if (fDuration > 0.0f) if (fDuration > 0.0f)
fDuration = fDuration - elapsed; fDuration = fDuration - elapsed;
else if (fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->GetImpactTime() > kMinAirTime) else if (fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->GetImpactTime() > kMinAirTime)
{ {
if (fHuBrain->fCallbackAction->GetImpactVelocity().fZ < -kMinImpactVel) if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ < -kMinImpactVel)
{ {
if (fHuBrain->fCallbackAction->GetImpactVelocity().fY < kRunningImpactThresh) if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fY < kRunningImpactThresh)
{ {
fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fCallbackAction->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel))); fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel)));
if (fMaxBlend > 1) if (fMaxBlend > 1)
fMaxBlend = 1; fMaxBlend = 1;
fDuration = 1.0f / fFadeIn; fDuration = 1.0f / fFadeIn;
@ -1273,13 +1268,13 @@ hsBool GroundImpact::PreCondition(double time, float elapsed)
bool result = false; bool result = false;
if (fDuration > 0.0f) if (fDuration > 0.0f)
fDuration = fDuration - elapsed; fDuration = fDuration - elapsed;
else if (fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->GetImpactTime() > kMinAirTime) else if (fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->GetImpactTime() > kMinAirTime)
{ {
if (fHuBrain->fCallbackAction->GetImpactVelocity().fZ < -kMinImpactVel) if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ < -kMinImpactVel)
{ {
if (fHuBrain->fCallbackAction->GetImpactVelocity().fY >= kRunningImpactThresh) if (fHuBrain->fWalkingStrategy->GetImpactVelocity().fY >= kRunningImpactThresh)
{ {
fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fCallbackAction->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel))); fMaxBlend = 0.5f + (0.5f * (-fHuBrain->fWalkingStrategy->GetImpactVelocity().fZ / (kFullImpactVel - kMinImpactVel)));
if (fMaxBlend > 1) if (fMaxBlend > 1)
fMaxBlend = 1; fMaxBlend = 1;
fDuration = 1.0f / fFadeIn; fDuration = 1.0f / fFadeIn;
@ -1298,7 +1293,7 @@ void GroundImpact::IStop()
hsBool Fall::PreCondition(double time, float elapsed) hsBool Fall::PreCondition(double time, float elapsed)
{ {
return !fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fCallbackAction->HitGroundInThisAge(); return !fHuBrain->fWalkingStrategy->IsOnGround() && fHuBrain->fWalkingStrategy->HitGroundInThisAge();
} }
void Fall::Process(double time, float elapsed) void Fall::Process(double time, float elapsed)
@ -1310,7 +1305,7 @@ void Fall::Process(double time, float elapsed)
if (fAnim && fAnim->GetBlend() > 0.8) if (fAnim && fAnim->GetBlend() > 0.8)
{ {
float panicThresh = plAvBrainHuman::kAirTimePanicThreshold; float panicThresh = plAvBrainHuman::kAirTimePanicThreshold;
if (panicThresh > 0.0f && fHuBrain->fCallbackAction->GetAirTime() > panicThresh) if (panicThresh > 0.0f && fHuBrain->fWalkingStrategy->GetAirTime() > panicThresh)
{ {
fHuBrain->IdleOnly(); // clear the fall state; we're going somewhere new fHuBrain->IdleOnly(); // clear the fall state; we're going somewhere new
fAvMod->PanicLink(); fAvMod->PanicLink();
@ -1327,7 +1322,7 @@ void Push::Process(double time, float elapsed)
fAvMod->GetPositionAndRotationSim(&pos, &rot); fAvMod->GetPositionAndRotationSim(&pos, &rot);
hsPoint3 lookAt; hsPoint3 lookAt;
fHuBrain->fCallbackAction->GetPushingPhysical()->GetPositionSim(lookAt); fHuBrain->fWalkingStrategy->GetPushingPhysical()->GetPositionSim(lookAt);
hsVector3 up(0.f, 0.f, 1.f); hsVector3 up(0.f, 0.f, 1.f);
hsScalar angle = hsATan2(lookAt.fY - pos.fY, lookAt.fX - pos.fX) + hsScalarPI / 2; hsScalar angle = hsATan2(lookAt.fY - pos.fY, lookAt.fX - pos.fX) + hsScalarPI / 2;
hsQuat targRot(angle, &up); hsQuat targRot(angle, &up);
@ -1341,23 +1336,23 @@ void Push::Process(double time, float elapsed)
globFwd = rot.Rotate(&globFwd); globFwd = rot.Rotate(&globFwd);
if (globFwd.fX < 0) if (globFwd.fX < 0)
fHuBrain->fCallbackAction->SetTurnStrength(-turnSpeed); fHuBrain->fWalkingStrategy->SetTurnStrength(-turnSpeed);
else else
fHuBrain->fCallbackAction->SetTurnStrength(turnSpeed); fHuBrain->fWalkingStrategy->SetTurnStrength(turnSpeed);
} }
//hsBool PushIdle::PreCondition(double time, float elapsed) //hsBool PushIdle::PreCondition(double time, float elapsed)
//{ //{
// return (fHuBrain->fCallbackAction->GetPushingPhysical() && // return (fHuBrain->fWalkingStrategy->GetPushingPhysical() &&
// fHuBrain->fCallbackAction->IsOnGround() && // fHuBrain->fWalkingStrategy->IsOnGround() &&
// !fAvMod->TurnLeftKeyDown() && !fAvMod->TurnRightKeyDown() // !fAvMod->TurnLeftKeyDown() && !fAvMod->TurnRightKeyDown()
// && fAvMod->GetTurnStrength() == 0); // && fAvMod->GetTurnStrength() == 0);
//} //}
hsBool PushWalk::PreCondition(double time, float elapsed) hsBool PushWalk::PreCondition(double time, float elapsed)
{ {
return (fHuBrain->fCallbackAction->GetPushingPhysical() && fHuBrain->fCallbackAction->GetFacingPushingPhysical() && return (fHuBrain->fWalkingStrategy->GetPushingPhysical() && fHuBrain->fWalkingStrategy->GetFacingPushingPhysical() &&
fHuBrain->fCallbackAction->IsOnGround() && fHuBrain->fWalkingStrategy->IsOnGround() &&
fAvMod->ForwardKeyDown()); fAvMod->ForwardKeyDown());
} }
@ -1372,7 +1367,7 @@ bool PushSimpleMultiStage(plArmatureMod *avatar, const char *enterAnim, const ch
{ {
plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(avatar->FindBrainByClass(plAvBrainHuman::Index())); plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(avatar->FindBrainByClass(plAvBrainHuman::Index()));
const char *names[3] = {enterAnim, idleAnim, exitAnim}; const char *names[3] = {enterAnim, idleAnim, exitAnim};
if (!huBrain || !huBrain->fCallbackAction->IsOnGround() || !huBrain->fCallbackAction->HitGroundInThisAge() || huBrain->IsRunningTask() || if (!huBrain || !huBrain->fWalkingStrategy->IsOnGround() || !huBrain->fWalkingStrategy->HitGroundInThisAge() || huBrain->IsRunningTask() ||
!avatar->IsPhysicsEnabled() || avatar->FindMatchingGenericBrain(names, 3)) !avatar->IsPhysicsEnabled() || avatar->FindMatchingGenericBrain(names, 3))
return false; return false;
@ -1436,7 +1431,7 @@ bool AvatarEmote(plArmatureMod *avatar, const char *emoteName)
if (swimBrain && swimBrain->IsSwimming()) if (swimBrain && swimBrain->IsSwimming())
return false; return false;
if (huBrain && huBrain->fCallbackAction->IsOnGround() && huBrain->fCallbackAction->HitGroundInThisAge() && !huBrain->IsRunningTask() && if (huBrain && huBrain->fWalkingStrategy->IsOnGround() && huBrain->fWalkingStrategy->HitGroundInThisAge() && !huBrain->IsRunningTask() &&
emote && !alreadyActive && avatar->IsPhysicsEnabled()) emote && !alreadyActive && avatar->IsPhysicsEnabled())
{ {
plKey avKey = avatar->GetKey(); plKey avKey = avatar->GetKey();

4
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainHuman.h

@ -58,7 +58,7 @@ class plAGAnimInstance;
class plAvTask; class plAvTask;
class plAvTaskMsg; class plAvTaskMsg;
class plAvBrainHuman; class plAvBrainHuman;
class plWalkingController; class plWalkingStrategy;
class plArmatureUpdateMsg; class plArmatureUpdateMsg;
class plClimbMsg; class plClimbMsg;
class plControlEventMsg; class plControlEventMsg;
@ -164,7 +164,7 @@ public:
static const hsScalar kControlledFlightThreshold; static const hsScalar kControlledFlightThreshold;
static const hsScalar kAirTimeThreshold; static const hsScalar kAirTimeThreshold;
static const hsScalar kAirTimePanicThreshold; static const hsScalar kAirTimePanicThreshold;
plWalkingController* fCallbackAction; plWalkingStrategy* fWalkingStrategy;
protected: protected:
plAGAnim *FindCustomAnim(const char *baseName); plAGAnim *FindCustomAnim(const char *baseName);

13
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.cpp

@ -44,7 +44,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAvBrainHuman.h" #include "plAvBrainHuman.h"
#include "plAvBrain.h" #include "plAvBrain.h"
#include "plAvCallbackAction.h" #include "plPhysicalControllerCore.h"
#include "../plMessage/plRideAnimatedPhysMsg.h" #include "../plMessage/plRideAnimatedPhysMsg.h"
@ -52,20 +52,19 @@ void plAvBrainRideAnimatedPhysical::Activate(plArmatureModBase *avMod)
{ {
plArmatureBrain::Activate(avMod); plArmatureBrain::Activate(avMod);
IInitAnimations(); IInitAnimations();
if (!fCallbackAction) if (!fWalkingStrategy)
{ {
plSceneObject* avObj = fArmature->GetTarget(0); plSceneObject* avObj = fArmature->GetTarget(0);
plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index()))); plAGModifier* agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore* controller = avMod->GetController(); plPhysicalControllerCore* controller = avMod->GetController();
fCallbackAction = TRACKED_NEW plRidingAnimatedPhysicalController(avObj, agMod->GetApplicator(kAGPinTransform), controller); fWalkingStrategy = TRACKED_NEW plDynamicWalkingStrategy(agMod->GetApplicator(kAGPinTransform), controller);
fCallbackAction->ActivateController(); controller->SetMovementStrategy(fWalkingStrategy);
} }
} }
plAvBrainRideAnimatedPhysical::~plAvBrainRideAnimatedPhysical() plAvBrainRideAnimatedPhysical::~plAvBrainRideAnimatedPhysical()
{ {
delete fCallbackAction; delete fWalkingStrategy;
fCallbackAction=nil; fWalkingStrategy = nil;
} }
void plAvBrainRideAnimatedPhysical::Deactivate() void plAvBrainRideAnimatedPhysical::Deactivate()

2
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainRideAnimatedPhysical.h

@ -41,8 +41,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/ *==LICENSE==*/
#include "plAvBrainHuman.h" #include "plAvBrainHuman.h"
class plRidingAnimatedPhysicalController;
class plAvBrainRideAnimatedPhysical : public plAvBrainHuman class plAvBrainRideAnimatedPhysical : public plAvBrainHuman
{ {
public: public:

137
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.cpp

@ -46,10 +46,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
// //
///////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////
//#include <hkmath/vector3.h>
//#include <hkdynamics/entity/rigidbody.h>
#include "plAntiGravAction.h" // descends from Havok class, so must be included first, like havok objects
// singular // singular
#include "plAvBrainSwim.h" #include "plAvBrainSwim.h"
@ -69,7 +65,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "hsTimer.h" #include "hsTimer.h"
#include "plPhysical.h" #include "plPhysical.h"
#include "plPhysicalControllerCore.h" #include "plPhysicalControllerCore.h"
#include "plAvCallbackAction.h"
// other // other
#include "../plPhysical/plCollisionDetector.h" #include "../plPhysical/plCollisionDetector.h"
#include "../plPipeline/plDebugText.h" #include "../plPipeline/plDebugText.h"
@ -180,18 +175,16 @@ public:
static const float timeToMaxTurn = 0.5f; static const float timeToMaxTurn = 0.5f;
static const float incPerSec = maxTurnSpeed / timeToMaxTurn; static const float incPerSec = maxTurnSpeed / timeToMaxTurn;
// hsAssert(0, "fixme physx"); float oldSpeed = fabs(fSwimBrain->fSwimStrategy->GetTurnStrength());
float oldSpeed = fabs(fSwimBrain->fCallbackAction->GetTurnStrength());
float thisInc = elapsed * incPerSec; float thisInc = elapsed * incPerSec;
float newSpeed = __min(oldSpeed + thisInc, maxTurnSpeed); float newSpeed = __min(oldSpeed + thisInc, maxTurnSpeed);
fSwimBrain->fCallbackAction->SetTurnStrength(newSpeed * fAvMod->GetKeyTurnStrength() + fAvMod->GetAnalogTurnStrength()); fSwimBrain->fSwimStrategy->SetTurnStrength(newSpeed * fAvMod->GetKeyTurnStrength() + fAvMod->GetAnalogTurnStrength());
// the turn is actually applied during PhysicsUpdate // the turn is actually applied during PhysicsUpdate
} }
virtual void IStop() virtual void IStop()
{ {
// hsAssert(0, "fixme physx"); if (fSwimBrain->fSwimStrategy)
if (fSwimBrain->fCallbackAction) fSwimBrain->fSwimStrategy->SetTurnStrength(0.0f);
fSwimBrain->fCallbackAction->SetTurnStrength(0.0f);
plSwimBehavior::IStop(); plSwimBehavior::IStop();
} }
}; };
@ -237,7 +230,7 @@ public:
const hsScalar plAvBrainSwim::kMinSwimDepth = 4.0f; const hsScalar plAvBrainSwim::kMinSwimDepth = 4.0f;
plAvBrainSwim::plAvBrainSwim() : plAvBrainSwim::plAvBrainSwim() :
fCallbackAction(nil), fSwimStrategy(nil),
fMode(kWalking), fMode(kWalking),
fSurfaceDistance(0.f) fSurfaceDistance(0.f)
{ {
@ -250,12 +243,9 @@ plAvBrainSwim::plAvBrainSwim() :
plAvBrainSwim::~plAvBrainSwim() plAvBrainSwim::~plAvBrainSwim()
{ {
if(fCallbackAction) delete fSwimStrategy;
{ fSwimStrategy = nil;
IDetachAction();
delete fCallbackAction;
fCallbackAction=nil;
}
fSurfaceProbeMsg->UnRef(); fSurfaceProbeMsg->UnRef();
int i; int i;
@ -273,8 +263,7 @@ hsBool plAvBrainSwim::Apply(double time, hsScalar elapsed)
fMode = kWading; fMode = kWading;
plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(fAvMod->GetNextBrain(this)); plAvBrainHuman *huBrain = plAvBrainHuman::ConvertNoRef(fAvMod->GetNextBrain(this));
// hsAssert(0, "fixme physx"); if (huBrain && !huBrain->fWalkingStrategy->IsOnGround())
if (huBrain && !huBrain->fCallbackAction->IsOnGround())
{ {
// We're jumping in! Trigger splash effect (sound) // We're jumping in! Trigger splash effect (sound)
plArmatureEffectMsg *msg = TRACKED_NEW plArmatureEffectMsg(fAvMod->GetArmatureEffects()->GetKey(), kTime); plArmatureEffectMsg *msg = TRACKED_NEW plArmatureEffectMsg(fAvMod->GetArmatureEffects()->GetKey(), kTime);
@ -318,8 +307,7 @@ hsBool plAvBrainSwim::Apply(double time, hsScalar elapsed)
// The contact check is so that if buoyancy bobs us a little too high, we don't // The contact check is so that if buoyancy bobs us a little too high, we don't
// switch to wading only to fall again. // switch to wading only to fall again.
// hsAssert(0, "fixme physx"); if (fSurfaceDistance < kMinSwimDepth-.5 && fSwimStrategy->HadContacts())
if (fSurfaceDistance < kMinSwimDepth-.5 && fCallbackAction->HadContacts())
IStartWading(); IStartWading();
} }
else if (fMode == kSwimming3D) else if (fMode == kSwimming3D)
@ -346,13 +334,12 @@ hsBool plAvBrainSwim::MsgReceive(plMessage *msg)
else else
fSurfaceDistance = -100.f; fSurfaceDistance = -100.f;
// hsAssert(0, "fixme physx"); if (fSwimStrategy)
if (fCallbackAction)
{ {
if (region) if (region)
fCallbackAction->SetSurface(region, fArmature->GetTarget(0)->GetLocalToWorld().GetTranslate().fZ + fSurfaceDistance); fSwimStrategy->SetSurface(region, fArmature->GetTarget(0)->GetLocalToWorld().GetTranslate().fZ + fSurfaceDistance);
else else
fCallbackAction->SetSurface(nil, 0.f); fSwimStrategy->SetSurface(nil, 0.f);
} }
return true; return true;
} }
@ -419,20 +406,16 @@ void plAvBrainSwim::Activate(plArmatureModBase* avMod)
void plAvBrainSwim::Deactivate() void plAvBrainSwim::Deactivate()
{ {
plArmatureBrain::Deactivate(); plArmatureBrain::Deactivate();
IDetachAction();
} }
void plAvBrainSwim::Suspend() void plAvBrainSwim::Suspend()
{ {
if (fMode == kSwimming2D)
IDetachAction();
} }
void plAvBrainSwim::Resume() void plAvBrainSwim::Resume()
{ {
if (fMode == kSwimming2D) if (fMode == kSwimming2D)
IAttachAction(); fSwimStrategy->Reset(false);
} }
bool plAvBrainSwim::IsWalking() bool plAvBrainSwim::IsWalking()
@ -460,8 +443,6 @@ void plAvBrainSwim::IStartWading()
for (i = 0; i < fBehaviors.GetCount(); i++) for (i = 0; i < fBehaviors.GetCount(); i++)
fBehaviors[i]->SetStrength(0.f, 2.f); fBehaviors[i]->SetStrength(0.f, 2.f);
IDetachAction();
if (fAvMod->IsLocalAvatar()) if (fAvMod->IsLocalAvatar())
{ {
plCameraMsg* pMsg = TRACKED_NEW plCameraMsg; plCameraMsg* pMsg = TRACKED_NEW plCameraMsg;
@ -479,7 +460,16 @@ void plAvBrainSwim::IStartSwimming(bool is2D)
plArmatureBrain *nextBrain = fAvMod->GetNextBrain(this); plArmatureBrain *nextBrain = fAvMod->GetNextBrain(this);
nextBrain->Suspend(); nextBrain->Suspend();
IAttachAction(); if (!fSwimStrategy)
{
plSceneObject * avObj = fArmature->GetTarget(0);
plAGModifier *agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
plPhysicalControllerCore *controller = fAvMod->GetController();
fSwimStrategy = new plSwimStrategy(agMod->GetApplicator(kAGPinTransform), controller);
}
fSwimStrategy->Reset(false);
if (is2D) if (is2D)
fMode = kSwimming2D; fMode = kSwimming2D;
else else
@ -509,8 +499,8 @@ hsBool plAvBrainSwim::IProcessSwimming2D(double time, float elapsed)
else else
behavior->SetStrength(0.f, 2.f); behavior->SetStrength(0.f, 2.f);
} }
// hsAssert(0, "fixme physx");
fCallbackAction->RecalcVelocity(time, time - elapsed); fSwimStrategy->RecalcVelocity(time, elapsed);
return true; return true;
} }
@ -568,59 +558,6 @@ hsBool plAvBrainSwim::IInitAnimations()
return true; return true;
} }
bool plAvBrainSwim::IAttachAction()
{
bool result = false;
if(fAvMod)
{
// hsAssert(0, "fixme physx");
plPhysicalControllerCore *physical = fAvMod->GetController();
if (physical)
{
if (!fCallbackAction)
{
plSceneObject * avObj = fArmature->GetTarget(0);
plAGModifier *agMod = const_cast<plAGModifier*>(plAGModifier::ConvertNoRef(FindModifierByClass(avObj, plAGModifier::Index())));
fCallbackAction = new plSwimmingController(avObj, agMod->GetApplicator(kAGPinTransform),physical);
// physical->AttachAction(fCallbackAction, true, false);
result = true;
}
else
{
fCallbackAction->ActivateController();
}
}
}
return result;
}
bool plAvBrainSwim::IDetachAction()
{
bool result = false;
if (fCallbackAction)
{
// hsAssert(0, "fixme physx");
// plPhysical *physical = fAvMod->GetPhysical();
//
// if(physical)
// {
// physical->RemoveAction(fCallbackAction);
// result = true; // there was an action and we removed it
// }
// TODO: We get a compiler warning about deleting a pointer to an
// undefined class. So, who knows what the code is actually doing.
// Seems bad. Just putting a note in here for whoever fixes the
// physx issue.
//delete fCallbackAction;
//fCallbackAction = nil;
}
return result;
}
void plAvBrainSwim::IProbeSurface() void plAvBrainSwim::IProbeSurface()
{ {
hsPoint3 ourPos = fAvMod->GetTarget(0)->GetLocalToWorld().GetTranslate(); hsPoint3 ourPos = fAvMod->GetTarget(0)->GetLocalToWorld().GetTranslate();
@ -676,21 +613,15 @@ void plAvBrainSwim::DumpToDebugDisplay(int &x, int &y, int lineHeight, char *str
debugTxt.DrawString(x, y, strBuf); debugTxt.DrawString(x, y, strBuf);
y += lineHeight; y += lineHeight;
float buoy = fSwimStrategy ? fSwimStrategy->GetBuoyancy() : 0.0f;
sprintf(strBuf, "Distance to surface: %f Buoyancy: %f", fSurfaceDistance, buoy);
debugTxt.DrawString(x, y, strBuf);
y += lineHeight;
// hsAssert(0, "fixme physx"); hsVector3 linV = fAvMod->GetController()->GetAchievedLinearVelocity();
// float buoy = fCallbackAction? fCallbackAction->GetBuoyancy() : 0.0f; sprintf(strBuf, "Linear Velocity: (%5.2f, %5.2f, %5.2f)", linV.fX, linV.fY, linV.fZ);
// sprintf(strBuf, "Distance to surface: %f Buoyancy: %f", fSurfaceDistance, buoy); debugTxt.DrawString(x, y, strBuf);
// debugTxt.DrawString(x, y, strBuf); y += lineHeight;
// y += lineHeight;
//
// hsVector3 linV;
// fAvMod->GetPhysical()->GetLinearVelocitySim(linV);
// hsVector3 angV;
// fAvMod->GetPhysical()->GetAngularVelocitySim(angV);
// hsScalar angle = angV.fZ > 0 ? angV.Magnitude() : -angV.Magnitude();
// sprintf(strBuf, "Velocity: Linear (%5.2f, %5.2f, %5.2f), Angular %5.2f", linV.fX, linV.fY, linV.fZ, angle);
// debugTxt.DrawString(x, y, strBuf);
// y += lineHeight;
int i; int i;
for (i = 0; i < fBehaviors.GetCount(); i++) for (i = 0; i < fBehaviors.GetCount(); i++)

7
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvBrainSwim.h

@ -47,11 +47,10 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../pnKeyedObject/plKey.h" #include "../pnKeyedObject/plKey.h"
class plArmatureMod; class plArmatureMod;
class plAntiGravAction;
class plControlEventMsg; class plControlEventMsg;
class plLOSRequestMsg; class plLOSRequestMsg;
class plSwimRegionInterface; class plSwimRegionInterface;
class plSwimmingController; class plSwimStrategy;
class plAvBrainSwim : public plArmatureBrain class plAvBrainSwim : public plArmatureBrain
{ {
public: public:
@ -73,7 +72,7 @@ public:
bool IsSwimming(); bool IsSwimming();
hsScalar GetSurfaceDistance() { return fSurfaceDistance; } hsScalar GetSurfaceDistance() { return fSurfaceDistance; }
plSwimmingController *fCallbackAction; plSwimStrategy *fSwimStrategy;
static const hsScalar kMinSwimDepth; static const hsScalar kMinSwimDepth;
protected: protected:
@ -86,8 +85,6 @@ protected:
hsBool IProcessBehaviors(double time, float elapsed); hsBool IProcessBehaviors(double time, float elapsed);
virtual hsBool IInitAnimations(); virtual hsBool IInitAnimations();
bool IAttachAction();
bool IDetachAction();
void IProbeSurface(); void IProbeSurface();
hsBool IHandleControlMsg(plControlEventMsg* msg); hsBool IHandleControlMsg(plControlEventMsg* msg);
float IGetTargetZ(); float IGetTargetZ();

579
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.cpp

@ -1,579 +0,0 @@
/*==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 "plAvCallbackAction.h"
#include "../plMessage/plLOSHitMsg.h"
#include "plArmatureMod.h" // for LOS enum type
#include "plMatrixChannel.h"
#include "hsTimer.h"
#include "plPhysicalControllerCore.h"
// Generic geom utils.
hsBool LinearVelocity(hsVector3 &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
void AngularVelocity(hsScalar &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
float AngleRad2d (float x1, float y1, float x3, float y3);
inline hsVector3 GetYAxis(hsMatrix44 &mat)
{
return hsVector3(mat.fMap[1][0], mat.fMap[1][1], mat.fMap[1][2]);
}
plAnimatedController::plAnimatedController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
: fRootObject(rootObject)
, fRootApp(rootApp)
, fController(controller)
, fTurnStr(0.f)
, fAnimAngVel(0.f)
, fAnimPosVel(0.f, 0.f, 0.f)
{
}
void plAnimatedController::RecalcVelocity(double timeNow, double timePrev, hsBool useAnim /* = true */)
{
if (useAnim)
{
// while you may think it would be correct to cache this,
// what we're actually asking is "what would the animation's
// position be at the previous time given its *current*
// parameters (particularly blends)"
hsMatrix44 prevMat = ((plMatrixChannel *)fRootApp->GetChannel())->Value(timePrev, true);
hsMatrix44 curMat = ((plMatrixChannel *)fRootApp->GetChannel())->Value(timeNow, true);
// If we get a valid linear velocity (ie, we didn't wrap around in the anim),
// use it. Otherwise just reuse the previous frames velocity.
hsVector3 linearVel;
if (LinearVelocity(linearVel, (float)(timeNow - timePrev), prevMat, curMat))
fAnimPosVel = linearVel;
// Automatically sets fAnimAngVel
AngularVelocity(fAnimAngVel, (float)(timeNow - timePrev), prevMat, curMat);
}
else
{
fAnimPosVel.Set(0.f, 0.f, 0.f);
fAnimAngVel = 0.f;
}
if (fController)
fController->SetVelocities(fAnimPosVel, fAnimAngVel + fTurnStr);
}
///////////////////////////////////////////////////////////////////////////
const hsScalar plWalkingController::kControlledFlightThreshold = 1.f; // seconds
plWalkingController::plWalkingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
: plAnimatedController(rootObject, rootApp, controller)
, fHitGroundInThisAge(false)
, fWaitingForGround(false)
, fControlledFlightTime(0)
, fControlledFlight(0)
, fImpactTime(0.f)
, fImpactVelocity(0.f, 0.f, 0.f)
, fClearImpact(false)
, fGroundLastFrame(false)
{
if (fController)
{
fWalkingStrategy= TRACKED_NEW plWalkingStrategy(fController);
fController->SetMovementSimulationInterface(fWalkingStrategy);
}
else
fWalkingStrategy = nil;
}
void plWalkingController::RecalcVelocity(double timeNow, double timePrev, hsBool useAnim)
{
if (!fHitGroundInThisAge && fController && fController->IsEnabled() && fWalkingStrategy->IsOnGround())
fHitGroundInThisAge = true; // if we're not pinned and we're not in an age yet, we are now.
if (fClearImpact)
{
fImpactTime = 0.f;
fImpactVelocity.Set(0.f, 0.f, 0.f);
}
if (fController && !fWalkingStrategy->IsOnGround())
{
// PhysX Hack
// LinearVelocity is always (0,0,0) outside the PhysController
fImpactTime = fWalkingStrategy->GetAirTime();
fImpactVelocity = fController->GetAchievedLinearVelocity();
// convert orientation from subworld to avatar-local coordinates
fImpactVelocity = (hsVector3)fController->GetLocalRotation().Rotate(&fImpactVelocity);
fClearImpact = false;
}
else
fClearImpact = true;
if (IsControlledFlight())
{
if (fWalkingStrategy && fWalkingStrategy->IsOnGround())
fControlledFlightTime = fWalkingStrategy->GetAirTime();
if(fGroundLastFrame&&(fWalkingStrategy && !fWalkingStrategy->IsOnGround()))
{
//we have started to leave the ground tell the movement strategy in case it cares
fWalkingStrategy->StartJump();
}
if (fControlledFlightTime > kControlledFlightThreshold)
EnableControlledFlight(false);
}
if (fWalkingStrategy)
fGroundLastFrame = fWalkingStrategy->IsOnGround();
else
fGroundLastFrame=false;
plAnimatedController::RecalcVelocity(timeNow, timePrev, useAnim);
}
void plWalkingController::Reset(bool newAge)
{
ActivateController();
if (newAge)
{
if (fWalkingStrategy)
fWalkingStrategy->ResetAirTime();
fHitGroundInThisAge = false;
}
}
void plWalkingController::ActivateController()
{
if (fWalkingStrategy)
{
fWalkingStrategy->RefreshConnectionToControllerCore();
}
else
{
fWalkingStrategy= TRACKED_NEW plWalkingStrategy(fController);
fWalkingStrategy->RefreshConnectionToControllerCore();
}
}
bool plWalkingController::EnableControlledFlight(bool status)
{
if (status)
{
if (fControlledFlight == 0)
fControlledFlightTime = 0.f;
++fControlledFlight;
fWaitingForGround = true;
}
else
fControlledFlight = __max(--fControlledFlight, 0);
return status;
}
plWalkingController::~plWalkingController()
{
delete fWalkingStrategy;
if (fController)
fController->SetMovementSimulationInterface(nil);
}
#if 0
void plWalkingController::Update()
{
// double elapsed = time.asDouble() - getRefresh().asDouble();
// setRefresh(time);
//
// hsBool isPhysical = !fPhysical->GetProperty(plSimulationInterface::kPinned);
// const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f);
// hsBool alreadyInAge = fHitGroundInThisAge;
//
// int numContacts = fPhysical->GetNumContacts();
// bool ground = false;
// fPushingPhysical = nil;
// int i, j;
/* for(i = 0; i < numContacts; i++)
{
plHKPhysical *contactPhys = fPhysical->GetContactPhysical(i);
if (!contactPhys)
continue; // Physical no longer exists. Skip it.
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
hsScalar dotUp = straightUp.dot(contact->m_normal);
if (dotUp > .5)
ground = true;
else if (contactPhys->GetProperty(plSimulationInterface::kAvAnimPushable))
{
hsPoint3 position;
hsQuat rotation;
fPhysical->GetPositionAndRotationSim(&position, &rotation);
hsQuat inverseRotation = rotation.Inverse();
hsVector3 normal(contact->m_normal.x, contact->m_normal.y, contact->m_normal.z);
fFacingPushingPhysical = (inverseRotation.Rotate(&kAvatarForward).InnerProduct(normal) < 0 ? true : false);
fPushingPhysical = contactPhys;
}
}
// We need to check for the case where the avatar hasn't collided with "ground", but is colliding
// with a few other objects so that he's not actually falling (wedged in between some slopes).
// We do this by answering the following question (in 2d top-down space): "If you sort the contact
// normals by angle, is there a large enough gap between normals?"
//
// If you think in terms of geometry, this means a collection of surfaces are all pushing on you.
// If they're pushing from all sides, you have nowhere to go, and you won't fall. There needs to be
// a gap, so that you're pushed out and have somewhere to fall. This is the same as finding a gap
// larger than 180 degrees between sorted normals.
//
// The problem is that on top of that, the avatar needs enough force to shove him out that gap (he
// has to overcome friction). I deal with that by making the threshold (360 - (180 - 60) = 240). I've
// seen up to 220 reached in actual gameplay in a situation where we'd want this to take effect.
// This is the same running into 2 walls where the angle between them is 60.
const hsScalar threshold = hsScalarDegToRad(240);
if (!ground && numContacts >= 2)
{
// Can probably do a special case for exactly 2 contacts. Not sure if it's worth it...
fCollisionAngles.SetCount(numContacts);
for (i = 0; i < numContacts; i++)
{
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
fCollisionAngles[i] = hsATan2(contact->m_normal.y, contact->m_normal.x);
}
// numContacts is rarely larger than 6, so let's do a simple bubble sort.
for (i = 0; i < numContacts; i++)
{
for (j = i + 1; j < numContacts; j++)
{
if (fCollisionAngles[i] > fCollisionAngles[j])
{
hsScalar tempAngle = fCollisionAngles[i];
fCollisionAngles[i] = fCollisionAngles[j];
fCollisionAngles[j] = tempAngle;
}
}
}
// sorted, now we check.
for (i = 1; i < numContacts; i++)
{
if (fCollisionAngles[i] - fCollisionAngles[i - 1] >= threshold)
break;
}
if (i == numContacts)
{
// We got to the end. Check the last with the first and make your decision.
if (!(fCollisionAngles[0] - fCollisionAngles[numContacts - 1] >= (threshold - 2 * hsScalarPI)))
ground = true;
}
}
*/
bool ground = fController ? fController->GotGroundHit() : true;
bool isPhysical = true;
if (!fHitGroundInThisAge && isPhysical)
fHitGroundInThisAge = true; // if we're not pinned and we're not in an age yet, we are now.
if (IsControlledFlight())
fControlledFlightTime += (hsScalar)elapsed;
if (fControlledFlightTime > kControlledFlightThreshold && numContacts > 0)
EnableControlledFlight(false);
if (ground || !isPhysical)
{
if (!IsControlledFlight() && !IsOnGround())
{
// The first ground contact in an age doesn't count.
// if (alreadyInAge)
// {
// hsVector3 vel;
// fPhysical->GetLinearVelocitySim(vel);
// fImpactVel = vel.fZ;
// fTimeInAirPeak = (hsScalar)(fTimeInAir + elapsed);
// }
fWaitingForGround = false;
}
fTimeInAir = 0;
}
else if (elapsed < plSimulationMgr::GetInstance()->GetMaxDelta())
{
// If the simultation skipped a huge chunk of time, we didn't process the
// collisions, which could trick us into thinking we've just gone a long
// time without hitting ground. So we only count the time if this wasn't
// the case.
fTimeInAir += (hsScalar)elapsed;
}
// Tweakage so that we still fall under the right conditions.
// If we're in controlled flight, or standing still with ground solidly under us (probe hit). We only use anim velocity.
// if (!IsControlledFlight() && !(ground && fProbeHitGround && fAnimPosVel.fX == 0 && fAnimPosVel.fY == 0))
// {
// hsVector3 curV;
// fPhysical->GetLinearVelocitySim(curV);
// fAnimPosVel.fZ = curV.fZ;
//
// // Prevents us from going airborn from running up bumps/inclines.
// if (IsOnGround() && fAnimPosVel.fZ > 0.f)
// fAnimPosVel.fZ = 0.f;
//
// // Unless we're on the ground and moving, or standing still with a probe hit, we use the sim's other axes too.
// if (!(IsOnGround() && (fProbeHitGround || fAnimPosVel.fX != 0 || fAnimPosVel.fY != 0)))
// {
// fAnimPosVel.fX = curV.fX;
// fAnimPosVel.fY = curV.fY;
// }
// }
//
// fPhysical->SetLinearVelocitySim(fAnimPosVel);
// fPhysical->SetSpin(fAnimAngVel + fTurnStr, hsVector3(0.0f, 0.0f, 1.0f));
}
#endif
#if 0
/////////////////////////////////////////////////////////////////////////
plSimDefs::ActionType plHorizontalFreezeAction::GetType()
{
return plSimDefs::kHorizontalFreeze;
}
void plHorizontalFreezeAction::apply(Havok::Subspace &s, Havok::hkTime time)
{
double elapsed = time.asDouble() - getRefresh().asDouble();
setRefresh(time);
int numContacts = fPhysical->GetNumContacts();
bool ground = false;
const Havok::Vector3 straightUp(0.0f, 0.0f, 1.0f);
int i;
for(i = 0; i < numContacts; i++)
{
const Havok::ContactPoint *contact = fPhysical->GetContactPoint(i);
hsScalar dotUp = straightUp.dot(contact->m_normal);
if (dotUp > .5)
ground = true;
}
hsVector3 vel;
fPhysical->GetLinearVelocitySim(vel);
vel.fX = 0.0;
vel.fY = 0.0;
if (ground)
vel.fZ = 0;
fPhysical->SetLinearVelocitySim(vel);
fPhysical->ClearContacts();
}
#endif
plSwimmingController::plSwimmingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
:plAnimatedController(rootObject,rootApp,controller)
{
if (controller)
fSwimmingStrategy= TRACKED_NEW plSwimStrategy(controller);
else
fSwimmingStrategy = nil;
}
plSwimmingController::~plSwimmingController()
{
delete fSwimmingStrategy;
}
plRidingAnimatedPhysicalController::plRidingAnimatedPhysicalController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller)
: plWalkingController(rootObject, rootApp, controller)
{
if(controller)
fWalkingStrategy = TRACKED_NEW plRidingAnimatedPhysicalStrategy(controller);
else
fWalkingStrategy = nil;
}
plRidingAnimatedPhysicalController::~plRidingAnimatedPhysicalController()
{
delete fWalkingStrategy;
fWalkingStrategy=nil;
}
//////////////////////////////////////////////////////////////////////////
/*
Purpose:
ANGLE_RAD_2D returns the angle in radians swept out between two rays in 2D.
Discussion:
Except for the zero angle case, it should be true that
ANGLE_RAD_2D(X1,Y1,X2,Y2,X3,Y3)
+ ANGLE_RAD_2D(X3,Y3,X2,Y2,X1,Y1) = 2 * PI
Modified:
19 April 1999
Author:
John Burkardt
Parameters:
Input, float X1, Y1, X2, Y2, X3, Y3, define the rays
( X1-X2, Y1-Y2 ) and ( X3-X2, Y3-Y2 ) which in turn define the
angle, counterclockwise from ( X1-X2, Y1-Y2 ).
Output, float ANGLE_RAD_2D, the angle swept out by the rays, measured
in radians. 0 <= ANGLE_DEG_2D < 2 PI. If either ray has zero length,
then ANGLE_RAD_2D is set to 0.
*/
static float AngleRad2d ( float x1, float y1, float x3, float y3 )
{
float value;
float x;
float y;
x = ( x1 ) * ( x3 ) + ( y1 ) * ( y3 );
y = ( x1 ) * ( y3 ) - ( y1 ) * ( x3 );
if ( x == 0.0 && y == 0.0 ) {
value = 0.0;
}
else
{
value = atan2 ( y, x );
if ( value < 0.0 )
{
value = (float)(value + TWO_PI);
}
}
return value;
}
static hsBool LinearVelocity(hsVector3 &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat)
{
bool result = false;
hsPoint3 startPos(0.0f, 0.0f, 0.0f); // default position (at start of anim)
hsPoint3 prevPos = prevMat.GetTranslate(); // position previous frame
hsPoint3 nowPos = curMat.GetTranslate(); // position current frame
hsVector3 prev2Now = (hsVector3)(nowPos - prevPos); // frame-to-frame delta
if (fabs(prev2Now.fX) < 0.0001f && fabs(prev2Now.fY) < 0.0001f && fabs(prev2Now.fZ) < 0.0001f)
{
outputV.Set(0.f, 0.f, 0.f);
result = true;
}
else
{
hsVector3 start2Now = (hsVector3)(nowPos - startPos); // start-to-frame delta
float prev2NowMagSqr = prev2Now.MagnitudeSquared();
float start2NowMagSqr = start2Now.MagnitudeSquared();
float dot = prev2Now.InnerProduct(start2Now);
// HANDLING ANIMATION WRAPPING:
// the vector from the animation origin to the current frame should point in roughly
// the same direction as the vector from the previous animation position to the
// current animation position.
//
// If they don't agree (dot < 0,) then we probably mpst wrapped around.
// The right answer would be to compare the current frame to the start of
// the anim loop, but it's cheaper to cheat and return false,
// telling the caller to use the previous frame's velocity.
if (dot > 0.0f)
{
prev2Now /= elapsed;
float xfabs = fabs(prev2Now.fX);
float yfabs = fabs(prev2Now.fY);
float zfabs = fabs(prev2Now.fZ);
static const float maxVel = 20.0f;
hsBool valid = xfabs < maxVel && yfabs < maxVel && zfabs < maxVel;
if (valid)
{
outputV = prev2Now;
result = true;
}
}
}
return result;
}
static void AngularVelocity(hsScalar &outputV, float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat)
{
outputV = 0.f;
hsScalar appliedVelocity = 0.0f;
hsVector3 prevForward = GetYAxis(prevMat);
hsVector3 curForward = GetYAxis(curMat);
hsScalar angleSincePrev = AngleRad2d(curForward.fX, curForward.fY, prevForward.fX, prevForward.fY);
hsBool sincePrevSign = angleSincePrev > 0.0f;
if (angleSincePrev > hsScalarPI)
angleSincePrev = angleSincePrev - TWO_PI;
const hsVector3 startForward = hsVector3(0, -1.0, 0); // the Y orientation of a "resting" armature....
hsScalar angleSinceStart = AngleRad2d(curForward.fX, curForward.fY, startForward.fX, startForward.fY);
hsBool sinceStartSign = angleSinceStart > 0.0f;
if (angleSinceStart > hsScalarPI)
angleSinceStart = angleSinceStart - TWO_PI;
// HANDLING ANIMATION WRAPPING:
// under normal conditions, the angle from rest to the current frame will have the same
// sign as the angle from the previous frame to the current frame.
// if it does not, we have (most likely) wrapped the motivating animation from frame n back
// to frame zero, creating a large angle from the previous frame to the current one
if (sincePrevSign == sinceStartSign)
{
// signs are the same; didn't wrap; use the frame-to-frame angle difference
appliedVelocity = angleSincePrev / elapsed; // rotation / time
if (fabs(appliedVelocity) < 3)
{
outputV = appliedVelocity;
}
}
}

217
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvCallbackAction.h

@ -1,217 +0,0 @@
/*==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 PL_HK_CALLBACK_ACTION_H
#define PL_HK_CALLBACK_ACTION_H
#include "hsGeometry3.h"
#include "hsMatrix44.h"
#include "hsTemplates.h"
#include "../pnKeyedObject/plKey.h"
#include "../plPhysical/plSimDefs.h"
#include "../pnMessage/plMessage.h"
#include "plPhysicalControllerCore.h"
class plLOSHitMsg;
class plAGApplicator;
class plSceneObject;
class plPhysical;
class plAvatarController;
class plCoordinateInterface;
class plPhysicalControllerCore;
// Used by the other controllers to actually move the avatar. The actual
// implementation is in the physics system.
/*class plPhysicalController
{
public:
// Implemented in the physics system. If you're linking this without that for
// some reason, just stub this function out.
//
// Pass in the key to the root sceneobject for the avatar
static plPhysicalController* Create(plKey ownerSO, hsScalar height, hsScalar width);
virtual ~plPhysicalController() {}
// A disabled avatar doesn't move or accumulate air time if he's off the ground.
virtual void Enable(bool enable) = 0;
virtual bool IsEnabled() const = 0;
// Set the LOS DB this avatar will be in (only one)
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) = 0;
// Call this once per frame with the velocities of the avatar in avatar space.
virtual void SetVelocities(const hsVector3& linearVel, hsScalar angVel) = 0;
// Gets the actual velocity we achieved in the last step (relative to our subworld)
virtual const hsVector3& GetLinearVelocity() const = 0;
virtual void ResetAchievedLinearVelocity() = 0;
// Get and set the current subworld for the avatar. Use nil for the main world.
virtual plKey GetSubworld() const = 0;
virtual void SetSubworld(plKey world) = 0;
// If IsOnGround returns false, GetAirTime will tell you how long the avatar
// has been airborne. Use ResetAirTime to reset the air time to zero, for
// cases like when the avatar spawns into a new age.
virtual bool IsOnGround() const = 0;
virtual bool IsOnFalseGround() const = 0;
virtual hsScalar GetAirTime() const = 0;
virtual void ResetAirTime() = 0;
virtual plPhysical* GetPushingPhysical() const = 0;
virtual bool GetFacingPushingPhysical() const = 0;
// A helper function to get the coordinate interface for the avatars current
// world. Handy if you need to convert points to and from that. This will
// return nil if the avatar is in the main world (ie, you don't need to do
// any translation).
virtual const plCoordinateInterface* GetSubworldCI() const = 0;
// For the avatar SDL only
virtual void GetState(hsPoint3& pos, float& zRot) = 0;
virtual void SetState(const hsPoint3& pos, float zRot) = 0;
// kinematic stuff .... should be just for when playing a behavior...
virtual void Kinematic(bool state) = 0;
virtual bool IsKinematic() = 0;
virtual void GetKinematicPosition(hsPoint3& pos) = 0;
virtual const hsMatrix44& GetPrevSubworldW2L() = 0;
//when seeking no longer want to interact with exclusion regions
virtual void SetSeek(bool seek)=0;
};
*/
class plAvatarController
{
public:
virtual ~plAvatarController() {}
};
class plAnimatedController : public plAvatarController
{
public:
plAnimatedController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual void RecalcVelocity(double timeNow, double timePrev, hsBool useAnim = true);
void SetTurnStrength(hsScalar val) { fTurnStr = val; }
hsScalar GetTurnStrength() { return fTurnStr; }
virtual void ActivateController()=0;
protected:
plSceneObject* fRootObject;
plPhysicalControllerCore* fController;
plAGApplicator* fRootApp;
hsScalar fAnimAngVel;
hsVector3 fAnimPosVel;
hsScalar fTurnStr; // Explicit turning, separate from animations
};
class plWalkingController : public plAnimatedController
{
public:
plWalkingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plWalkingController();
virtual void RecalcVelocity(double timeNow, double timePrev, hsBool useAnim = true);
void Reset(bool newAge);
bool IsControlledFlight() const { return fControlledFlight != 0; }
bool IsOnGround() const { return fWalkingStrategy ? fWalkingStrategy->IsOnGround() : true; }
bool IsOnFalseGround() const { return fWalkingStrategy ? fWalkingStrategy->IsOnFalseGround() : true; }
bool HitGroundInThisAge() const { return fHitGroundInThisAge; }
bool EnableControlledFlight(bool status);
hsScalar GetAirTime() const { return fWalkingStrategy ? fWalkingStrategy->GetAirTime() : 0.f; }
void ResetAirTime() { if (fWalkingStrategy) fWalkingStrategy->ResetAirTime(); }
hsScalar GetForwardVelocity() const;
void ActivateController();
// Check these after the avatar the avatar hits the ground for his total
// hangtime and impact velocity.
hsScalar GetImpactTime() const { return fImpactTime; }
const hsVector3& GetImpactVelocity() const { return fImpactVelocity; }
plPhysical* GetPushingPhysical() const
{
if(fController)return fController->GetPushingPhysical();
else return nil;
}
bool GetFacingPushingPhysical() const
{ if(fController)return fController->GetFacingPushingPhysical();
else return false;
}
protected:
bool fHitGroundInThisAge;
bool fWaitingForGround; // We've gone airborne. IsOnGround() returns false until we hit ground again.
hsScalar fControlledFlightTime;
int fControlledFlight; // Count of how many are currently forcing flight
plWalkingStrategy* fWalkingStrategy;
hsScalar fImpactTime;
hsVector3 fImpactVelocity;
bool fClearImpact;
bool fGroundLastFrame;//used for a test to pass the event of first getting air during a jump
static const hsScalar kControlledFlightThreshold;
};
class plSwimmingController: public plAnimatedController
{
public :
plSwimmingController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plSwimmingController();
void SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight){
fSwimmingStrategy->SetSurface(region,surfaceHeight);
}
hsScalar GetBuoyancy() { return fSwimmingStrategy->GetBuoyancy(); }
hsBool IsOnGround() { return fSwimmingStrategy->IsOnGround(); }
hsBool HadContacts() { return fSwimmingStrategy->HadContacts();}
void Enable(bool en){if (fController) fController->Enable(en);}
plPhysicalControllerCore* GetController(){return fController;}
virtual void ActivateController(){fSwimmingStrategy->RefreshConnectionToControllerCore();}
protected:
plSwimStrategy* fSwimmingStrategy;
};
class plRidingAnimatedPhysicalController: public plWalkingController
{
public:
plRidingAnimatedPhysicalController(plSceneObject* rootObject, plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plRidingAnimatedPhysicalController();
};
#endif // PL_HK_CALLBACK_ACTION_H

4
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvLadderModifier.cpp

@ -39,7 +39,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021 Mead, WA 99021
*==LICENSE==*/ *==LICENSE==*/
#include "../plAvatar/plAvCallbackAction.h" #include "plPhysicalControllerCore.h"
#include "hsTypes.h" #include "hsTypes.h"
@ -129,7 +129,7 @@ bool plAvLadderMod::IIsReadyToClimb()
if (armMod) if (armMod)
{ {
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(armMod->GetCurrentBrain()); plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(armMod->GetCurrentBrain());
if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround()) if (brain && brain->IsMovingForward() && brain->fWalkingStrategy->IsOnGround())
movingForward = true; movingForward = true;
} }

6
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvTaskSeek.cpp

@ -54,7 +54,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAGAnim.h" #include "plAGAnim.h"
#include "plArmatureMod.h" #include "plArmatureMod.h"
#include "plAvatarMgr.h" #include "plAvatarMgr.h"
#include "plAvCallbackAction.h" #include "plPhysicalControllerCore.h"
// other // other
#include "../plMessage/plAvatarMsg.h" #include "../plMessage/plAvatarMsg.h"
@ -462,10 +462,10 @@ hsBool plAvTaskSeek::IFinishPosition(hsPoint3 &newPosition,
{ {
// While warping, we might be hovering just above the ground. Don't want that to // While warping, we might be hovering just above the ground. Don't want that to
// trigger any falling behavior. // trigger any falling behavior.
if(brain&&brain->fCallbackAction) if(brain&&brain->fWalkingStrategy)
{ {
brain->fCallbackAction->ResetAirTime(); brain->fWalkingStrategy->ResetAirTime();
} }
// how far will we translate this frame? // how far will we translate this frame?
float thisDist = kFloatSpeed * elapsed; float thisDist = kFloatSpeed * elapsed;

2
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarSDLModifier.cpp

@ -47,7 +47,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plAvatar/plAvBrainClimb.h" #include "../plAvatar/plAvBrainClimb.h"
#include "../plAvatar/plAvBrainDrive.h" #include "../plAvatar/plAvBrainDrive.h"
#include "../plAvatar/plAnimStage.h" #include "../plAvatar/plAnimStage.h"
#include "../plAvatar/plAvCallbackAction.h" #include "../plAvatar/plPhysicalControllerCore.h"
#include "../pnSceneObject/plSceneObject.h" #include "../pnSceneObject/plSceneObject.h"
#include "../pnMessage/plSDLModifierMsg.h" #include "../pnMessage/plSDLModifierMsg.h"
#include "../plSDL/plSDL.h" #include "../plSDL/plSDL.h"

4
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plAvatarTasks.cpp

@ -53,7 +53,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "plAGAnimInstance.h" #include "plAGAnimInstance.h"
#include "plAGModifier.h" #include "plAGModifier.h"
#include "plMatrixChannel.h" #include "plMatrixChannel.h"
#include "plAvCallbackAction.h" #include "plPhysicalControllerCore.h"
#include "plAvatarMgr.h" #include "plAvatarMgr.h"
// global // global
@ -689,7 +689,7 @@ hsBool plAvOneShotTask::Process(plArmatureMod *avatar, plArmatureBrain *brain, d
if(fEnablePhysicsAtEnd) if(fEnablePhysicsAtEnd)
{ {
#if 0//ndef PLASMA_EXTERNAL_RELEASE #if 0//ndef PLASMA_EXTERNAL_RELEASE
if (!humanBrain || humanBrain->fCallbackAction->HitGroundInThisAge()) if (!humanBrain || humanBrain->fWalkingStrategy->HitGroundInThisAge())
{ {
// For some reason, calling CheckValidPosition at the beginning of // For some reason, calling CheckValidPosition at the beginning of
// an age can cause detectors to incorrectly report collisions. So // an age can cause detectors to incorrectly report collisions. So

1289
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.cpp

File diff suppressed because it is too large Load Diff

418
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plAvatar/plPhysicalControllerCore.h

@ -41,310 +41,286 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/ *==LICENSE==*/
#ifndef PLPHYSICALCONTROLLERCORE_H #ifndef PLPHYSICALCONTROLLERCORE_H
#define PLPHYSICALCONTROLLERCORE_H #define PLPHYSICALCONTROLLERCORE_H
#include "hsGeometry3.h" #include "hsGeometry3.h"
#include "hsMatrix44.h" #include "hsMatrix44.h"
#include "hsQuat.h"
#include "hsTemplates.h" #include "hsTemplates.h"
#include "../pnKeyedObject/plKey.h" #include "../pnKeyedObject/plKey.h"
#include "../plPhysical/plSimDefs.h" #include "../plPhysical/plSimDefs.h"
#include "../pnMessage/plMessage.h" #include <vector>
#include "hsQuat.h"
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
#define kSLOPELIMIT (cosf(hsScalarDegToRad(55.f)))
class plCoordinateInterface; class plCoordinateInterface;
class plPhysical; class plPhysical;
class plPXPhysical; class plMovementStrategy;
class plAGApplicator;
class plSwimRegionInterface; class plSwimRegionInterface;
//Replacement for for plPhysicalController stripped out some walk specific code
//plPhysicalControllerCore needs to have movement strategies registered to it these will then #define kSlopeLimit (cosf(hsScalarDegToRad(55.f)))
//be called by the controller during the simulation steps. The Strategies need to at least have an
// Apply and Update definition. Everything else should be movement specific. I hope to come back and
//and refactor when I have time this in the future.
enum plControllerCollisionFlags enum plControllerCollisionFlags
{ {
kSides = 1, kSides = 1,
kTop = (1 << 1), kTop = (1 << 1),
kBottom=(1<<2), kBottom = (1 << 2)
}; };
class plMovementStrategySimulationInterface struct plControllerSweepRecord
{ {
public:
virtual void Apply(hsScalar delSecs)=0;
virtual void Update(hsScalar delSecs)=0;
//most strategies don't require this. Only the ones that require behavior like a physical or need
//something after the sim step. this used to be taken care of by Update, but this was moved to take care of
//some of the frame lag
virtual void PostStep(hsScalar delSecs){};
virtual void IAddContactNormals(hsVector3& vec){fContactNormals.Append(vec);}
virtual void AddOnTopOfObject(plPhysical* phys){ fOnTopOf.Append(phys);}
virtual void LeaveAge()
{
fContactNormals.SetCount(0);
fOnTopOf.SetCount(0);
}
protected:
hsTArray<hsVector3> fContactNormals;
hsTArray<plPhysical* > fOnTopOf;
};
class plControllerSweepRecord
{
public:
plPhysical *ObjHit; plPhysical *ObjHit;
hsPoint3 locHit;//World space hsPoint3 Point;
hsScalar TimeHit;//Normalized between 0 and 1 hsVector3 Normal;
hsVector3 Norm;
}; };
bool operator<(const plControllerSweepRecord left, const plControllerSweepRecord right);
class plPhysicalControllerCore class plPhysicalControllerCore
{ {
public: public:
virtual ~plPhysicalControllerCore(); plPhysicalControllerCore(plKey ownerSceneObject, hsScalar height, hsScalar radius);
virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults)=0; virtual ~plPhysicalControllerCore() { }
virtual void SetMovementSimulationInterface(plMovementStrategySimulationInterface* strat){fMovementInterface=strat;}
virtual void Apply(hsScalar delSecs); // An ArmatureMod has its own idea about when physics should be enabled/disabled.
virtual void Update(hsScalar delSecs); // Use plArmatureModBase::EnablePhysics() instead.
virtual void PostStep(hsScalar delSecs);
// A disabled avatar doesn't move or accumulate air time if he's off the ground.
virtual void Enable(bool enable) = 0; virtual void Enable(bool enable) = 0;
virtual bool IsEnabled() { return fEnabled; } virtual bool IsEnabled() { return fEnabled; }
// Subworld
virtual plKey GetSubworld() { return fWorldKey; } virtual plKey GetSubworld() { return fWorldKey; }
virtual void SetSubworld(plKey world) = 0; virtual void SetSubworld(plKey world) = 0;
virtual const plCoordinateInterface* GetSubworldCI() const = 0; virtual const plCoordinateInterface* GetSubworldCI();
// For the avatar SDL only // For the avatar SDL only
virtual void GetState(hsPoint3& pos, float& zRot) = 0; virtual void GetState(hsPoint3& pos, float& zRot) = 0;
virtual void SetState(const hsPoint3& pos, float zRot) = 0; virtual void SetState(const hsPoint3& pos, float zRot) = 0;
// kinematic stuff .... should be just for when playing a behavior...
virtual void Kinematic(bool state) = 0; // The LOS DB this avatar is in (only one)
virtual bool IsKinematic() = 0;
virtual void GetKinematicPosition(hsPoint3& pos) = 0;
virtual const hsMatrix44& GetPrevSubworldW2L() = 0;
//when seeking no longer want to interact with exclusion regions
virtual void SetSeek(bool seek){fSeeking=seek;}
virtual bool IsSeeking(){return fSeeking;}
static plPhysicalControllerCore* Create(plKey ownerSO, hsScalar height, hsScalar radius);
virtual plMovementStrategySimulationInterface* GetMovementInterface(){return fMovementInterface;}
plPhysicalControllerCore(plKey ownerSceneObject, hsScalar height, hsScalar radius);
virtual plKey GetOwner(){return fOwner;};
// Set the LOS DB this avatar will be in (only one)
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; } ;
virtual plSimDefs::plLOSDB GetLOSDB() { return fLOSDB; } virtual plSimDefs::plLOSDB GetLOSDB() { return fLOSDB; }
virtual const hsMatrix44& GetLastGlobalLoc()=0; virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; }
virtual void SetKinematicLoc(const hsMatrix44& l2w)=0;
// Movement strategy
virtual void SetMovementStrategy(plMovementStrategy* strategy) = 0;
// Global location
virtual const hsMatrix44& GetLastGlobalLoc() { return fLastGlobalLoc; }
virtual void SetGlobalLoc(const hsMatrix44& l2w) = 0; virtual void SetGlobalLoc(const hsMatrix44& l2w) = 0;
virtual bool IsEnabledChanged(){return fEnableChanged;}
virtual void HandleEnableChanged()=0; // Local sim position
virtual bool IsKinematicChanged(){return fKinematicChanged;}
virtual void GetPositionSim(hsPoint3& pos) = 0; virtual void GetPositionSim(hsPoint3& pos) = 0;
virtual void HandleKinematicChanged()=0;
virtual bool IsKinematicEnableNextUpdate(){return fKinematicEnableNextUpdate;} // Move kinematic controller
virtual void HandleKinematicEnableNextUpdate()=0; virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults) = 0;
virtual void MoveKinematicToController(hsPoint3& pos)=0;
virtual void UpdateControllerAndPhysicalRep()=0; // Set linear velocity on dynamic controller
virtual void CheckAndHandleAnyStateChanges(); virtual void SetLinearVelocitySim(const hsVector3& linearVel) = 0;
virtual void UpdateSubstepNonPhysical();
virtual const hsPoint3& GetLocalPosition()=0; // Sweep the controller path from startPos through endPos
const hsQuat& GetLocalRotation() { return fLocalRotation; } virtual int SweepControllerPath(const hsPoint3& startPos,const hsPoint3& endPos, hsBool vsDynamics, hsBool vsStatics,
virtual void MoveActorToSim(); UInt32& vsSimGroups, std::vector<plControllerSweepRecord>& hits) = 0;
virtual void OverrideAchievedVelocity(hsVector3 newAchievedVel)
{//because of things like superjumps this is needed I'd rather not, but can't help it
fAchievedLinearVelocity=newAchievedVel;
}
// any clean up for the controller should go here // any clean up for the controller should go here
virtual void LeaveAge() = 0; virtual void LeaveAge() = 0;
hsVector3 DisplacementLastStep(){return fDisplacementThisStep;}
hsVector3 MeanVelocityForLastStep() // Local rotation
{ const hsQuat& GetLocalRotation() const { return fLocalRotation; }
hsVector3 vel=fDisplacementThisStep;
return vel/fSimLength;
}
void SendCorrectionMessages();
void IncrementAngle(hsScalar deltaAngle); void IncrementAngle(hsScalar deltaAngle);
void UpdateWorldRelativePos();
virtual void SetLinearVelocity(const hsVector3& linearVel){fLinearVelocity=linearVel;} // Linear velocity
//should actually be a 3 vector but everywhere else it is assumed to be just around Z void SetLinearVelocity(const hsVector3& linearVel) { fLinearVelocity = linearVel; }
virtual void SetAngularVelocity(const hsScalar angvel){ fAngularVelocity=angvel;} const hsVector3& GetLinearVelocity() const { return fLinearVelocity; }
virtual void SetVelocities(const hsVector3& linearVel, hsScalar angVel)
{ // Acheived linear velocity
fLinearVelocity=linearVel; const hsVector3& GetAchievedLinearVelocity() const { return fAchievedLinearVelocity; }
fAngularVelocity=angVel; void OverrideAchievedLinearVelocity(const hsVector3& linearVel) { fAchievedLinearVelocity = linearVel; }
} void ResetAchievedLinearVelocity() { fAchievedLinearVelocity.Set(0.f, 0.f, 0.f); }
virtual const hsVector3& GetLinearVelocity() ; // SceneObject
virtual hsScalar GetAngularVelocity(){return fAngularVelocity;} plKey GetOwner() { return fOwner; }
virtual const hsVector3& GetAchievedLinearVelocity()const {return fAchievedLinearVelocity;}
plPhysical* GetPushingPhysical(); // When seeking no longer want to interact with exclude regions
bool GetFacingPushingPhysical(); void SetSeek(bool seek) { fSeeking = seek; }
virtual void SetPushingPhysical(plPhysical* pl){fPushingPhysical=pl;} bool IsSeeking() const { return fSeeking; }
virtual void SetFacingPushingPhysical(bool ans){fFacingPushingPhysical=ans;}
//To be Used during runtime conversions, say to switch a tall controller to a ball for swimming // Pushing physical
virtual void SetControllerDimensions(hsScalar radius, hsScalar height)=0; plPhysical* GetPushingPhysical() const { return fPushingPhysical; }
virtual hsScalar GetControllerWidth(){return fRadius;} void SetPushingPhysical(plPhysical* phys) { fPushingPhysical = phys; }
virtual hsScalar GetControllerHeight(){return fHeight;} bool GetFacingPushingPhysical() const { return fFacingPushingPhysical; }
virtual void ResetAchievedLinearVelocity() void SetFacingPushingPhysical(bool facing) { fFacingPushingPhysical = facing; }
{
fAchievedLinearVelocity.Set(0.f,0.f,0.f); // Controller dimensions
} hsScalar GetRadius() const { return fRadius; }
virtual int SweepControllerPath(const hsPoint3& startPos,const hsPoint3& endPos, hsBool vsDynamics, hsBool vsStatics, UInt32& vsSimGroups, std::multiset< plControllerSweepRecord >& WhatWasHitOut)=0; hsScalar GetHeight() const { return fHeight; }
//this should only be used to force a move it could place your head into a wall and that would be good
virtual hsScalar GetHeight() {return fHeight;} // Create a new controller instance - Implemented in the physics system
virtual hsScalar GetRadius() {return fRadius;} static plPhysicalControllerCore* Create(plKey ownerSO, hsScalar height, hsScalar radius, bool human);
//Wether the avatar thing has mass and forces things down or not, and changes the way things move
//This is an attempt fix things like riding on an animated physical
virtual void BehaveLikeAnimatedPhysical(hsBool actLikeAnAnimatedPhys)=0;
virtual hsBool BehavingLikeAnAnimatedPhysical()=0;
protected: protected:
virtual void IHandleEnableChanged() = 0;
void IApply(hsScalar delSecs);
void IUpdate(int numSubSteps, hsScalar alpha);
void IUpdateNonPhysical(hsScalar alpha);
void ISendCorrectionMessages(bool dirtySynch = false);
plKey fOwner; plKey fOwner;
plKey fWorldKey;
hsScalar fHeight; hsScalar fHeight;
hsScalar fRadius; hsScalar fRadius;
plKey fWorldKey;
plSimDefs::plLOSDB fLOSDB; plSimDefs::plLOSDB fLOSDB;
bool fSeeking;
bool fEnabled; plMovementStrategy* fMovementStrategy;
bool fEnableChanged;
bool fKinematic; hsScalar fSimLength;
bool fKinematicEnableNextUpdate;
bool fKinematicChanged;
plMovementStrategySimulationInterface* fMovementInterface;
hsMatrix44 fLastGlobalLoc;
hsPoint3 fLocalPosition;
hsQuat fLocalRotation; hsQuat fLocalRotation;
hsPoint3 fLocalPosition;
hsPoint3 fLastLocalPosition;
hsMatrix44 fLastGlobalLoc;
hsMatrix44 fPrevSubworldW2L; hsMatrix44 fPrevSubworldW2L;
hsVector3 fDisplacementThisStep;
hsScalar fSimLength;
//physical properties
hsVector3 fLinearVelocity; hsVector3 fLinearVelocity;
hsScalar fAngularVelocity;
hsVector3 fAchievedLinearVelocity; hsVector3 fAchievedLinearVelocity;
plPhysical* fPushingPhysical; plPhysical* fPushingPhysical;
bool fFacingPushingPhysical; bool fFacingPushingPhysical;
bool fNeedsResize;
bool fSeeking;
bool fEnabled;
bool fEnableChanged;
}; };
class plMovementStrategy: public plMovementStrategySimulationInterface class plMovementStrategy
{ {
public: public:
virtual void SetControllerCore(plPhysicalControllerCore* core) plMovementStrategy(plPhysicalControllerCore* controller);
{ virtual ~plMovementStrategy() { }
fCore=core;
fCore->SetMovementSimulationInterface(this);
}
virtual void RefreshConnectionToControllerCore()
{
fCore->SetMovementSimulationInterface(this);
//fCore->SetControllerDimensions(fPreferedControllerWidth,fPreferedControllerHeight);
fCore->BehaveLikeAnimatedPhysical(this->IRequireBehaviourLikeAnAnimatedPhysical());
}
plMovementStrategy(plPhysicalControllerCore* core);
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
virtual void SetLinearAcceleration(const hsVector3& accel){fLinearAcceleration=accel;}
virtual const hsVector3& GetLinearAcceleration()const{return fLinearAcceleration;}
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
virtual void ResetAchievedLinearVelocity()
{
hsVector3 AchievedLinearVelocity(0.f,0.f,0.f);
if(fCore)fCore->OverrideAchievedVelocity(AchievedLinearVelocity);
}
//proxy functions for Controller Core
virtual hsScalar GetAirTime() const { return fTimeInAir; }
virtual void ResetAirTime() { fTimeInAir = 0.f; }
protected: virtual void Apply(hsScalar delSecs) = 0;
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical()=0; virtual void Update(hsScalar delSecs) { }
virtual void IApplyKinematic();
plPhysicalControllerCore* fCore;
hsVector3 fLinearAcceleration;
hsScalar fAngularAcceleration;
plKey fOwner;
static const hsScalar kAirTimeThreshold;
hsScalar fTimeInAir;
hsScalar fPreferedControllerWidth;
hsScalar fPreferedControllerHeight;
virtual void AddContactNormals(hsVector3& vec) { }
virtual void Reset(bool newAge);
virtual bool IsKinematic() { return true; }
protected:
plPhysicalControllerCore* fController;
}; };
class plWalkingStrategy: public plMovementStrategy class plAnimatedMovementStrategy : public plMovementStrategy
{ {
public: public:
plWalkingStrategy(plPhysicalControllerCore* core):plMovementStrategy(core) plAnimatedMovementStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plAnimatedMovementStrategy() { }
virtual void RecalcVelocity(double timeNow, hsScalar elapsed, hsBool useAnim = true);
void SetTurnStrength(hsScalar val) { fTurnStr = val; }
hsScalar GetTurnStrength() const { return fTurnStr; }
private:
void IRecalcLinearVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
void IRecalcAngularVelocity(float elapsed, hsMatrix44 &prevMat, hsMatrix44 &curMat);
plAGApplicator* fRootApp;
hsVector3 fAnimLinearVel;
hsScalar fAnimAngularVel;
hsScalar fTurnStr;
};
class plWalkingStrategy : public plAnimatedMovementStrategy
{ {
fGroundHit=false; public:
fFalseGround=false; plWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
fHitHead=false; virtual ~plWalkingStrategy() { }
fCore->SetMovementSimulationInterface(this);
fPreferedControllerWidth=core->GetControllerWidth();
fPreferedControllerHeight=core->GetControllerHeight();
fOnTopOfAnimatedPhysLastFrame=false;
}
virtual ~plWalkingStrategy(){};
virtual void Apply(hsScalar delSecs); virtual void Apply(hsScalar delSecs);
virtual void Update(hsScalar delSecs); virtual void Update(hsScalar delSecs);
virtual void AddContactNormals(hsVector3& vec);
virtual void Reset(bool newAge);
virtual void RecalcVelocity(double timeNow, hsScalar elapsed, hsBool useAnim = true);
bool HitGroundInThisAge() const { return fHitGroundInThisAge; }
bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; } bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
void GroundHit() { fGroundHit = true; }
virtual void IAddContactNormals(hsVector3& vec);
virtual void StartJump(){};
hsScalar GetAirTime() const { return fTimeInAir; }
void ResetAirTime() { fTimeInAir = 0.0f; }
hsScalar GetImpactTime() const { return fImpactTime; }
const hsVector3& GetImpactVelocity() const { return fImpactVelocity; }
bool EnableControlledFlight(bool status);
bool IsControlledFlight() const { return fControlledFlight != 0; }
plPhysical* GetPushingPhysical() const;
bool GetFacingPushingPhysical() const;
protected: protected:
static const hsScalar kAirTimeThreshold;
static const hsScalar kControlledFlightThreshold;
hsTArray<hsVector3> fSlidingNormals;
hsVector3 fImpactVelocity;
hsScalar fImpactTime;
hsScalar fTimeInAir;
hsScalar fControlledFlightTime;
int fControlledFlight;
void ICheckForFalseGround();
bool fGroundHit; bool fGroundHit;
bool fFalseGround; bool fFalseGround;
bool fHitHead; bool fHeadHit;
bool fOnTopOfAnimatedPhysLastFrame; bool fSliding;
hsTArray<hsVector3> fPrevSlidingNormals;
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
bool fClearImpact;
bool fHitGroundInThisAge;
}; };
class plSwimStrategy: public plMovementStrategy
class plSwimStrategy : public plAnimatedMovementStrategy
{ {
public: public:
plSwimStrategy(plPhysicalControllerCore *core); plSwimStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
virtual ~plSwimStrategy(){}; virtual ~plSwimStrategy() { }
void SetSurface(plSwimRegionInterface *region, hsScalar surfaceHeight);
virtual void Apply(hsScalar delSecs); virtual void Apply(hsScalar delSecs);
virtual void Update(hsScalar delSecs);
hsScalar GetBuoyancy() { return fBuoyancy; } virtual void AddContactNormals(hsVector3& vec);
hsBool IsOnGround() { return fOnGround; }
hsBool HadContacts() { return fHadContacts; } void SetSurface(plSwimRegionInterface* region, hsScalar surfaceHeight);
virtual void IAddContactNormals(hsVector3& vec);
hsScalar GetBuoyancy() const { return fBuoyancy; }
bool IsOnGround() const { return fOnGround; }
bool HadContacts() const { return fHadContacts; }
protected: protected:
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return true;}
private:
void IAdjustBuoyancy(); void IAdjustBuoyancy();
hsScalar fBuoyancy; hsScalar fBuoyancy;
hsBool fOnGround;
hsBool fHadContacts;
hsScalar fSurfaceHeight; hsScalar fSurfaceHeight;
plSwimRegionInterface *fCurrentRegion; plSwimRegionInterface *fCurrentRegion;
bool fOnGround;
bool fHadContacts;
}; };
class plRidingAnimatedPhysicalStrategy : public plWalkingStrategy
class plDynamicWalkingStrategy : public plWalkingStrategy
{ {
public: public:
plRidingAnimatedPhysicalStrategy(plPhysicalControllerCore *core ) : plDynamicWalkingStrategy(plAGApplicator* rootApp, plPhysicalControllerCore* controller);
fNeedVelocityOverride(false),fStartJump(false),plWalkingStrategy(core){}; virtual ~plDynamicWalkingStrategy() { }
virtual ~plRidingAnimatedPhysicalStrategy(){};
virtual void Apply(hsScalar delSecs); virtual void Apply(hsScalar delSecs);
virtual void Update(hsScalar delSecs);
virtual void PostStep(hsScalar delSecs); virtual bool IsKinematic() { return false; }
bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
void GroundHit() { fGroundHit = true; }
virtual void StartJump(){fStartJump = true;}
protected: protected:
virtual hsBool IRequireBehaviourLikeAnAnimatedPhysical(){return false;} bool ICheckForGround(hsScalar& zVelocity);
bool ICheckMove(const hsPoint3& startPos, const hsPoint3& desiredPos);
hsBool fNeedVelocityOverride;
hsVector3 fOverrideVelocity;
bool fStartJump;
}; };
#endif// PLPHYSICALCONTROLLERCORE_H #endif// PLPHYSICALCONTROLLERCORE_H

2
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plInputCore/plSceneInputInterface.cpp

@ -73,7 +73,7 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plAvatar/plArmatureMod.h" #include "../plAvatar/plArmatureMod.h"
#include "../plAvatar/plAvBrain.h" #include "../plAvatar/plAvBrain.h"
#include "../plAvatar/plAvatarMgr.h" #include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plAvCallbackAction.h" #include "../plAvatar/plPhysicalControllerCore.h"
#include "../plModifier/plInterfaceInfoModifier.h" #include "../plModifier/plInterfaceInfoModifier.h"
#include "../pnModifier/plLogicModBase.h" #include "../pnModifier/plLogicModBase.h"
#include "../plVault/plVault.h" #include "../plVault/plVault.h"

1
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plModifier/plExcludeRegionModifier.cpp

@ -54,7 +54,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plMessage/plAvatarMsg.h" #include "../plMessage/plAvatarMsg.h"
#include "plPhysical.h" #include "plPhysical.h"
#include "../plPhysical/plSimDefs.h" #include "../plPhysical/plSimDefs.h"
#include "../plAvatar/plAvCallbackAction.h"
#include "../plAvatar/plAvBrainGeneric.h" #include "../plAvatar/plAvBrainGeneric.h"

3
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plLOSDispatch.cpp

@ -94,8 +94,7 @@ private:
} }
else else
{ {
bool isController; plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(hitActor);
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(hitActor,&isController);
if (controller) if (controller)
{ {
objKey = controller->GetOwner(); objKey = controller->GetOwner();

1279
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysicalController.cpp

File diff suppressed because it is too large Load Diff

211
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysicalController.h

@ -1,211 +0,0 @@
/*==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 plPXPhysicalController_h_inc
#define plPXPhysicalController_h_inc
#include "../plAvatar/plAvCallbackAction.h"
#include "hsQuat.h"
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
class NxController;
class NxCapsuleController;
class NxActor;
class plCoordinateInterface;
class plPhysicalProxy;
class plDrawableSpans;
class hsGMaterial;
class NxCapsule;
#ifndef PLASMA_EXTERNAL_RELEASE
class plDbgCollisionInfo
{
public:
plSceneObject *fSO;
hsVector3 fNormal;
hsBool fOverlap;
};
#endif // PLASMA_EXTERNAL_RELEASE
class plPXPhysicalController : public plPhysicalController
{
public:
plPXPhysicalController(plKey ownerSO, hsScalar height, hsScalar radius);
virtual ~plPXPhysicalController();
virtual void Enable(bool enable);
virtual bool IsEnabled() const { return fEnable; }
virtual void SetLOSDB(plSimDefs::plLOSDB losDB) { fLOSDB = losDB; }
plSimDefs::plLOSDB GetLOSDB() const { return fLOSDB; }
virtual void SetVelocities(const hsVector3& linearVel, hsScalar angVel)
{
fLinearVelocity = linearVel;
fAngularVelocity = angVel;
}
virtual const hsVector3& GetLinearVelocity() const { return fAchievedLinearVelocity; }
virtual void ResetAchievedLinearVelocity() { fAchievedLinearVelocity.Set(0.f, 0.f, 0.f); }
virtual plKey GetSubworld() const { return fWorldKey; }
virtual void SetSubworld(plKey world);
virtual bool IsOnGround() const { return fTimeInAir < kAirTimeThreshold || fFalseGround; }
virtual bool IsOnFalseGround() const { return fFalseGround && !fGroundHit; }
virtual void GroundHit() { fGroundHit = true; }
virtual hsScalar GetAirTime() const { return fTimeInAir; }
virtual void ResetAirTime() { fTimeInAir = 0.f; }
virtual void AddSlidingNormal(hsVector3 vec);
virtual hsTArray<hsVector3>* GetSlidingNormals() { return &fSlidingNormals; }
virtual plPhysical* GetPushingPhysical() const { return fPushingPhysical; }
virtual bool GetFacingPushingPhysical() const { return fFacingPushingPhysical; }
virtual const plCoordinateInterface* GetSubworldCI() const;
virtual void GetState(hsPoint3& pos, float& zRot);
virtual void SetState(const hsPoint3& pos, float zRot);
plKey GetOwner() const { return fOwner; }
// Called by the simulation mgr each frame
static void Update(bool prestep, hsScalar delSecs);
// Used by the LOS mgr to find the controller for an actor it hit
static plPXPhysicalController* GetController(NxActor& actor, bool* isController);
// test to see if there are any controllers (i.e. avatars) in this subworld
static bool plPXPhysicalController::AnyControllersInThisWorld(plKey world);
static int plPXPhysicalController::NumControllers();
static int plPXPhysicalController::GetControllersInThisSubWorld(plKey world, int maxToReturn,
plPXPhysicalController** bufferout);
static int plPXPhysicalController::GetNumberOfControllersInThisSubWorld(plKey world);
// Call this if a static physical in the scene has changed (unloaded,
// collision enabled/disabled, etc)
static void RebuildCache();
virtual void GetPositionSim(hsPoint3& pos) const { IGetPositionSim(pos); }
virtual void Kinematic(bool state);
virtual bool IsKinematic();
virtual void GetKinematicPosition(hsPoint3& pos);
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
virtual const hsMatrix44& GetPrevSubworldW2L() { return fPrevSubworldW2L; }
virtual void SetSeek(bool seek){fSeeking=seek;}
virtual void GetWorldSpaceCapsule(NxCapsule& cap);
#ifndef PLASMA_EXTERNAL_RELEASE
static hsBool fDebugDisplay;
#endif // PLASMA_EXTERNAL_RELEASE
protected:
static const hsScalar kAirTimeThreshold;
friend class PXControllerHitReport;
static plPXPhysicalController* FindController(NxController* controller);
void IApply(hsScalar delSecs);
void ISendUpdates(hsScalar delSecs);
void ICheckForFalseGround();
void ISetGlobalLoc(const hsMatrix44& l2w);
void IMatchKinematicToController();
void IMoveKinematicToController(hsPoint3& pos);
void ISetKinematicLoc(const hsMatrix44& l2w);
void IGetPositionSim(hsPoint3& pos) const;
void ICreateController();
void IDeleteController();
void IInformDetectors(bool entering);
plKey fOwner;
plKey fWorldKey;
hsScalar fRadius, fHeight;
NxCapsuleController* fController;
// this is the kinematic actor for triggering things when the avatar is collision-less during behaviors
NxActor* fKinematicActor;
hsVector3 fLinearVelocity;
hsScalar fAngularVelocity;
hsVector3 fAchievedLinearVelocity;
// The global position and rotation of the avatar last time we set it (so we
// can detect if someone else moves him)
hsMatrix44 fLastGlobalLoc;
//
hsPoint3 fLocalPosition;
hsQuat fLocalRotation;
hsMatrix44 fPrevSubworldW2L;
bool fEnable;
bool fEnableChanged;
plSimDefs::plLOSDB fLOSDB;
bool fKinematic;
bool fKinematicChanged;
bool fKinematicEnableNextUpdate;
bool fGroundHit;
bool fFalseGround;
hsScalar fTimeInAir;
hsTArray<hsVector3> fSlidingNormals;
hsTArray<hsVector3> fPrevSlidingNormals;
#ifndef PLASMA_EXTERNAL_RELEASE
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
void IDrawDebugDisplay();
#endif // PLASMA_EXTERNAL_RELEASE
plPhysical* fPushingPhysical;
bool fFacingPushingPhysical;
plPhysicalProxy* fProxyGen; // visual proxy for debugging
bool fHitHead;
bool fSeeking;
};
#endif // plPXPhysicalController_h_inc

1447
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysicalControllerCore.cpp

File diff suppressed because it is too large Load Diff

158
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plPXPhysicalControllerCore.h

@ -40,22 +40,19 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
*==LICENSE==*/ *==LICENSE==*/
#include "../plAvatar/plPhysicalControllerCore.h" #include "../plAvatar/plPhysicalControllerCore.h"
#include "hsQuat.h"
#define PHYSX_ONLY_TRIGGER_FROM_KINEMATIC 1
class NxController;
class NxCapsuleController; class NxCapsuleController;
class NxActor; class NxActor;
class plCoordinateInterface; class NxCapsule;
class PXControllerHitReport;
class plPhysicalProxy; class plPhysicalProxy;
class plDrawableSpans; class plDrawableSpans;
class hsGMaterial; class hsGMaterial;
class NxCapsule;
class plSceneObject; class plSceneObject;
class PXControllerHitReportWalk; class plPXPhysical;
class plCollideMsg; class plCollideMsg;
#ifndef PLASMA_EXTERNAL_RELEASE
#ifndef PLASMA_EXTERNAL_RELEASE
class plDbgCollisionInfo class plDbgCollisionInfo
{ {
public: public:
@ -64,98 +61,113 @@ public:
hsBool fOverlap; hsBool fOverlap;
}; };
#endif // PLASMA_EXTERNAL_RELEASE #endif // PLASMA_EXTERNAL_RELEASE
class plPXPhysicalControllerCore: public plPhysicalControllerCore class plPXPhysicalControllerCore: public plPhysicalControllerCore
{ {
friend PXControllerHitReportWalk;
public: public:
plPXPhysicalControllerCore(plKey ownerSO, hsScalar height, hsScalar radius); plPXPhysicalControllerCore(plKey ownerSO, hsScalar height, hsScalar radius, bool human);
~plPXPhysicalControllerCore(); ~plPXPhysicalControllerCore();
//should actually be a 3 vector but everywhere else it is assumed to be just around Z
inline virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults); // An ArmatureMod has its own idea about when physics should be enabled/disabled.
// A disabled avatar doesn't move or accumulate air time if he's off the ground. // Use plArmatureModBase::EnablePhysics() instead.
virtual void Enable(bool enable); virtual void Enable(bool enable);
// Subworld
virtual void SetSubworld(plKey world); virtual void SetSubworld(plKey world);
virtual const plCoordinateInterface* GetSubworldCI() const ;
// For the avatar SDL only // For the avatar SDL only
virtual void GetState(hsPoint3& pos, float& zRot); virtual void GetState(hsPoint3& pos, float& zRot);
virtual void SetState(const hsPoint3& pos, float zRot); virtual void SetState(const hsPoint3& pos, float zRot);
// kinematic stuff .... should be just for when playing a behavior...
virtual void Kinematic(bool state); // Movement strategy
virtual bool IsKinematic(); virtual void SetMovementStrategy(plMovementStrategy* strategy);
virtual void GetKinematicPosition(hsPoint3& pos);
virtual const hsMatrix44& GetPrevSubworldW2L(){ return fPrevSubworldW2L; } // Global location
//when seeking no longer want to interact with exclusion regions virtual void SetGlobalLoc(const hsMatrix44& l2w);
virtual void GetWorldSpaceCapsule(NxCapsule& cap) const;
static void RebuildCache(); // Local Sim Position
virtual const hsMatrix44& GetLastGlobalLoc(){return fLastGlobalLoc;} virtual void GetPositionSim(hsPoint3& pos);
virtual void SetKinematicLoc(const hsMatrix44& l2w){ISetKinematicLoc(l2w);}
virtual void SetGlobalLoc(const hsMatrix44& l2w){ISetGlobalLoc(l2w);} // Move kinematic controller
virtual void HandleEnableChanged(); virtual void Move(hsVector3 displacement, unsigned int collideWith, unsigned int &collisionResults);
virtual void HandleKinematicChanged();
virtual void HandleKinematicEnableNextUpdate(); // Set linear velocity on dynamic controller
virtual void GetPositionSim(hsPoint3& pos){IGetPositionSim(pos);} virtual void SetLinearVelocitySim(const hsVector3& linearVel);
virtual void MoveKinematicToController(hsPoint3& pos);
virtual const hsPoint3& GetLocalPosition(){return fLocalPosition;} // Sweep the controller path from startPos through endPos
virtual void SetControllerDimensions(hsScalar radius, hsScalar height); virtual int SweepControllerPath(const hsPoint3& startPos, const hsPoint3& endPos, hsBool vsDynamics,
hsBool vsStatics, UInt32& vsSimGroups, std::vector<plControllerSweepRecord>& hits);
// any clean up for the controller should go here
virtual void LeaveAge(); virtual void LeaveAge();
virtual void UpdateControllerAndPhysicalRep();
// Capsule
void GetWorldSpaceCapsule(NxCapsule& cap) const;
// Create Proxy for debug rendering
plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
// Dynamic hits
void AddDynamicHit(plPXPhysical* phys);
////////////////////////////////////////// //////////////////////////////////////////
//Static Helper Functions //Static Helper Functions
//////////////////////////////////////// ////////////////////////////////////////
// Used by the LOS mgr to find the controller for an actor it hit
static plPXPhysicalControllerCore* GetController(NxActor& actor, bool* isController); // Call pre-sim to apply movement to controllers
// test to see if there are any controllers (i.e. avatars) in this subworld static void Apply(hsScalar delSecs);
// Call post-sim to update controllers
static void Update(int numSubSteps, hsScalar alpha);
// Update controllers when not performing a physics step
static void UpdateNonPhysical(hsScalar alpha);
// Rebuild the controller cache, required when a static actor in the scene has changed.
static void RebuildCache();
// Returns the plPXPhysicalControllerCore associated with the given NxActor
static plPXPhysicalControllerCore* GetController(NxActor& actor);
// Subworld controller queries
static bool AnyControllersInThisWorld(plKey world); static bool AnyControllersInThisWorld(plKey world);
static int NumControllers();
static int GetControllersInThisSubWorld(plKey world, int maxToReturn,
plPXPhysicalControllerCore** bufferout);
static int GetNumberOfControllersInThisSubWorld(plKey world); static int GetNumberOfControllersInThisSubWorld(plKey world);
static void UpdatePrestep(hsScalar delSecs); static int GetControllersInThisSubWorld(plKey world, int maxToReturn, plPXPhysicalControllerCore** bufferout);
static void UpdatePoststep(hsScalar delSecs);
static void UpdatePostSimStep(hsScalar delSecs); // Controller count
virtual plDrawableSpans* CreateProxy(hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo); static int NumControllers();
#ifndef PLASMA_EXTERNAL_RELEASE static void SetMaxNumberOfControllers(int max) { fPXControllersMax = max; }
static hsBool fDebugDisplay;
#endif // PLASMA_EXTERNAL_RELEASE
static void plPXPhysicalControllerCore::SetMaxNumberOfControllers(int max) { fPXControllersMax = max; }
static int fPXControllersMax; static int fPXControllersMax;
virtual int SweepControllerPath(const hsPoint3& startPos, const hsPoint3& endPos, hsBool vsDynamics, hsBool vsStatics, UInt32& vsSimGroups, std::multiset< plControllerSweepRecord >& WhatWasHitOut);
virtual void BehaveLikeAnimatedPhysical(hsBool actLikeAnAnimatedPhys);
virtual hsBool BehavingLikeAnAnimatedPhysical();
virtual const hsVector3& GetLinearVelocity();
virtual void SetLinearVelocity(const hsVector3& linearVel); #ifndef PLASMA_EXTERNAL_RELEASE
//should actually be a 3 vector but everywhere else it is assumed to be just around Z static hsBool fDebugDisplay;
virtual void SetAngularVelocity(const hsScalar angvel); #endif
virtual void SetVelocities(const hsVector3& linearVel, hsScalar angVel);
protected: protected:
friend class PXControllerHitReport; friend class PXControllerHitReport;
static plPXPhysicalControllerCore* FindController(NxController* controller);
void ISetGlobalLoc(const hsMatrix44& l2w); virtual void IHandleEnableChanged();
void IMatchKinematicToController();
void IMatchControllerToKinematic(); void IInformDetectors(bool entering);
void ISetKinematicLoc(const hsMatrix44& l2w);
void IGetPositionSim(hsPoint3& pos) const; void ICreateController(const hsPoint3& pos);
void ICreateController();
void IDeleteController(); void IDeleteController();
void IInformDetectors(bool entering,bool deferUntilNextSim);
void plPXPhysicalControllerCore::ICreateController(const hsPoint3& pos); void IDispatchQueuedMsgs();
NxActor* fKinematicActor; void IProcessDynamicHits();
NxCapsuleController* fController;
#ifndef PLASMA_EXTERNAL_RELEASE #ifndef PLASMA_EXTERNAL_RELEASE
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
void IDrawDebugDisplay(); void IDrawDebugDisplay();
hsTArray<plDbgCollisionInfo> fDbgCollisionInfo;
#endif #endif
void plPXPhysicalControllerCore::IHandleResize();
hsTArray<plCollideMsg*> fQueuedCollideMsgs; std::vector<plCollideMsg*> fQueuedCollideMsgs;
hsScalar fPreferedRadius; std::vector<plPXPhysical*> fDynamicHits;
hsScalar fPreferedHeight;
// The global position and rotation of the avatar last time we set it (so we NxCapsuleController* fController;
// can detect if someone else moves him) NxActor* fActor;
plPhysicalProxy* fProxyGen; plPhysicalProxy* fProxyGen;
hsBool fBehavingLikeAnimatedPhys; bool fKinematicCCT;
bool fHuman;
}; };

113
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.cpp

@ -67,80 +67,26 @@ class SensorReport : public NxUserTriggerReport
{ {
virtual void onTrigger(NxShape& triggerShape, NxShape& otherShape, NxTriggerFlag status) virtual void onTrigger(NxShape& triggerShape, NxShape& otherShape, NxTriggerFlag status)
{ {
// Get our trigger physical. This should definitely have a plPXPhysical
plPXPhysical* triggerPhys = (plPXPhysical*)triggerShape.getActor().userData;
hsBool doReport = false;
// Get the triggerer. This may be an avatar, which doesn't have a
// plPXPhysical, so we have to extract the necessary info.
plKey otherKey = nil; plKey otherKey = nil;
hsPoint3 otherPos = plPXConvert::Point(otherShape.getGlobalPosition()); hsBool doReport = false;
if (plSimulationMgr::fExtraProfile) // Get our trigger physical. This should definitely have a plPXPhysical
DetectorLogRed("-->%s %s (status=%x) other@(%f,%f,%f)",triggerPhys->GetObjectKey()->GetName(),status & NX_TRIGGER_ON_ENTER ? "enter" : "exit",status,otherPos.fX,otherPos.fY,otherPos.fZ); plPXPhysical* triggerPhys = (plPXPhysical*)triggerShape.getActor().userData;
// Get the triggerer. If it doesn't have a plPXPhyscial, it's an avatar
plPXPhysical* otherPhys = (plPXPhysical*)otherShape.getActor().userData; plPXPhysical* otherPhys = (plPXPhysical*)otherShape.getActor().userData;
if (otherPhys) if (otherPhys)
{ {
otherKey = otherPhys->GetObjectKey(); otherKey = otherPhys->GetObjectKey();
doReport = triggerPhys->DoReportOn((plSimDefs::Group)otherPhys->GetGroup()); doReport = triggerPhys->DoReportOn((plSimDefs::Group)otherPhys->GetGroup());
if (!doReport)
{
if (plSimulationMgr::fExtraProfile)
DetectorLogRed("<--Kill collision %s :failed group. US=%x OTHER=(%s)%x",triggerPhys->GetObjectKey()->GetName(),triggerPhys->GetGroup(),otherPhys->GetObjectKey()->GetName(),otherPhys->GetGroup());
}
} }
else else
{ {
bool isController; plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(otherShape.getActor());
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(otherShape.getActor(),&isController);
if (controller) if (controller)
{ {
if (isController)
{
#ifdef PHYSX_ONLY_TRIGGER_FROM_KINEMATIC
if (plSimulationMgr::fExtraProfile)
DetectorLogRed("<--Kill collision %s : ignoring controller events.",triggerPhys->GetObjectKey()->GetName());
return;
#else // else if trigger on both controller and kinematic
// only suppress controller collision 'enters' when disabled but let 'exits' continue
// ...this is because there are detector regions that are on the edge on ladders that the exit gets missed.
if ( ( !controller->IsEnabled() /*&& (status & NX_TRIGGER_ON_ENTER)*/ ) || controller->IsKinematic() )
{
if (plSimulationMgr::fExtraProfile)
DetectorLogRed("<--Kill collision %s : controller is not enabled.",triggerPhys->GetObjectKey()->GetName());
return;
}
#endif // PHYSX_ONLY_TRIGGER_FROM_KINEMATIC
}
#ifndef PHYSX_ONLY_TRIGGER_FROM_KINEMATIC // if triggering only kinematics, then all should trigger
else
{
// only suppress kinematic collision 'enters' when disabled but let 'exits' continue
// ...this is because there are detector regions that are on the edge on ladders that the exit gets missed.
if ( !controller->IsKinematic() /*&& (status & NX_TRIGGER_ON_ENTER) */ )
{
if (plSimulationMgr::fExtraProfile)
DetectorLogRed("<--Kill collision %s : kinematic is not enabled.",triggerPhys->GetObjectKey()->GetName());
return;
}
}
#endif // PHYSX_ONLY_TRIGGER_FROM_KINEMATIC
otherKey = controller->GetOwner(); otherKey = controller->GetOwner();
doReport = triggerPhys->DoReportOn(plSimDefs::kGroupAvatar); doReport = triggerPhys->DoReportOn(plSimDefs::kGroupAvatar);
if (plSimulationMgr::fExtraProfile )
{
if (!doReport)
{
DetectorLogRed("<--Kill collision %s :failed group. US=%x OTHER=(NotAvatar)",triggerPhys->GetObjectKey()->GetName(),triggerPhys->GetGroup());
}
else
{
hsPoint3 avpos;
controller->GetPositionSim(avpos);
DetectorLogRed("-->Avatar at (%f,%f,%f)",avpos.fX,avpos.fY,avpos.fZ);
}
}
} }
} }
@ -315,7 +261,7 @@ public:
// //
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
#define kDefaultMaxDelta 0.1 // if the step is greater than .1 seconds, clamp to that #define kDefaultMaxDelta 0.15 // if the step is greater than .15 seconds, clamp to that
#define kDefaultStepSize 1.f / 60.f // default simulation freqency is 60hz #define kDefaultStepSize 1.f / 60.f // default simulation freqency is 60hz
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
@ -408,6 +354,8 @@ plSimulationMgr::plSimulationMgr()
: fSuspended(true) : fSuspended(true)
, fMaxDelta(kDefaultMaxDelta) , fMaxDelta(kDefaultMaxDelta)
, fStepSize(kDefaultStepSize) , fStepSize(kDefaultStepSize)
, fAccumulator(0.0f)
, fStepCount(0)
, fLOSDispatch(TRACKED_NEW plLOSDispatch()) , fLOSDispatch(TRACKED_NEW plLOSDispatch())
, fSoundMgr(new plPhysicsSoundMgr) , fSoundMgr(new plPhysicsSoundMgr)
, fLog(nil) , fLog(nil)
@ -496,6 +444,7 @@ NxScene* plSimulationMgr::GetScene(plKey world)
scene->setGroupCollisionFlag(i, plSimDefs::kGroupDynamicBlocker, false); scene->setGroupCollisionFlag(i, plSimDefs::kGroupDynamicBlocker, false);
scene->setGroupCollisionFlag(i, plSimDefs::kGroupLOSOnly, false); scene->setGroupCollisionFlag(i, plSimDefs::kGroupLOSOnly, false);
scene->setGroupCollisionFlag(plSimDefs::kGroupLOSOnly, i, false); scene->setGroupCollisionFlag(plSimDefs::kGroupLOSOnly, i, false);
scene->setGroupCollisionFlag(i, plSimDefs::kGroupAvatarKinematic, false);
} }
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupAvatar, false); scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupAvatar, false);
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupAvatarBlocker, true); scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupAvatarBlocker, true);
@ -504,6 +453,10 @@ NxScene* plSimulationMgr::GetScene(plKey world)
scene->setGroupCollisionFlag( plSimDefs::kGroupStatic, plSimDefs::kGroupAvatar, true); scene->setGroupCollisionFlag( plSimDefs::kGroupStatic, plSimDefs::kGroupAvatar, true);
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupDynamic, true); scene->setGroupCollisionFlag(plSimDefs::kGroupAvatar, plSimDefs::kGroupDynamic, true);
// Kinematically controlled avatars interact with detectors and dynamics
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatarKinematic, plSimDefs::kGroupDetector, true);
scene->setGroupCollisionFlag(plSimDefs::kGroupAvatarKinematic, plSimDefs::kGroupDynamic, true);
// The dynamics are in actor group 1, everything else is in 0. Request // The dynamics are in actor group 1, everything else is in 0. Request
// a callback for whenever a dynamic touches something. // a callback for whenever a dynamic touches something.
scene->setActorGroupPairFlags(0, 1, NX_NOTIFY_ON_TOUCH); scene->setActorGroupPairFlags(0, 1, NX_NOTIFY_ON_TOUCH);
@ -616,8 +569,7 @@ void plSimulationMgr::UpdateAvatarInDetector(plKey world, plPXPhysical* detector
if ( actors[i]->userData == nil ) if ( actors[i]->userData == nil )
{ {
// we go a controller // we go a controller
bool isController; plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(*actors[i]);
plPXPhysicalControllerCore* controller = plPXPhysicalControllerCore::GetController(*actors[i],&isController);
if (controller && controller->IsEnabled()) if (controller && controller->IsEnabled())
{ {
plKey avatar = controller->GetOwner(); plKey avatar = controller->GetOwner();
@ -644,20 +596,31 @@ void plSimulationMgr::Advance(float delSecs)
if (fSuspended) if (fSuspended)
return; return;
if (delSecs > fMaxDelta) fAccumulator += delSecs;
if (fAccumulator < fStepSize)
{
// Not enough time has passed to perform a substep.
plPXPhysicalControllerCore::UpdateNonPhysical(fAccumulator / fStepSize);
return;
}
else if (fAccumulator > fMaxDelta)
{ {
if (fExtraProfile) if (fExtraProfile)
Log("Step clamped from %f to limit of %f", delSecs, fMaxDelta); Log("Step clamped from %f to limit of %f", fAccumulator, fMaxDelta);
delSecs = fMaxDelta; fAccumulator = fMaxDelta;
} }
plProfile_IncCount(StepLen, (int)(delSecs*1000));
#ifndef PLASMA_EXTERNAL_RELASE ++fStepCount;
UInt32 stepTime = hsTimer::GetPrecTickCount();
#endif // Perform as many whole substeps as possible saving the remainder in our accumulator.
int numSubSteps = (int)(fAccumulator / fStepSize + 0.000001f);
float delta = numSubSteps * fStepSize;
fAccumulator -= delta;
plProfile_IncCount(StepLen, (int)(delta*1000));
plProfile_BeginTiming(Step); plProfile_BeginTiming(Step);
plPXPhysicalControllerCore::UpdatePrestep(delSecs);
plPXPhysicalControllerCore::UpdatePoststep( delSecs); plPXPhysicalControllerCore::Apply(delta);
for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++) for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
{ {
@ -672,12 +635,13 @@ void plSimulationMgr::Advance(float delSecs)
} }
if (do_advance) if (do_advance)
{ {
scene->simulate(delSecs); scene->simulate(delta);
scene->flushStream(); scene->flushStream();
scene->fetchResults(NX_RIGID_BODY_FINISHED, true); scene->fetchResults(NX_RIGID_BODY_FINISHED, true);
} }
} }
plPXPhysicalControllerCore::UpdatePostSimStep(delSecs);
plPXPhysicalControllerCore::Update(numSubSteps, fAccumulator / fStepSize);
//sending off and clearing the Collision Messages generated by scene->simulate //sending off and clearing the Collision Messages generated by scene->simulate
IDispatchCollisionMessages(); IDispatchCollisionMessages();
@ -754,9 +718,6 @@ void plSimulationMgr::ISendUpdates()
plPXPhysical* physical = (plPXPhysical*)actors[i]->userData; plPXPhysical* physical = (plPXPhysical*)actors[i]->userData;
if (physical) if (physical)
{ {
// apply any hit forces
physical->ApplyHitForce();
if (physical->GetSceneNode()) if (physical->GetSceneNode())
{ {
physical->SendNewLocation(); physical->SendNewLocation();

5
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysX/plSimulationMgr.h

@ -99,6 +99,8 @@ public:
int GetMaterialIdx(NxScene* scene, hsScalar friction, hsScalar restitution); int GetMaterialIdx(NxScene* scene, hsScalar friction, hsScalar restitution);
UInt32 GetStepCount() { return fStepCount; }
// PHYSX FIXME - walk thru all the convex hull detector regions to see if we are in any... we're either coming or going // PHYSX FIXME - walk thru all the convex hull detector regions to see if we are in any... we're either coming or going
void UpdateDetectorsInScene(plKey world, plKey avatar, hsPoint3& pos, bool entering); void UpdateDetectorsInScene(plKey world, plKey avatar, hsPoint3& pos, bool entering);
void UpdateAvatarInDetector(plKey world, plPXPhysical* detector); void UpdateAvatarInDetector(plKey world, plPXPhysical* detector);
@ -159,6 +161,9 @@ protected:
float fMaxDelta; float fMaxDelta;
float fStepSize; float fStepSize;
float fAccumulator;
UInt32 fStepCount;
// A utility class to keep track of a request for a physical synchronization. // A utility class to keep track of a request for a physical synchronization.
// These requests must pass a certain criteria (see the code for the latest) // These requests must pass a certain criteria (see the code for the latest)

448
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.cpp

@ -39,7 +39,6 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
Mead, WA 99021 Mead, WA 99021
*==LICENSE==*/ *==LICENSE==*/
#include "../plAvatar/plAvCallbackAction.h"
#include "hsTypes.h" #include "hsTypes.h"
#include "plCollisionDetector.h" #include "plCollisionDetector.h"
@ -65,11 +64,13 @@ You can contact Cyan Worlds, Inc. by email legal@cyan.com
#include "../plAvatar/plAvatarMgr.h" #include "../plAvatar/plAvatarMgr.h"
#include "../plAvatar/plAvBrainHuman.h" #include "../plAvatar/plAvBrainHuman.h"
#include "../plAvatar/plAvBrainDrive.h" #include "../plAvatar/plAvBrainDrive.h"
#include "../plAvatar/plPhysicalControllerCore.h"
#include "../plModifier/plDetectorLog.h" #include "../plModifier/plDetectorLog.h"
#define USE_PHYSX_MULTIPLE_CAMREGION_ENTER 1 #ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
#define USE_PHYSX_COLLISION_FLUTTER_WORKAROUND 1 #include "../plPhysX/plSimulationMgr.h"
#endif
plArmatureMod* plCollisionDetector::IGetAvatarModifier(plKey key) plArmatureMod* plCollisionDetector::IGetAvatarModifier(plKey key)
{ {
@ -245,127 +246,40 @@ plCameraRegionDetector::~plCameraRegionDetector()
fMessages.SetCountAndZero(0); fMessages.SetCountAndZero(0);
} }
void plCameraRegionDetector::ITrigger(plKey hitter, bool entering, bool immediate) void plCameraRegionDetector::ISendTriggerMsg()
{
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
if (entering && fNumEvals - fLastExitEval <= 1 && fSavingSendMsg)
{
DetectorLog("%s: Skipping Camera Entering volume", GetKeyName());
fLastEnterEval = fNumEvals;
if (fSavingSendMsg)
{
DetectorLog("%s: Dumping saved Camera Exiting volume", GetKeyName());
}
fSavingSendMsg = false;
return;
}
if (!entering && fNumEvals - fLastEnterEval <= 1 && fSavingSendMsg)
{ {
DetectorLog("%s: Skipping Exiting volume", GetKeyName()); for (int i = 0; i < fMessages.Count(); ++i)
fLastExitEval = fNumEvals;
if (fSavingSendMsg)
{ {
DetectorLog("%s: Dumping saved Camera Entering volume", GetKeyName());
}
fSavingSendMsg = false;
return;
}
// get rid of any saved messages... this should happen though
if (fSavingSendMsg)
{
DetectorLog("%s: Killing saved camera message... shouldn't happen", GetKeyName());
}
// end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
fSavingSendMsg = true;
fSavedMsgEnterFlag = entering;
if (entering)
{
//DetectorLog("%s: Saving camera Entering volume - Evals=%d", GetKeyName(),fNumEvals);
fLastEnterEval = fNumEvals;
}
else
{
//DetectorLog("%s: Saving camera Exiting volume - Evals=%d", GetKeyName(),fNumEvals);
fLastExitEval = fNumEvals;
}
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
// we're saving the message to be dispatched later...
if (immediate)
{
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
ISendSavedTriggerMsgs();
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
}
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
}
void plCameraRegionDetector::ISendSavedTriggerMsgs()
{
if (fSavingSendMsg)
{
for (int i = 0; i < fMessages.Count(); i++)
{
char str[256];
hsRefCnt_SafeRef(fMessages[i]); hsRefCnt_SafeRef(fMessages[i]);
if (fSavedMsgEnterFlag) if (fIsInside)
{
fMessages[i]->SetCmd(plCameraMsg::kEntering); fMessages[i]->SetCmd(plCameraMsg::kEntering);
sprintf(str, "Entering cameraRegion: %s - Evals=%d -msg %d of %d\n", GetKeyName(),fNumEvals,i+1,fMessages.Count());
fIsInside = true;
}
else else
{
fMessages[i]->ClearCmd(plCameraMsg::kEntering); fMessages[i]->ClearCmd(plCameraMsg::kEntering);
sprintf(str, "Exiting cameraRegion: %s - Evals=%d -msg %d of %d\n", GetKeyName(),fNumEvals,i+1,fMessages.Count());
fIsInside = false;
}
plgDispatch::MsgSend(fMessages[i]); plgDispatch::MsgSend(fMessages[i]);
DetectorLog("%s", str);
}
} }
fSavingSendMsg = false;
} }
hsBool plCameraRegionDetector::MsgReceive(plMessage* msg) hsBool plCameraRegionDetector::MsgReceive(plMessage* msg)
{ {
plCollideMsg* pCollMsg = plCollideMsg::ConvertNoRef(msg); plCollideMsg* pCollMsg = plCollideMsg::ConvertNoRef(msg);
if (pCollMsg) if (pCollMsg)
{ {
// camera collisions are only for the local player // camera collisions are only for the local player
if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pCollMsg->fOtherKey) if (plNetClientApp::GetInstance()->GetLocalPlayerKey() != pCollMsg->fOtherKey)
return true; return true;
#ifdef USE_PHYSX_MULTIPLE_CAMREGION_ENTER
// first determine if this is a multiple camera region enter (PHYSX BUG WORKAROUND)
if (!fWaitingForEval) if (!fWaitingForEval)
{//plObjectInVolumeCollisionDetector::MsgReceive() will flip fWaitingForEval IRegisterForEval();
// and registers for the Eval, child objects of plObjectInVolumeCollisionDetector
//must decide when they are no longer interested in Evals. I suggest using IHandleEvals()
fNumEvals = 0; fEntering = (pCollMsg->fEntering != 0);
fLastEnterEval=-999;
fLastExitEval=-999;
}
// end of (PHYSX BUG WORKAROUND)
#endif // USE_PHYSX_MULTIPLE_CAMREG_ENTER
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
fLastStep = plSimulationMgr::GetInstance()->GetStepCount();
#endif
return true;
} }
return plObjectInVolumeDetector::MsgReceive(msg); return plObjectInVolumeDetector::MsgReceive(msg);
} }
void plCameraRegionDetector::Read(hsStream* stream, hsResMgr* mgr) void plCameraRegionDetector::Read(hsStream* stream, hsResMgr* mgr)
@ -388,22 +302,24 @@ void plCameraRegionDetector::Write(hsStream* stream, hsResMgr* mgr)
mgr->WriteCreatable( stream, fMessages[i] ); mgr->WriteCreatable( stream, fMessages[i] );
} }
void plCameraRegionDetector::IHandleEval(plEvalMsg *pEval)
void plCameraRegionDetector::IHandleEval(plEvalMsg*)
{ {
fNumEvals++; #ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
if (fNumEvals - fLastEnterEval > 1 && fNumEvals-fLastExitEval>1) if (plSimulationMgr::GetInstance()->GetStepCount() - fLastStep > 1)
{
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
if (fIsInside != fEntering)
{ {
ISendSavedTriggerMsgs(); fIsInside = fEntering;
DetectorLog("%s CameraRegion: %s", fIsInside ? "Entering" : "Exiting", GetKeyName());
ISendTriggerMsg();
}
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey()); plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
fWaitingForEval = false; fWaitingForEval = false;
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
} }
else #endif
{
if(fSavedActivatorMsg)
DetectorLog("%s didn't send its message. fNumEvals=%d fLastEnterEval=%d, fLastExit=%d",
GetKeyName(),fNumEvals, fLastEnterEval, fLastExitEval);
}
} }
///////////////////////////////// /////////////////////////////////
@ -412,182 +328,49 @@ void plCameraRegionDetector::IHandleEval(plEvalMsg *pEval)
///////////////////////////////// /////////////////////////////////
// object-in-volume detector // object-in-volume detector
void plObjectInVolumeDetector::ITrigger(plKey hitter, bool entering, bool immediate) void plObjectInVolumeDetector::ITrigger(plKey hitter, bool entering)
{ {
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND #ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame for (bookKeepingList::iterator it = fCollisionList.begin(); it != fCollisionList.end(); ++it)
/* if (entering && fNumEvals - fLastExitEval <= 1 && fSavedActivatorMsg)
{
//DetectorLog("%s: Skipping Entering volume", GetKeyName());
fLastEnterEval = fNumEvals;
if (fSavedActivatorMsg)
{
//DetectorLog("%s: Dumping saved Exiting volume", GetKeyName());
delete fSavedActivatorMsg;
}
fSavedActivatorMsg = nil;
return;
}
if (!entering && fNumEvals - fLastEnterEval <= 1 && fSavedActivatorMsg)
{ {
//DetectorLog("%s: Skipping Exiting volume", GetKeyName()); plCollisionBookKeepingInfo* collisionInfo = *it;
fLastExitEval = fNumEvals; if (collisionInfo->fHitter == hitter)
if (fSavedActivatorMsg)
{ {
//DetectorLog("%s: Dumping saved Entering volume", GetKeyName()); collisionInfo->fEntering = entering;
delete fSavedActivatorMsg; collisionInfo->fLastStep = plSimulationMgr::GetInstance()->GetStepCount();
}
fSavedActivatorMsg = nil;
return; return;
} }
// get rid of any saved messages... this should happen though
if (fSavedActivatorMsg)
{
delete fSavedActivatorMsg;
DetectorLog("%s: Killing saved message... shouldn't happen", GetKeyName());
} }
// end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame #endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
*/
if(!immediate)
{
bookKeepingList::iterator curit=fCollisionList.begin(); plCollisionBookKeepingInfo* collisionInfo = new plCollisionBookKeepingInfo(hitter, entering);
while(curit!=fCollisionList.end()) fCollisionList.push_back(collisionInfo);
{ #ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
if(hitter==(*curit)->hitter) collisionInfo->fLastStep = plSimulationMgr::GetInstance()->GetStepCount();
{//hey the object is already in my list #endif
//try and figure out what my real state is
if(entering)
{
(*curit)->enters++;
if(!(*curit)->fSubStepCurState)
{//We weren't already in
(*curit)->fSubStepCurState =true;
}
}
else
{
(*curit)->exits++;
if((*curit)->fSubStepCurState)
{//We were already in
(*curit)->fSubStepCurState =false;
}
}
//get out
break;
}
curit++;
} }
if(curit==fCollisionList.end())
{
//hitter was not in the list add him in
//hitter was not in the current frame list
//lets find out its state in the begining of the frame
ResidentSet::iterator curres = fCurrentResidents.find(hitter);
bool initialState;
if(curres != fCurrentResidents.end())
initialState =true;
else
initialState =false;
plCollisionBookKeepingInfo* BookKeeper=TRACKED_NEW plCollisionBookKeepingInfo(hitter); void plObjectInVolumeDetector::IRegisterForEval()
if(entering)
{ {
BookKeeper->enters++; fWaitingForEval = true;
BookKeeper->fSubStepCurState =true; plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
}
else
{
BookKeeper->exits++;
BookKeeper->fSubStepCurState =false;
}
fCollisionList.push_front(BookKeeper);
}
} }
else
{
plActivatorMsg* ActivatorMsg = TRACKED_NEW plActivatorMsg;
ActivatorMsg->AddReceivers(fReceivers);
if (fProxyKey)
ActivatorMsg->fHiteeObj = fProxyKey;
else
ActivatorMsg->fHiteeObj = GetTarget()->GetKey();
ActivatorMsg->fHitterObj = hitter; void plObjectInVolumeDetector::ISendTriggerMsg(plKey hitter, bool entering)
ActivatorMsg->SetSender(GetKey());
if (entering)
{
ActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter);
}
else
{ {
ActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit); plActivatorMsg* activatorMsg = new plActivatorMsg();
} activatorMsg->SetSender(GetKey());
activatorMsg->AddReceivers(fReceivers);
plgDispatch::MsgSend(ActivatorMsg); activatorMsg->fHiteeObj = fProxyKey ? fProxyKey : GetTarget()->GetKey();
activatorMsg->fHitterObj = hitter;
}
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
/* fSavedActivatorMsg = TRACKED_NEW plActivatorMsg;
fSavedActivatorMsg->AddReceivers(fReceivers);
if (fProxyKey)
fSavedActivatorMsg->fHiteeObj = fProxyKey;
else
fSavedActivatorMsg->fHiteeObj = GetTarget()->GetKey();
fSavedActivatorMsg->fHitterObj = hitter;
fSavedActivatorMsg->SetSender(GetKey());
if (entering) if (entering)
{ activatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter);
//DetectorLog("%s: Saving Entering volume - Evals=%d", GetKeyName(),fNumEvals);
fSavedActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeEnter);
fLastEnterEval = fNumEvals;
}
else else
{ activatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit);
//DetectorLog("%s: Saving Exiting volume - Evals=%d", GetKeyName(),fNumEvals);
fSavedActivatorMsg->SetTriggerType(plActivatorMsg::kVolumeExit);
fLastExitEval = fNumEvals;
}
*/
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
// we're saving the message to be dispatched later...
if (immediate)
{
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// fSavedActivatorMsg = nil;
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND plgDispatch::MsgSend(activatorMsg);
}
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
} }
/*
void plObjectInVolumeDetector::ISendSavedTriggerMsgs()
{
if (fSavedActivatorMsg)
{
if (fSavedActivatorMsg->fTriggerType == plActivatorMsg::kVolumeEnter)
DetectorLog("%s: Sending Entering volume - Evals=%d", GetKeyName(),fNumEvals);
else
DetectorLog("%s: Sending Exiting volume - Evals=%d", GetKeyName(),fNumEvals);
// we're saving the message to be dispatched later...
plgDispatch::MsgSend(fSavedActivatorMsg);
}
fSavedActivatorMsg = nil;
}
*/
hsBool plObjectInVolumeDetector::MsgReceive(plMessage* msg) hsBool plObjectInVolumeDetector::MsgReceive(plMessage* msg)
{ {
plCollideMsg* pCollMsg = plCollideMsg::ConvertNoRef(msg); plCollideMsg* pCollMsg = plCollideMsg::ConvertNoRef(msg);
@ -597,36 +380,17 @@ hsBool plObjectInVolumeDetector::MsgReceive(plMessage* msg)
if (IIsDisabledAvatar(pCollMsg->fOtherKey)) if (IIsDisabledAvatar(pCollMsg->fOtherKey))
return false; return false;
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
if (!fWaitingForEval) if (!fWaitingForEval)
{ IRegisterForEval();
plgDispatch::Dispatch()->RegisterForExactType(plEvalMsg::Index(), GetKey());
fWaitingForEval = true;
}
// end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
ITrigger(pCollMsg->fOtherKey, (pCollMsg->fEntering != 0));
ITrigger(pCollMsg->fOtherKey, (pCollMsg->fEntering != 0));
return true; return true;
} }
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
// PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
plEvalMsg* pEval = plEvalMsg::ConvertNoRef(msg); plEvalMsg* pEval = plEvalMsg::ConvertNoRef(msg);
if (pEval) if (pEval)
{
//if (fSavedActivatorMsg)
// DetectorLog("%s: InVolumeEval=%d with saved message", GetKeyName(), fNumEvals);
//else
// DetectorLog("%s: InVolumeEval=%d without saved message", GetKeyName(), fNumEvals);
IHandleEval(pEval); IHandleEval(pEval);
}
// end PHYSX_FIXME hack for PhysX turd that sends bunches of enter/exits over one frame
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
plPlayerPageMsg* pageMsg = plPlayerPageMsg::ConvertNoRef(msg); plPlayerPageMsg* pageMsg = plPlayerPageMsg::ConvertNoRef(msg);
if (pageMsg && pageMsg->fUnload) if (pageMsg && pageMsg->fUnload)
{ {
@ -636,73 +400,57 @@ hsBool plObjectInVolumeDetector::MsgReceive(plMessage* msg)
return plCollisionDetector::MsgReceive(msg); return plCollisionDetector::MsgReceive(msg);
} }
void plObjectInVolumeDetector::IHandleEval(plEvalMsg* pEval) void plObjectInVolumeDetector::IHandleEval(plEvalMsg*)
{ {
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey()); bookKeepingList::iterator it = fCollisionList.begin();
fWaitingForEval = false; while (it != fCollisionList.end())
for(bookKeepingList::reverse_iterator it= fCollisionList.rbegin();it!=fCollisionList.rend(); it++)
{
bool alreadyInside;
ResidentSet::iterator HitIt;
HitIt = fCurrentResidents.find((*it)->hitter);
if(HitIt != fCurrentResidents.end()) alreadyInside = true;
else alreadyInside=false;
plActivatorMsg* actout=TRACKED_NEW plActivatorMsg;
actout->fHitterObj=((*it)->hitter);
actout->SetSender(GetKey());
if (fProxyKey)
actout->fHiteeObj = fProxyKey;
else
actout->fHiteeObj = GetTarget()->GetKey();
if((*it)->fSubStepCurState)//current substate says we are entered
{//different enters and exits
//figure out what to do
if(!alreadyInside)
{//we are actuall entering
actout->SetTriggerType(plActivatorMsg::kVolumeEnter);
fCurrentResidents.insert((*it)->hitter);
actout->AddReceivers(fReceivers);
actout->Send();
DetectorLog("%s sent an Enter ActivatorMsg. To: %s", GetKeyName(), GetTarget()->GetKeyName() );
}
else
{ {
DetectorLog("%s squelched an Enter ActivatorMsg.", GetKeyName()); plCollisionBookKeepingInfo* collisionInfo = *it;
delete actout; #ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
} if (plSimulationMgr::GetInstance()->GetStepCount() - collisionInfo->fLastStep > 1)
}
else
{ {
//fSubStepCurState says we are outside #endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
if(alreadyInside) bool wasInside = fCurrentResidents.find(collisionInfo->fHitter) != fCurrentResidents.end();
{//we are actuall exiting if (collisionInfo->fEntering != wasInside)
actout->SetTriggerType(plActivatorMsg::kVolumeExit); {
fCurrentResidents.erase((*it)->hitter); if (collisionInfo->fEntering)
actout->AddReceivers(fReceivers); {
actout->Send(); fCurrentResidents.insert(collisionInfo->fHitter);
DetectorLog("%s sent an Exit ActivatorMsg. To: %s", GetKeyName(), GetTarget()->GetKeyName()); DetectorLog("%s: Sending Volume Enter ActivatorMsg", GetKeyName());
ISendTriggerMsg(collisionInfo->fHitter, true);
} }
else else
{ {
DetectorLog("%s squelched an Exit ActivatorMsg.", GetKeyName()); fCurrentResidents.erase(collisionInfo->fHitter);
delete actout; DetectorLog("%s: Sending Volume Exit ActivatorMsg", GetKeyName());
ISendTriggerMsg(collisionInfo->fHitter, false);
} }
} }
delete collisionInfo;
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
it = fCollisionList.erase(it);
} }
DetectorLog("*********"); else
for(bookKeepingList::iterator it = fCollisionList.begin(); it != fCollisionList.end(); it ++)
{ {
delete (*it); ++it;
} }
DetectorLog("This is the regions inhabitants after the op"); #else
for(ResidentSet::iterator it = fCurrentResidents.begin(); it!= fCurrentResidents.end(); it++) ++it;
{ #endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
DetectorLog("%s", (*it)->GetName());
} }
DetectorLog("*********");
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
if (fCollisionList.empty())
{
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
fWaitingForEval = false;
}
#else
fCollisionList.clear(); fCollisionList.clear();
plgDispatch::Dispatch()->UnRegisterForExactType(plEvalMsg::Index(), GetKey());
fWaitingForEval = false;
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
} }
void plObjectInVolumeDetector::SetTarget(plSceneObject* so) void plObjectInVolumeDetector::SetTarget(plSceneObject* so)
@ -770,7 +518,7 @@ void plObjectInVolumeAndFacingDetector::ICheckForTrigger()
// And are we walking towards it? // And are we walking towards it?
plArmatureBrain* abrain = armMod->FindBrainByClass(plAvBrainHuman::Index()); //armMod->GetCurrentBrain(); plArmatureBrain* abrain = armMod->FindBrainByClass(plAvBrainHuman::Index()); //armMod->GetCurrentBrain();
plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(abrain); plAvBrainHuman* brain = plAvBrainHuman::ConvertNoRef(abrain);
if (brain && brain->IsMovingForward() && brain->fCallbackAction->IsOnGround()) if (brain && brain->IsMovingForward() && brain->fWalkingStrategy->IsOnGround())
movingForward = true; movingForward = true;
} }
else else
@ -780,13 +528,13 @@ void plObjectInVolumeAndFacingDetector::ICheckForTrigger()
{ {
DetectorLog("%s: Trigger InVolume&Facing", GetKeyName()); DetectorLog("%s: Trigger InVolume&Facing", GetKeyName());
fTriggered = true; fTriggered = true;
ITrigger(avatar->GetKey(), true, true); ISendTriggerMsg(avatar->GetKey(), true);
} }
else if (!facing && fTriggered) else if (!facing && fTriggered)
{ {
DetectorLog("%s: Untrigger InVolume&Facing", GetKeyName()); DetectorLog("%s: Untrigger InVolume&Facing", GetKeyName());
fTriggered = false; fTriggered = false;
ITrigger(avatar->GetKey(), false, true); ISendTriggerMsg(avatar->GetKey(), false);
} }
} }
} }
@ -820,7 +568,7 @@ hsBool plObjectInVolumeAndFacingDetector::MsgReceive(plMessage* msg)
if (fTriggered) if (fTriggered)
{ {
fTriggered = false; fTriggered = false;
ITrigger(plNetClientApp::GetInstance()->GetLocalPlayerKey(), false, true); ISendTriggerMsg(plNetClientApp::GetInstance()->GetLocalPlayerKey(), false);
} }
} }
@ -940,11 +688,11 @@ hsBool plPanicLinkRegion::MsgReceive(plMessage* msg)
plArmatureMod* avMod = IGetAvatarModifier(pCollMsg->fOtherKey); plArmatureMod* avMod = IGetAvatarModifier(pCollMsg->fOtherKey);
if (avMod) if (avMod)
{ {
hsPoint3 kinPos; hsPoint3 pos;
if (avMod->GetController()) if (avMod->GetController())
{ {
avMod->GetController()->GetKinematicPosition(kinPos); avMod->GetController()->GetPositionSim(pos);
DetectorLogSpecial("Avatar is panic linking. KinPos at %f,%f,%f and is %s",kinPos.fX,kinPos.fY,kinPos.fZ,avMod->GetController()->IsEnabled() ? "enabled" : "disabled"); DetectorLogSpecial("Avatar is panic linking. Position %f,%f,%f and is %s", pos.fX, pos.fY, pos.fZ, avMod->GetController()->IsEnabled() ? "enabled" : "disabled");
} }
avMod->PanicLink(fPlayLinkOutAnim); avMod->PanicLink(fPlayLinkOutAnim);
} }

65
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plCollisionDetector.h

@ -53,6 +53,8 @@ class plArmatureMod;
class plActivatorMsg; class plActivatorMsg;
class plEvalMsg; class plEvalMsg;
#define USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
class plCollisionDetector : public plDetectorModifier class plCollisionDetector : public plDetectorModifier
{ {
protected: protected:
@ -90,34 +92,26 @@ public:
// sub type for object-in-volume detectors // sub type for object-in-volume detectors
class plObjectInVolumeDetector : public plCollisionDetector class plObjectInVolumeDetector : public plCollisionDetector
{ {
public: protected:
class plCollisionBookKeepingInfo class plCollisionBookKeepingInfo
{ {
friend plObjectInVolumeDetector;
public: public:
plCollisionBookKeepingInfo(plKey& hit) plCollisionBookKeepingInfo(plKey& key, bool entering)
{ : fHitter(key), fEntering(entering) { }
hitter=hit;
enters=0; plKey fHitter;
exits=0; #ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
} UInt32 fLastStep;
~plCollisionBookKeepingInfo() #endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
{ bool fEntering;
hitter=nil;
}
protected:
plKey hitter;
int enters,exits;
bool fSubStepCurState;
}; };
protected:
virtual void ITrigger(plKey hitter, bool entering, bool immediate=false); virtual void ITrigger(plKey hitter, bool entering);
//virtual void ISendSavedTriggerMsgs(); virtual void ISendTriggerMsg(plKey hitter, bool entering);
virtual void IRegisterForEval();
virtual void IHandleEval(plEvalMsg* pEval); virtual void IHandleEval(plEvalMsg* pEval);
bool fWaitingForEval; bool fWaitingForEval;
plActivatorMsg* fSavedActivatorMsg;
typedef std::list<plCollisionBookKeepingInfo*> bookKeepingList; typedef std::list<plCollisionBookKeepingInfo*> bookKeepingList;
bookKeepingList fCollisionList; bookKeepingList fCollisionList;
typedef std::set<plKey> ResidentSet; typedef std::set<plKey> ResidentSet;
@ -126,12 +120,12 @@ protected:
public: public:
plObjectInVolumeDetector() plObjectInVolumeDetector()
{ : plCollisionDetector(), fWaitingForEval(false) { }
fWaitingForEval=false;fSavedActivatorMsg=nil;
plObjectInVolumeDetector(Int8 i)
: plCollisionDetector(), fWaitingForEval(false) { fType = i; }
} virtual ~plObjectInVolumeDetector() { }
plObjectInVolumeDetector(Int8 i){fType = i;fWaitingForEval=false;fSavedActivatorMsg=nil;}
virtual ~plObjectInVolumeDetector(){;}
virtual hsBool MsgReceive(plMessage* msg); virtual hsBool MsgReceive(plMessage* msg);
@ -178,18 +172,19 @@ class plCameraRegionDetector : public plObjectInVolumeDetector
{ {
protected: protected:
hsTArray<plCameraMsg*> fMessages; hsTArray<plCameraMsg*> fMessages;
#ifdef USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
UInt32 fLastStep;
#endif // USE_PHYSX_COLLISION_FLUTTER_WORKAROUND
bool fIsInside; bool fIsInside;
bool fSavingSendMsg; bool fEntering;
bool fSavedMsgEnterFlag;
int fNumEvals; virtual void ISendTriggerMsg();
int fLastEnterEval;
int fLastExitEval;
virtual void ITrigger(plKey hitter, bool entering, bool immediate=false);
virtual void ISendSavedTriggerMsgs();
virtual void IHandleEval(plEvalMsg* pEval); virtual void IHandleEval(plEvalMsg* pEval);
public: public:
plCameraRegionDetector(){ fIsInside = false; fSavingSendMsg = false; } plCameraRegionDetector()
: plObjectInVolumeDetector(), fIsInside(false) { }
~plCameraRegionDetector(); ~plCameraRegionDetector();
virtual hsBool MsgReceive(plMessage* msg); virtual hsBool MsgReceive(plMessage* msg);

23
MOULOpenSourceClientPlugin/Plasma20/Sources/Plasma/PubUtilLib/plPhysical/plSimDefs.h

@ -68,27 +68,10 @@ namespace plSimDefs
kGroupLOSOnly, kGroupLOSOnly,
//kExcludeRegion setting up so only blocks avatars and only when not in seek mode //kExcludeRegion setting up so only blocks avatars and only when not in seek mode
kGroupExcludeRegion, kGroupExcludeRegion,
// A kinematic avatar only interacts with dynamics and detectors
kGroupAvatarKinematic,
// Just for error checking // Just for error checking
kGroupMax, kGroupMax
};
/** A taxonomy of action types. Crucial for doing things like making sure you don't
do things like attach duplicate actions. */
enum ActionType
{
kUnknownAction = 0x01, // don't know the type (probably forgot to override GetType())
kUnknownZAction = 0x02, // unknown type of z-order action
kAntiGravityAction = 0x03, // an action that counters gravity exactly
kUprightAction = 0x04, // an action that keeps an object upright by apply force
kPhysAnimAction = 0x05, // an action that parses keyframed animation into physical information
kConstraint = 0x06, // a general constraint.
kCallbackAction = 0x07, // an action that just hands us the physics "tick"
kPseudoPhysAction = 0x08, // replacement for the physAnim
kAntiGravAction = 0x09, // makes things float in the air
kBasicGroundAction = 0x0a, // for your basic walkAroundOnGround corrections
kHorizontalFreeze = 0x0b, // Let's you fall vertically, but otherwise keeps you in place (generic brains)
kMaxAction = 0xffff // force 16-bit
}; };
/** Different types of line-of-sight requests. */ /** Different types of line-of-sight requests. */

Loading…
Cancel
Save