mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-14 13:30:48 +03:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
0a95b8079a | ||
|
3cdea3b939 |
@@ -216,6 +216,7 @@ n SelectMgr
|
||||
n StdPrs
|
||||
n StdSelect
|
||||
n V3d
|
||||
n Dynamics
|
||||
n Wasm
|
||||
n WNT
|
||||
n Xw
|
||||
|
@@ -238,6 +238,15 @@ proc wokdep:gui:UpdateList {} {
|
||||
set aDummy {}
|
||||
wokdep:SearchStandardLibrary anIncErrs anLib32Errs anLib64Errs aDummy aDummy "draco" "draco/compression/decode.h" "draco" {"draco"}
|
||||
}
|
||||
if { "$::HAVE_BULLET" == "true" } {
|
||||
set aDummy {}
|
||||
wokdep:SearchStandardLibrary anIncErrs anLib32Errs anLib64Errs aDummy aDummy "bullet" "bullet/btBulletDynamicsCommon.h" "BulletDynamics" {"bullet"}
|
||||
set aHeaderPath1 [wokdep:SearchHeader "btBulletDynamicsCommon.h"]
|
||||
set aHeaderPath2 [wokdep:SearchHeader "bullet/btBulletDynamicsCommon.h"]
|
||||
if { "$aHeaderPath1" == "" && "$aHeaderPath2" != "" } {
|
||||
lappend ::CSF_OPT_INC [file dirname "$aHeaderPath2"]
|
||||
}
|
||||
}
|
||||
|
||||
if {"$::BUILD_Inspector" == "true" } {
|
||||
set ::CHECK_QT "true"
|
||||
@@ -465,6 +474,8 @@ checkbutton .myFrame.myChecks.myXLibCheck -offvalue "false" -onvalue "true
|
||||
ttk::label .myFrame.myChecks.myXLibLbl -text "Use X11 for windows drawing"
|
||||
ttk::label .myFrame.myChecks.myVtkLbl -text "Use VTK"
|
||||
checkbutton .myFrame.myChecks.myVtkCheck -offvalue "false" -onvalue "true" -variable HAVE_VTK -command wokdep:gui:UpdateList
|
||||
ttk::label .myFrame.myChecks.myBulletLbl -text "Use Bullet"
|
||||
checkbutton .myFrame.myChecks.myBulletCheck -offvalue "false" -onvalue "true" -variable HAVE_BULLET -command wokdep:gui:UpdateList
|
||||
|
||||
checkbutton .myFrame.myChecks.myZLibCheck -offvalue "false" -onvalue "true" -variable HAVE_ZLIB -command wokdep:gui:UpdateList
|
||||
ttk::label .myFrame.myChecks.myZLibLbl -text "Use zlib"
|
||||
@@ -655,8 +666,8 @@ grid .myFrame.myChecks.myJDKLbl -row $aCheckRowIter -column 13 -sticky w
|
||||
incr aCheckRowIter
|
||||
grid .myFrame.myChecks.myFFmpegCheck -row $aCheckRowIter -column 0 -sticky e
|
||||
grid .myFrame.myChecks.myFFmpegLbl -row $aCheckRowIter -column 1 -sticky w
|
||||
grid .myFrame.myChecks.myVtkCheck -row $aCheckRowIter -column 2 -sticky e
|
||||
grid .myFrame.myChecks.myVtkLbl -row $aCheckRowIter -column 3 -sticky w
|
||||
grid .myFrame.myChecks.myBulletCheck -row $aCheckRowIter -column 2 -sticky e
|
||||
grid .myFrame.myChecks.myBulletLbl -row $aCheckRowIter -column 3 -sticky w
|
||||
grid .myFrame.myChecks.myOpenVrCheck -row $aCheckRowIter -column 4 -sticky e
|
||||
grid .myFrame.myChecks.myOpenVrLbl -row $aCheckRowIter -column 5 -sticky w
|
||||
grid .myFrame.myChecks.myE57Check -row $aCheckRowIter -column 6 -sticky e
|
||||
@@ -669,6 +680,8 @@ if { "$::tcl_platform(platform)" == "windows" } {
|
||||
|
||||
incr aCheckRowIter
|
||||
|
||||
grid .myFrame.myChecks.myVtkCheck -row $aCheckRowIter -column 2 -sticky e
|
||||
grid .myFrame.myChecks.myVtkLbl -row $aCheckRowIter -column 3 -sticky w
|
||||
grid .myFrame.myChecks.myTbbCheck -row $aCheckRowIter -column 12 -sticky e
|
||||
grid .myFrame.myChecks.myTbbLbl -row $aCheckRowIter -column 13 -sticky w
|
||||
|
||||
|
@@ -73,7 +73,7 @@ if { [info exists ::env(SHORTCUT_HEADERS)] } {
|
||||
|
||||
# fetch environment variables (e.g. set by custom.sh or custom.bat) and set them as tcl variables with the same name
|
||||
set THE_ENV_VARIABLES { HAVE_TK HAVE_FREETYPE HAVE_FREEIMAGE HAVE_FFMPEG HAVE_TBB HAVE_GLES2 HAVE_D3D HAVE_VTK \
|
||||
HAVE_ZLIB HAVE_LIBLZMA HAVE_E57 HAVE_RAPIDJSON HAVE_DRACO HAVE_OPENVR HAVE_OPENCL \
|
||||
HAVE_ZLIB HAVE_LIBLZMA HAVE_E57 HAVE_RAPIDJSON HAVE_DRACO HAVE_OPENVR HAVE_BULLET HAVE_OPENCL \
|
||||
CHECK_QT4 CHECK_JDK HAVE_XLIB \
|
||||
HAVE_RelWithDebInfo BUILD_Inspector }
|
||||
foreach anEnvIter $THE_ENV_VARIABLES { set ${anEnvIter} "false" }
|
||||
|
@@ -1415,6 +1415,9 @@ proc osutils:csfList { theOS theCsfLibsMap theCsfFrmsMap theRelease} {
|
||||
if { "$::HAVE_FREETYPE" == "true" } {
|
||||
set aLibsMap(CSF_FREETYPE) "freetype"
|
||||
}
|
||||
if { "$::HAVE_BULLET" == "true" && "$theOS" != "wnt" } {
|
||||
set aLibsMap(CSF_BULLET) "BulletDynamics BulletCollision LinearMath"
|
||||
}
|
||||
set aLibsMap(CSF_TclLibs) "tcl8.6"
|
||||
if { "$::HAVE_TK" == "true" } {
|
||||
set aLibsMap(CSF_TclTkLibs) "tk8.6"
|
||||
|
@@ -29,6 +29,7 @@ set "HAVE_LIBLZMA=false"
|
||||
set "HAVE_RAPIDJSON=false"
|
||||
set "HAVE_DRACO=false"
|
||||
set "HAVE_OPENVR=false"
|
||||
set "HAVE_BULLET=false"
|
||||
set "HAVE_E57=false"
|
||||
set "CSF_OPT_INC="
|
||||
set "CSF_OPT_LIB32="
|
||||
@@ -205,6 +206,7 @@ if ["%HAVE_LIBLZMA%"] == ["true"] set "PRODUCTS_DEFINES=%PRODUCTS_DEFINES% -DH
|
||||
if ["%HAVE_RAPIDJSON%"] == ["true"] set "PRODUCTS_DEFINES=%PRODUCTS_DEFINES% -DHAVE_RAPIDJSON" & set "CSF_DEFINES=HAVE_RAPIDJSON;%CSF_DEFINES%"
|
||||
if ["%HAVE_DRACO%"] == ["true"] set "PRODUCTS_DEFINES=%PRODUCTS_DEFINES% -DHAVE_DRACO" & set "CSF_DEFINES=HAVE_DRACO;%CSF_DEFINES%"
|
||||
if ["%HAVE_OPENVR%"] == ["true"] set "PRODUCTS_DEFINES=%PRODUCTS_DEFINES% -DHAVE_OPENVR" & set "CSF_DEFINES=HAVE_OPENVR;%CSF_DEFINES%"
|
||||
if ["%HAVE_BULLET%"] == ["true"] set "PRODUCTS_DEFINES=%PRODUCTS_DEFINES% -DHAVE_BULLET" & set "CSF_DEFINES=HAVE_BULLET;%CSF_DEFINES%"
|
||||
if ["%HAVE_E57%"] == ["true"] set "PRODUCTS_DEFINES=%PRODUCTS_DEFINES% -DHAVE_E57" & set "CSF_DEFINES=HAVE_E57;%CSF_DEFINES%"
|
||||
|
||||
rem Eliminate VS warning
|
||||
|
@@ -22,6 +22,7 @@ export HAVE_LIBLZMA="false";
|
||||
export HAVE_RAPIDJSON="false";
|
||||
export HAVE_DRACO="false";
|
||||
export HAVE_OPENVR="false";
|
||||
export HAVE_BULLET="false";
|
||||
export HAVE_E57="false";
|
||||
export HAVE_XLIB="true";
|
||||
if [ "$aSystem" == "Darwin" ]; then
|
||||
@@ -104,7 +105,7 @@ fi
|
||||
|
||||
export CSF_OPT_CMPL=""
|
||||
|
||||
# Optiona 3rd-parties should be enabled by HAVE macros
|
||||
# Optional 3rd-parties should be enabled by HAVE macros
|
||||
if [ "$HAVE_TBB" == "true" ]; then export CSF_OPT_CMPL="${CSF_OPT_CMPL} -DHAVE_TBB"; fi
|
||||
if [ "$HAVE_OPENCL" == "true" ]; then export CSF_OPT_CMPL="${CSF_OPT_CMPL} -DHAVE_OPENCL"; fi
|
||||
if [ "$HAVE_TK" == "true" ]; then export CSF_OPT_CMPL="${CSF_OPT_CMPL} -DHAVE_TK"; fi
|
||||
@@ -118,6 +119,7 @@ if [ "$HAVE_LIBLZMA" == "true" ]; then export CSF_OPT_CMPL="${CSF_OPT_CMPL} -D
|
||||
if [ "$HAVE_RAPIDJSON" == "true" ]; then export CSF_OPT_CMPL="${CSF_OPT_CMPL} -DHAVE_RAPIDJSON"; fi
|
||||
if [ "$HAVE_DRACO" == "true" ]; then export CSF_OPT_CMPL="${CSF_OPT_CMPL} -DHAVE_DRACO"; fi
|
||||
if [ "$HAVE_OPENVR" == "true" ]; then export CSF_OPT_CMPL="${CSF_OPT_CMPL} -DHAVE_OPENVR"; fi
|
||||
if [ "$HAVE_BULLET" == "true" ]; then export CSF_OPT_CMPL="${CSF_OPT_CMPL} -DHAVE_BULLET"; fi
|
||||
if [ "$HAVE_E57" == "true" ]; then export CSF_OPT_CMPL="${CSF_OPT_CMPL} -DHAVE_E57"; fi
|
||||
if [ "$HAVE_XLIB" == "true" ]; then export CSF_OPT_CMPL="${CSF_OPT_CMPL} -DHAVE_XLIB"; fi
|
||||
|
||||
|
@@ -185,12 +185,16 @@ void WasmOcctView::initWindow()
|
||||
emscripten_set_resize_callback (EMSCRIPTEN_EVENT_TARGET_WINDOW, this, toUseCapture, onResizeCallback);
|
||||
|
||||
emscripten_set_mousedown_callback (aTargetId, this, toUseCapture, onMouseCallback);
|
||||
emscripten_set_mouseup_callback (aTargetId, this, toUseCapture, onMouseCallback);
|
||||
emscripten_set_mousemove_callback (aTargetId, this, toUseCapture, onMouseCallback);
|
||||
// bind these events to window to track mouse movements outside of canvas
|
||||
//emscripten_set_mouseup_callback (aTargetId, this, toUseCapture, onMouseCallback);
|
||||
//emscripten_set_mousemove_callback (aTargetId, this, toUseCapture, onMouseCallback);
|
||||
//emscripten_set_mouseleave_callback (aTargetId, this, toUseCapture, onMouseCallback);
|
||||
emscripten_set_mouseup_callback (EMSCRIPTEN_EVENT_TARGET_WINDOW, this, toUseCapture, onMouseCallback);
|
||||
emscripten_set_mousemove_callback (EMSCRIPTEN_EVENT_TARGET_WINDOW, this, toUseCapture, onMouseCallback);
|
||||
|
||||
emscripten_set_dblclick_callback (aTargetId, this, toUseCapture, onMouseCallback);
|
||||
emscripten_set_click_callback (aTargetId, this, toUseCapture, onMouseCallback);
|
||||
emscripten_set_mouseenter_callback (aTargetId, this, toUseCapture, onMouseCallback);
|
||||
emscripten_set_mouseleave_callback (aTargetId, this, toUseCapture, onMouseCallback);
|
||||
emscripten_set_wheel_callback (aTargetId, this, toUseCapture, onWheelCallback);
|
||||
|
||||
emscripten_set_touchstart_callback (aTargetId, this, toUseCapture, onTouchCallback);
|
||||
@@ -474,6 +478,21 @@ EM_BOOL WasmOcctView::onResizeEvent (int theEventType, const EmscriptenUiEvent*
|
||||
return EM_TRUE;
|
||||
}
|
||||
|
||||
//! Update canvas bounding rectangle.
|
||||
EM_JS(void, jsUpdateBoundingClientRect, (), {
|
||||
Module._myCanvasRect = Module.canvas.getBoundingClientRect();
|
||||
});
|
||||
|
||||
//! Get canvas bounding top.
|
||||
EM_JS(int, jsGetBoundingClientTop, (), {
|
||||
return Math.round(Module._myCanvasRect.top);
|
||||
});
|
||||
|
||||
//! Get canvas bounding left.
|
||||
EM_JS(int, jsGetBoundingClientLeft, (), {
|
||||
return Math.round(Module._myCanvasRect.left);
|
||||
});
|
||||
|
||||
// ================================================================
|
||||
// Function : onMouseEvent
|
||||
// Purpose :
|
||||
@@ -486,6 +505,17 @@ EM_BOOL WasmOcctView::onMouseEvent (int theEventType, const EmscriptenMouseEvent
|
||||
}
|
||||
|
||||
Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (myView->Window());
|
||||
if (theEventType == EMSCRIPTEN_EVENT_MOUSEMOVE
|
||||
|| theEventType == EMSCRIPTEN_EVENT_MOUSEUP)
|
||||
{
|
||||
// these events are bound to EMSCRIPTEN_EVENT_TARGET_WINDOW, and coordinates should be converted
|
||||
jsUpdateBoundingClientRect();
|
||||
EmscriptenMouseEvent anEvent = *theEvent;
|
||||
anEvent.targetX -= jsGetBoundingClientLeft();
|
||||
anEvent.targetY -= jsGetBoundingClientTop();
|
||||
return aWindow->ProcessMouseEvent (*this, theEventType, &anEvent) ? EM_TRUE : EM_FALSE;
|
||||
}
|
||||
|
||||
return aWindow->ProcessMouseEvent (*this, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
|
||||
}
|
||||
|
||||
|
@@ -60,6 +60,7 @@ CSF_OpenGlesLibs
|
||||
CSF_FFmpeg
|
||||
CSF_FreeImagePlus
|
||||
CSF_FREETYPE
|
||||
CSF_BULLET
|
||||
CSF_Draco
|
||||
CSF_user32
|
||||
CSF_advapi32
|
||||
|
@@ -394,6 +394,11 @@ static Standard_Integer dversion(Draw_Interpretor& di, Standard_Integer, const c
|
||||
#else
|
||||
di << "Draco disabled\n";
|
||||
#endif
|
||||
#ifdef HAVE_BULLET
|
||||
di << "Bullet Physics enabled (HAVE_BULLET)\n";
|
||||
#else
|
||||
di << "Bullet Physics disabled\n";
|
||||
#endif
|
||||
#ifdef HAVE_VTK
|
||||
di << "VTK enabled (HAVE_VTK)\n";
|
||||
#else
|
||||
|
389
src/Dynamics/Dynamics_Character.cxx
Normal file
389
src/Dynamics/Dynamics_Character.cxx
Normal file
@@ -0,0 +1,389 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_Character.hxx>
|
||||
|
||||
#include <Dynamics_CollisionShape.hxx>
|
||||
#include <Dynamics_Internal.hxx>
|
||||
#include <Dynamics_World.hxx>
|
||||
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_Character, Dynamics_CollisionBody)
|
||||
|
||||
namespace
|
||||
{
|
||||
static const double THE_GRAVITY_G = 9.8;
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
static const btScalar THE_TIME_PRECISION = 0.001f;
|
||||
static const double THE_DIST_PRECISION = 0.0001;
|
||||
|
||||
//! Character controller.
|
||||
ATTRIBUTE_ALIGNED16(class) Dynamics_CharacterController : public btKinematicCharacterController
|
||||
{
|
||||
public:
|
||||
|
||||
enum StableState
|
||||
{
|
||||
StableState_Reset,
|
||||
StableState_Stable,
|
||||
StableState_Stuck,
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
Dynamics_CharacterController (btPairCachingGhostObject* theGhostObject,
|
||||
btConvexShape* theConvexShape,
|
||||
btScalar theStepHeight,
|
||||
const btVector3& theUp)
|
||||
: btKinematicCharacterController (theGhostObject, theConvexShape, theStepHeight, theUp),
|
||||
myOldDirection (0.0f, 0.0f, 0.0f),
|
||||
myStableState (StableState_Reset)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
//! Setup distance tolerance.
|
||||
void setDistancePrecision (btScalar theDistancePrec)
|
||||
{
|
||||
myDistancePrec = theDistancePrec;
|
||||
}
|
||||
|
||||
//! Action interface.
|
||||
virtual void updateAction (btCollisionWorld* theCollisionWorld,
|
||||
btScalar theDeltaTimeStep) Standard_OVERRIDE
|
||||
{
|
||||
const bool isUpdateNeeded = !m_useWalkDirection && m_velocityTimeInterval > THE_TIME_PRECISION && m_walkDirection.length() > myDistancePrec;
|
||||
if (myStableState != StableState_Reset)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const btVector3 aLocBefore = m_ghostObject->getWorldTransform().getOrigin();
|
||||
btKinematicCharacterController::updateAction (theCollisionWorld, theDeltaTimeStep);
|
||||
|
||||
const btVector3 aLocAfter = m_ghostObject->getWorldTransform().getOrigin();
|
||||
const btVector3 aDelta = aLocAfter - aLocBefore;
|
||||
if (theDeltaTimeStep > THE_TIME_PRECISION)
|
||||
{
|
||||
if (aDelta.length() < myDistancePrec)
|
||||
{
|
||||
myStableState = isUpdateNeeded ? StableState_Stuck : StableState_Stable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Setup walking.
|
||||
virtual void setVelocityForTimeInterval (const btVector3& theVelocity, btScalar theTimeInterval) Standard_OVERRIDE
|
||||
{
|
||||
if (theVelocity.length() > myDistancePrec)
|
||||
{
|
||||
const btVector3 aNewDirection = theVelocity.normalized();
|
||||
const btScalar aDelta = (myOldDirection - aNewDirection).length();
|
||||
myOldDirection = aNewDirection;
|
||||
if (aDelta > myDistancePrec
|
||||
|| myStableState == StableState_Stable)
|
||||
{
|
||||
myStableState = StableState_Reset;
|
||||
}
|
||||
}
|
||||
|
||||
btKinematicCharacterController::setVelocityForTimeInterval (btVector3 (0.0f, 0.0f, 0.0f), 0.0f);
|
||||
btKinematicCharacterController::setVelocityForTimeInterval (theVelocity, theTimeInterval);
|
||||
}
|
||||
|
||||
//! Reset stable state.
|
||||
void ResetStable()
|
||||
{
|
||||
myStableState = StableState_Reset;
|
||||
btKinematicCharacterController::setVelocityForTimeInterval (btVector3 (0.0f, 0.0f, 0.0f), 0.0f);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
btVector3 myOldDirection;
|
||||
btScalar myDistancePrec;
|
||||
StableState myStableState;
|
||||
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_Character
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_Character::Dynamics_Character (double theHumanHeight)
|
||||
: myDefFallSpeed(0.0),
|
||||
myFallSpeed (0.0),
|
||||
myHumanHeight(1.0),
|
||||
myHumanWidth (1.0),
|
||||
myStepHeight (1.0),
|
||||
myRunRatio (3.0),
|
||||
myCrouchRatio(0.5),
|
||||
myCapsHalfHeight(1.0),
|
||||
myCapsMaxPenetr (0.1), // 0.2 is default
|
||||
myState (Dynamics_CharacterState_Stand)
|
||||
{
|
||||
Init (theHumanHeight);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Dynamics_Character
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_Character::~Dynamics_Character()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Init
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Character::Init (double theHumanHeight,
|
||||
double theHumanWidth,
|
||||
double theStepHeight)
|
||||
{
|
||||
myHumanHeight = theHumanHeight;
|
||||
myHumanWidth = theHumanWidth;
|
||||
myStepHeight = theStepHeight;
|
||||
init();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : init
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Character::init()
|
||||
{
|
||||
Dynamics_World* aWorld = myWorld;
|
||||
const double aLenScale = aWorld != nullptr ? aWorld->LengthUnitScale() : 1.0;
|
||||
|
||||
myVelocity.SetCoord (0.0, 0.0, 0.0);
|
||||
myGravity = myDefGravity = gp_Vec (0.0, 0.0, -THE_GRAVITY_G * 3.0 * aLenScale); // 3G acceleration
|
||||
myFallSpeed = myDefFallSpeed = 55.0 * aLenScale;
|
||||
#ifdef HAVE_BULLET
|
||||
double aHumanHeight = myHumanHeight;
|
||||
double aHumanWidth = myHumanWidth;
|
||||
double aStepHeight = myStepHeight;
|
||||
if (myState == Dynamics_CharacterState_Crouch)
|
||||
{
|
||||
aHumanHeight = myHumanHeight * 0.5;
|
||||
aStepHeight = myStepHeight * 0.5;
|
||||
}
|
||||
myCapsHalfHeight = aHumanHeight * 0.5;
|
||||
|
||||
btTransform aWorldLoc;
|
||||
aWorldLoc.setIdentity();
|
||||
if (myBody.get() != NULL)
|
||||
{
|
||||
aWorldLoc = myBody->getWorldTransform();
|
||||
}
|
||||
|
||||
myCapsMaxPenetr = 0.1 * aLenScale;
|
||||
if (aWorld != NULL)
|
||||
{
|
||||
removeFromWorld();
|
||||
}
|
||||
|
||||
if (!myCustomShape.IsNull())
|
||||
{
|
||||
const btConvexShape* aConvexShape = dynamic_cast<btConvexShape*> (myCustomShape->CollisionShape());
|
||||
if (aConvexShape == NULL)
|
||||
{
|
||||
throw Standard_ProgramError ("Dynamics_Character::init() - non-convex shape is set");
|
||||
}
|
||||
myShape = myCustomShape;
|
||||
}
|
||||
else
|
||||
{
|
||||
const double aCapsuleRadius = aHumanWidth * 0.5;
|
||||
const double aCapsuleHeight = aHumanHeight - 2.0 * aCapsuleRadius;
|
||||
|
||||
btCapsuleShapeZ* aCapsule = new btCapsuleShapeZ (btScalar(aCapsuleRadius), btScalar(aCapsuleHeight));
|
||||
myShape = new Dynamics_CollisionShape (aCapsule);
|
||||
}
|
||||
|
||||
btPairCachingGhostObject* aGhostObject = new btPairCachingGhostObject();
|
||||
aGhostObject->setWorldTransform (aWorldLoc);
|
||||
aGhostObject->setCollisionShape (myShape->CollisionShape());
|
||||
aGhostObject->setCollisionFlags (btCollisionObject::CF_CHARACTER_OBJECT);
|
||||
myBody.reset (aGhostObject);
|
||||
btConvexShape* aConvexShape = dynamic_cast<btConvexShape*> (myShape->CollisionShape());
|
||||
Dynamics_CharacterController* aCharacter = new Dynamics_CharacterController (aGhostObject, aConvexShape, btScalar (aStepHeight), btVector3 (0.0f, 0.0f, 1.0f));
|
||||
aCharacter->setDistancePrecision (btScalar(THE_DIST_PRECISION * aLenScale));
|
||||
aCharacter->setMaxPenetrationDepth (btScalar(myCapsMaxPenetr));
|
||||
aCharacter->setFallSpeed (btScalar(55.0 * aLenScale)); // terminal velocity of a sky diver in m/s
|
||||
aCharacter->setJumpSpeed (btScalar(10.0 * aLenScale));
|
||||
myAction.reset (aCharacter);
|
||||
SetGravity (myDefGravity);
|
||||
SetFallSpeed (myDefFallSpeed);
|
||||
if (aWorld != NULL)
|
||||
{
|
||||
addToWorld (aWorld);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : addToWorld
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Character::SetCustomConvexShape (const Handle(Dynamics_CollisionShape)& theShape)
|
||||
{
|
||||
myCustomShape = theShape;
|
||||
if (!myCustomShape.IsNull())
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
const btConvexShape* aConvexShape = dynamic_cast<const btConvexShape*> (myCustomShape->CollisionShape());
|
||||
if (aConvexShape == NULL)
|
||||
{
|
||||
throw Standard_ProgramError ("Dynamics_Character::SetCustomConvexShape() - non-convex shape is set");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : addToWorld
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Character::addToWorld (Dynamics_World* theWorld)
|
||||
{
|
||||
removeFromWorld();
|
||||
#ifdef HAVE_BULLET
|
||||
myWorld = theWorld;
|
||||
if (myWorld != NULL && myBody.get() != NULL)
|
||||
{
|
||||
btDiscreteDynamicsWorld* aWorld = myWorld->myDynamicsWorld.get();
|
||||
aWorld->addCollisionObject (myBody.get(), btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter);
|
||||
aWorld->addAction (myAction.get());
|
||||
}
|
||||
#else
|
||||
(void )theWorld;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetEyePosition
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Character::SetEyePosition (const gp_Pnt& theEyePosition,
|
||||
const Bnd_Box& theSceneBndBox)
|
||||
{
|
||||
myVelocity.SetCoord (0.0, 0.0, 0.0);
|
||||
const double aShift = myCapsHalfHeight + myCapsMaxPenetr * 0.5 - myHumanHeight * ProportionalHumanEyeShift();
|
||||
gp_XYZ aPos (theEyePosition.XYZ());
|
||||
aPos.SetZ (theEyePosition.Z() - aShift);
|
||||
if (!theSceneBndBox.IsVoid())
|
||||
{
|
||||
aPos.SetZ (Max (aPos.Z(), theSceneBndBox.CornerMin().Z()));
|
||||
}
|
||||
SetWorldPosition (aPos);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetWorldPosition
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Character::SetWorldPosition (const gp_Pnt& thePosition)
|
||||
{
|
||||
myVelocity.SetCoord (0.0, 0.0, 0.0);
|
||||
#ifdef HAVE_BULLET
|
||||
Dynamics_CharacterController* aCharacter = dynamic_cast<Dynamics_CharacterController* >(myAction.get());
|
||||
aCharacter->ResetStable();
|
||||
|
||||
btPairCachingGhostObject* aGhostObject = dynamic_cast<btPairCachingGhostObject* >(myBody.get());
|
||||
btTransform aStartTrsf;
|
||||
aStartTrsf.setIdentity();
|
||||
aStartTrsf.setOrigin (btVector3 (btScalar (thePosition.X()), btScalar(thePosition.Y()), btScalar(thePosition.Z())));
|
||||
aGhostObject->setWorldTransform (aStartTrsf);
|
||||
#else
|
||||
(void )thePosition;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetGravity
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Character::SetGravity (const gp_Vec& theGravity)
|
||||
{
|
||||
myGravity = theGravity;
|
||||
#ifdef HAVE_BULLET
|
||||
Dynamics_CharacterController* aCharacter = dynamic_cast<Dynamics_CharacterController* >(myAction.get());
|
||||
aCharacter->setGravity (btVector3 (btScalar(theGravity.X()), btScalar(theGravity.Y()), btScalar(theGravity.Z())));
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetFallSpeed
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Character::SetFallSpeed (double theSpeed)
|
||||
{
|
||||
myFallSpeed = theSpeed;
|
||||
#ifdef HAVE_BULLET
|
||||
Dynamics_CharacterController* aCharacter = dynamic_cast<Dynamics_CharacterController* >(myAction.get());
|
||||
aCharacter->setFallSpeed (btScalar(theSpeed));
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Walk
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Character::Walk (const gp_Vec& theMoveVec)
|
||||
{
|
||||
myVelocity.SetCoord (0.0, 0.0, 0.0);
|
||||
#ifdef HAVE_BULLET
|
||||
Dynamics_CharacterController* aCharacter = dynamic_cast<Dynamics_CharacterController* >(myAction.get());
|
||||
aCharacter->setWalkDirection (btVector3 (btScalar(theMoveVec.X()), btScalar(theMoveVec.Y()), btScalar(theMoveVec.Z())));
|
||||
#else
|
||||
(void )theMoveVec;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Walk
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Character::Walk (const gp_Vec& theSpeedVec,
|
||||
const double theDurationSec)
|
||||
{
|
||||
myVelocity = theSpeedVec;
|
||||
#ifdef HAVE_BULLET
|
||||
Dynamics_CharacterController* aCharacter = dynamic_cast<Dynamics_CharacterController* >(myAction.get());
|
||||
aCharacter->setVelocityForTimeInterval (btVector3 (btScalar(theSpeedVec.X()), btScalar(theSpeedVec.Y()), btScalar(theSpeedVec.Z())), btScalar(theDurationSec));
|
||||
#else
|
||||
(void )theDurationSec;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Jump
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Character::Jump()
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
Dynamics_CharacterController* aCharacter = dynamic_cast<Dynamics_CharacterController* >(myAction.get());
|
||||
aCharacter->ResetStable();
|
||||
aCharacter->jump (btVector3 (0, 0, 0));
|
||||
#endif
|
||||
}
|
218
src/Dynamics/Dynamics_Character.hxx
Normal file
218
src/Dynamics/Dynamics_Character.hxx
Normal file
@@ -0,0 +1,218 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_Character_HeaderFile
|
||||
#define _Dynamics_Character_HeaderFile
|
||||
|
||||
#include <Dynamics_CollisionBody.hxx>
|
||||
#include <Dynamics_CharacterState.hxx>
|
||||
|
||||
class Bnd_Box;
|
||||
class gp_Vec;
|
||||
|
||||
//! Class defining character object.
|
||||
class Dynamics_Character : public Dynamics_CollisionBody
|
||||
{
|
||||
friend class Dynamics_World;
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_Character, Dynamics_CollisionBody)
|
||||
public:
|
||||
|
||||
//! Return the average human height.
|
||||
static double AverageHumanHeight() { return 1.75; }
|
||||
|
||||
//! Compute human width from the human height using average proportions.
|
||||
static double ProportionalHumanWidth (double theHumanHeight) { return theHumanHeight * 0.265; }
|
||||
|
||||
//! Compute human step height from the human height using average proportions.
|
||||
static double ProportionalHumanStepHeight (double theHumanHeight) { return theHumanHeight * 0.2; }
|
||||
|
||||
//! Return the average human eye level shift (EyeLevel = Height - EyeShift), ~1/16.
|
||||
static double ProportionalHumanEyeShift() { return 0.0625; }
|
||||
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
Standard_EXPORT Dynamics_Character (double theHumanHeight = 1.75);
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Dynamics_Character();
|
||||
|
||||
//! Initialize the character using average proportions for specified human height.
|
||||
void Init (double theHumanHeight)
|
||||
{
|
||||
Init (theHumanHeight, ProportionalHumanWidth (theHumanHeight), ProportionalHumanStepHeight (theHumanHeight));
|
||||
}
|
||||
|
||||
//! Initialize the character.
|
||||
Standard_EXPORT void Init (double theHumanHeight,
|
||||
double theHumanWidth,
|
||||
double theStepHeight);
|
||||
|
||||
//! Setup custom convex shape instead of capsule.
|
||||
Standard_EXPORT void SetCustomConvexShape (const Handle(Dynamics_CollisionShape)& theShape);
|
||||
|
||||
//! Wrap to specified position.
|
||||
Standard_EXPORT void SetEyePosition (const gp_Pnt& theEyePosition,
|
||||
const Bnd_Box& theSceneBndBox);
|
||||
|
||||
//! Return the eye location.
|
||||
gp_Pnt EyePosition() const
|
||||
{
|
||||
const double aShift = myCapsHalfHeight + myCapsMaxPenetr * 0.5 - myHumanHeight * ProportionalHumanEyeShift();
|
||||
const gp_Pnt aPos = WorldPosition();
|
||||
return gp_Pnt (aPos.X(), aPos.Y(), aPos.Z() + aShift);
|
||||
}
|
||||
|
||||
//! Wrap to specified position.
|
||||
Standard_EXPORT void SetWorldPosition (const gp_Pnt& thePosition);
|
||||
|
||||
//! Return the ground location.
|
||||
gp_Pnt GroundPosition() const
|
||||
{
|
||||
const double aShift = -myCapsHalfHeight + myCapsMaxPenetr * 0.5;
|
||||
const gp_Pnt aPos = WorldPosition();
|
||||
return gp_Pnt (aPos.X(), aPos.Y(), aPos.Z() + aShift);
|
||||
}
|
||||
|
||||
//! Return the default gravity vector.
|
||||
const gp_Vec& DefaultGravity() const { return myDefGravity; }
|
||||
|
||||
//! Return the gravity vector.
|
||||
const gp_Vec& Gravity() const { return myGravity; }
|
||||
|
||||
//! Setup new gravity.
|
||||
Standard_EXPORT void SetGravity (const gp_Vec& theGravity);
|
||||
|
||||
//! Return the default fall speed limit.
|
||||
double DefaultFallSpeed() const { return myDefFallSpeed; }
|
||||
|
||||
//! Return the fall speed limit.
|
||||
double FallSpeed() const { return myFallSpeed; }
|
||||
|
||||
//! Setup fall speed limit.
|
||||
Standard_EXPORT void SetFallSpeed (double theSpeed);
|
||||
|
||||
//! Walk in specified direction and delta.
|
||||
Standard_EXPORT void Walk (const gp_Vec& theMoveVec);
|
||||
|
||||
//! Walk in specified direction and delta.
|
||||
Standard_EXPORT void Walk (const gp_Vec& theSpeedVec,
|
||||
const double theDurationSec);
|
||||
|
||||
//! Jump impulse.
|
||||
Standard_EXPORT void Jump();
|
||||
|
||||
//! Return current state.
|
||||
Dynamics_CharacterState State() const { return myState; }
|
||||
|
||||
//! Return current state.
|
||||
void SetState (Dynamics_CharacterState theState)
|
||||
{
|
||||
if (myState == theState)
|
||||
{
|
||||
return;
|
||||
}
|
||||
myState = theState;
|
||||
init();
|
||||
}
|
||||
|
||||
//! Return character height.
|
||||
double EyeLevel() const
|
||||
{
|
||||
double aHumanHeight = myHumanHeight;
|
||||
if (myState == Dynamics_CharacterState_Crouch)
|
||||
{
|
||||
aHumanHeight = myHumanHeight * 0.5;
|
||||
}
|
||||
return aHumanHeight - myHumanHeight * ProportionalHumanEyeShift();
|
||||
}
|
||||
|
||||
//! Return character height.
|
||||
double Height() const { return myHumanHeight; }
|
||||
|
||||
//! Return character width.
|
||||
double Width() const { return myHumanWidth; }
|
||||
|
||||
//! Return character step height.
|
||||
double StepHeight() const { return myStepHeight; }
|
||||
|
||||
//! Running speed ratio (relative to normal walk), 3 by default.
|
||||
double RunRatio() const { return myRunRatio; }
|
||||
|
||||
//! Setup running speed ratio.
|
||||
void SetRunRatio (double theRatio) { myRunRatio = theRatio; }
|
||||
|
||||
//! Crouching speed ratio (relative to normal walk), 0.5 by default.
|
||||
double CrouchRatio() const { return myCrouchRatio; }
|
||||
|
||||
//! Crouching running speed ratio.
|
||||
void SetCrouchRatio (double theRatio) { myCrouchRatio = theRatio; }
|
||||
|
||||
//! Return walking velocity.
|
||||
const gp_Vec& Velocity() const { return myVelocity; }
|
||||
|
||||
//! Return capsule half height (offset from the local CS).
|
||||
double CapsuleHalfHeight() const { return myCapsHalfHeight; }
|
||||
|
||||
//! Return allowed penetration.
|
||||
double CapsuleMaxPenetration() const { return myCapsMaxPenetr; }
|
||||
|
||||
//! Return TRUE if character is added to the World.
|
||||
bool IsActive() const { return myWorld != nullptr; }
|
||||
|
||||
//! Add/remove character to/from the World.
|
||||
void SetActive (Dynamics_World* theWorld)
|
||||
{
|
||||
if (myWorld == theWorld)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (theWorld != nullptr)
|
||||
{
|
||||
addToWorld (theWorld);
|
||||
init();
|
||||
}
|
||||
else
|
||||
{
|
||||
removeFromWorld();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! Add body to the world.
|
||||
Standard_EXPORT virtual void addToWorld (Dynamics_World* theWorld) Standard_OVERRIDE;
|
||||
|
||||
//! Initialize the character.
|
||||
Standard_EXPORT void init();
|
||||
|
||||
protected:
|
||||
|
||||
Handle(Dynamics_CollisionShape) myCustomShape;
|
||||
gp_Vec myVelocity;
|
||||
gp_Vec myDefGravity; //!< default gravity
|
||||
gp_Vec myGravity; //!< current gravity
|
||||
Standard_Real myDefFallSpeed; //!< default maximum fall speed
|
||||
Standard_Real myFallSpeed; //!< maximum fall speed
|
||||
Standard_Real myHumanHeight; //!< character height
|
||||
Standard_Real myHumanWidth; //!< character width
|
||||
Standard_Real myStepHeight; //!< step height
|
||||
Standard_Real myRunRatio; //!< running speed ratio (relative to normal walk)
|
||||
Standard_Real myCrouchRatio; //!< crouching speed ratio (relative to normal walk)
|
||||
Standard_Real myCapsHalfHeight; //!< capsule half height (offset from the local CS)
|
||||
Standard_Real myCapsMaxPenetr; //!< allowed penetration
|
||||
Dynamics_CharacterState myState; //!< current character state
|
||||
|
||||
};
|
||||
|
||||
#endif // _Dynamics_Character_HeaderFile
|
24
src/Dynamics/Dynamics_CharacterState.hxx
Normal file
24
src/Dynamics/Dynamics_CharacterState.hxx
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_CharacterState_HeaderFile
|
||||
#define _Dynamics_CharacterState_HeaderFile
|
||||
|
||||
//! Character state.
|
||||
enum Dynamics_CharacterState
|
||||
{
|
||||
Dynamics_CharacterState_Stand,
|
||||
Dynamics_CharacterState_Crouch,
|
||||
};
|
||||
|
||||
#endif // _Dynamics_CharacterState_HeaderFile
|
30
src/Dynamics/Dynamics_CollisionBRepFlags.hxx
Normal file
30
src/Dynamics/Dynamics_CollisionBRepFlags.hxx
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_CollisionBRepFlags_HeaderFile
|
||||
#define _Dynamics_CollisionBRepFlags_HeaderFile
|
||||
|
||||
//! Dynamics_CollisionBRepShape initialization parameters.
|
||||
enum Dynamics_CollisionBRepFlags
|
||||
{
|
||||
Dynamics_CollisionBRepFlags_NONE = 0x00,
|
||||
Dynamics_CollisionBRepFlags_Convex = 0x02,
|
||||
Dynamics_CollisionBRepFlags_Single = 0x04,
|
||||
Dynamics_CollisionBRepFlags_Compressed = 0x08,
|
||||
Dynamics_CollisionBRepFlags_BuildBVH = 0x10,
|
||||
|
||||
Dynamics_CollisionBRepFlags_DEFAULTS = Dynamics_CollisionBRepFlags_Compressed | Dynamics_CollisionBRepFlags_BuildBVH,
|
||||
Dynamics_CollisionBRepFlags_CONVEX_DEFAULTS = Dynamics_CollisionBRepFlags_DEFAULTS | Dynamics_CollisionBRepFlags_Single | Dynamics_CollisionBRepFlags_Convex,
|
||||
};
|
||||
|
||||
#endif // _Dynamics_CollisionBRepFlags_HeaderFile
|
237
src/Dynamics/Dynamics_CollisionBRepShape.cxx
Normal file
237
src/Dynamics/Dynamics_CollisionBRepShape.cxx
Normal file
@@ -0,0 +1,237 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_CollisionBRepShape.hxx>
|
||||
|
||||
#include <Dynamics_CollisionBRepShapeConvex.hxx>
|
||||
#include <Dynamics_CollisionBody.hxx>
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
#include <Dynamics_Graphic3dTriangulation.hxx>
|
||||
#include <Dynamics_PolyTriangulation.hxx>
|
||||
#include <Dynamics_MotionState.hxx>
|
||||
#endif
|
||||
|
||||
#include <BRep_Tool.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Face.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopLoc_Location.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_CollisionBRepShape, Dynamics_CollisionShape)
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_CollisionBRepShapeConvex, Dynamics_CollisionBRepShape)
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
//! Wrapper over btCompoundShape with destructor deleting child shapes.
|
||||
ATTRIBUTE_ALIGNED16(class) Dynamics_CompoundShape : public btCompoundShape
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
Dynamics_CompoundShape (bool theToEnableDynamicAabbTree = true, const int theInitialChildCapacity = 0)
|
||||
: btCompoundShape (theToEnableDynamicAabbTree, theInitialChildCapacity) {}
|
||||
|
||||
//! Destructor.
|
||||
virtual ~Dynamics_CompoundShape()
|
||||
{
|
||||
for (int aChildIter = 0; aChildIter < getNumChildShapes(); ++aChildIter)
|
||||
{
|
||||
btCollisionShape* aShape = getChildShape (aChildIter);
|
||||
delete aShape;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//! Wrapper over btBvhTriangleMeshShape with destructor deleting Mesh Interface.
|
||||
ATTRIBUTE_ALIGNED16(class) Dynamics_BvhTriangleMeshShape : public btBvhTriangleMeshShape
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
Dynamics_BvhTriangleMeshShape (btStridingMeshInterface* theMeshInterface,
|
||||
bool theToUseQuantizedAabbCompression,
|
||||
bool theToBuildBvh = true)
|
||||
: btBvhTriangleMeshShape (theMeshInterface, theToUseQuantizedAabbCompression, theToBuildBvh) {}
|
||||
|
||||
//! Destructor.
|
||||
virtual ~Dynamics_BvhTriangleMeshShape()
|
||||
{
|
||||
delete m_meshInterface;
|
||||
m_meshInterface = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
//! Wrapper over btConvexTriangleMeshShape with destructor deleting Mesh Interface.
|
||||
ATTRIBUTE_ALIGNED16(class) Dynamics_ConvexTriangleMeshShape : public btConvexTriangleMeshShape
|
||||
{
|
||||
public:
|
||||
//! Constructor.
|
||||
Dynamics_ConvexTriangleMeshShape (btStridingMeshInterface* theMeshInterface,
|
||||
bool theToBuildBvh = true)
|
||||
: btConvexTriangleMeshShape (theMeshInterface, theToBuildBvh) {}
|
||||
|
||||
//! Destructor.
|
||||
virtual ~Dynamics_ConvexTriangleMeshShape()
|
||||
{
|
||||
btStridingMeshInterface* aMeshInterface = getMeshInterface();
|
||||
delete aMeshInterface;
|
||||
}
|
||||
};
|
||||
|
||||
//! Wrap triangulation into mesh interface.
|
||||
btStridingMeshInterface* wrapTriangulation (const Handle(Poly_Triangulation)& thePolyTri)
|
||||
{
|
||||
if (!thePolyTri.IsNull())
|
||||
{
|
||||
return new Dynamics_PolyTriangulation (thePolyTri);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Init
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Dynamics_CollisionBRepShape::Init (const TopoDS_Shape& theShape,
|
||||
Dynamics_CollisionBRepFlags theFlags)
|
||||
{
|
||||
releaseShape();
|
||||
if (theShape.IsNull())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
const bool toUseCompression = (theFlags & Dynamics_CollisionBRepFlags_Compressed) != 0;
|
||||
const bool toBuildBvh = (theFlags & Dynamics_CollisionBRepFlags_BuildBVH) != 0;
|
||||
const bool isConvex = (theFlags & Dynamics_CollisionBRepFlags_Convex) != 0;
|
||||
|
||||
TopLoc_Location aLoc;
|
||||
btTransform aTrsfBtLocal;
|
||||
aTrsfBtLocal.setIdentity();
|
||||
if ((theFlags & Dynamics_CollisionBRepFlags_Single) != 0)
|
||||
{
|
||||
int aNbNodes = 0, aNbTris = 0;
|
||||
for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
|
||||
{
|
||||
const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
|
||||
const Handle(Poly_Triangulation)& aPolyTri = BRep_Tool::Triangulation (aFace, aLoc);
|
||||
if (!aPolyTri.IsNull())
|
||||
{
|
||||
aNbNodes += aPolyTri->NbNodes();
|
||||
aNbTris += aPolyTri->NbTriangles();
|
||||
}
|
||||
}
|
||||
if (aNbNodes < 3
|
||||
|| aNbTris < 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
btConvexHullShape aConvexHullShape;
|
||||
aConvexHullShape.setMargin (0); // this is to compensate for a bug in bullet
|
||||
|
||||
Handle(Graphic3d_ArrayOfTriangles) aTriangles;
|
||||
if (!isConvex)
|
||||
{
|
||||
aTriangles = new Graphic3d_ArrayOfTriangles (aNbNodes, aNbTris * 3, false, false, false);
|
||||
}
|
||||
for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
|
||||
{
|
||||
const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
|
||||
const Handle(Poly_Triangulation)& aPolyTri = BRep_Tool::Triangulation (aFace, aLoc);
|
||||
const gp_Trsf aTrsf = aLoc;
|
||||
if (!aPolyTri.IsNull())
|
||||
{
|
||||
const int aFirstNode = !aTriangles.IsNull() ? aTriangles->VertexNumber() : 0;
|
||||
for (int aNodeIter = 1; aNodeIter <= aPolyTri->NbNodes(); ++aNodeIter)
|
||||
{
|
||||
gp_Pnt aNode = aPolyTri->Node (aNodeIter);
|
||||
aNode.Transform (aTrsf);
|
||||
if (!aTriangles.IsNull())
|
||||
{
|
||||
aTriangles->AddVertex (aNode);
|
||||
}
|
||||
else
|
||||
{
|
||||
aConvexHullShape.addPoint (btVector3 (btScalar (aNode.X()), btScalar (aNode.Y()), btScalar (aNode.Z())), false);
|
||||
}
|
||||
}
|
||||
if (!aTriangles.IsNull())
|
||||
{
|
||||
Graphic3d_Vec4i anElem (-1, -1, -1, -1);
|
||||
for (int aTriIter = 1; aTriIter <= aPolyTri->NbTriangles(); ++aTriIter)
|
||||
{
|
||||
aPolyTri->Triangle (aTriIter).Get (anElem[0], anElem[1], anElem[2]);
|
||||
aTriangles->AddEdges (aFirstNode + anElem[0], aFirstNode + anElem[1], aFirstNode + anElem[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isConvex)
|
||||
{
|
||||
// create a hull approximation
|
||||
//btConvexHullShape aConvexHullShape ((const btScalar* )aTriangles->Attributes()->Data(), aNbNodes, aTriangles->Attributes()->Stride);
|
||||
aConvexHullShape.recalcLocalAabb();
|
||||
|
||||
btShapeHull aHull (&aConvexHullShape);
|
||||
aHull.buildHull (0);
|
||||
if (aHull.numVertices() == 0)
|
||||
{
|
||||
Message::SendTrace ("Dynamics_CollisionBRepShape, btShapeHull returned an empty result");
|
||||
return false;
|
||||
}
|
||||
myShape = new btConvexHullShape ((const btScalar* )aHull.getVertexPointer(), aHull.numVertices(), sizeof(btVector3));
|
||||
}
|
||||
else
|
||||
{
|
||||
btStridingMeshInterface* aMeshInterface = new Dynamics_Graphic3dTriangulation (aTriangles);
|
||||
myShape = new Dynamics_BvhTriangleMeshShape (aMeshInterface, toUseCompression, toBuildBvh);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Dynamics_CompoundShape* aCompShape = new Dynamics_CompoundShape();
|
||||
myShape = aCompShape;
|
||||
for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next())
|
||||
{
|
||||
const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current());
|
||||
const Handle(Poly_Triangulation)& aPolyTri = BRep_Tool::Triangulation (aFace, aLoc);
|
||||
if (btStridingMeshInterface* aChild = wrapTriangulation (aPolyTri))
|
||||
{
|
||||
Dynamics_MotionState::TrsfBtFromGp (aTrsfBtLocal, aLoc.Transformation());
|
||||
if (isConvex)
|
||||
{
|
||||
aCompShape->addChildShape (aTrsfBtLocal, new Dynamics_ConvexTriangleMeshShape (aChild, toBuildBvh));
|
||||
}
|
||||
else
|
||||
{
|
||||
aCompShape->addChildShape (aTrsfBtLocal, new Dynamics_BvhTriangleMeshShape (aChild, toUseCompression, toBuildBvh));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aCompShape->getNumChildShapes() == 0)
|
||||
{
|
||||
releaseShape();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
(void )theFlags;
|
||||
return false;
|
||||
#endif
|
||||
}
|
41
src/Dynamics/Dynamics_CollisionBRepShape.hxx
Normal file
41
src/Dynamics/Dynamics_CollisionBRepShape.hxx
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_CollisionBRepShape_HeaderFile
|
||||
#define _Dynamics_CollisionBRepShape_HeaderFile
|
||||
|
||||
#include <Dynamics_CollisionShape.hxx>
|
||||
#include <Dynamics_CollisionBRepFlags.hxx>
|
||||
|
||||
class TopoDS_Shape;
|
||||
|
||||
//! Define the collision body from triangulation data.
|
||||
class Dynamics_CollisionBRepShape : public Dynamics_CollisionShape
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_CollisionBRepShape, Dynamics_CollisionShape)
|
||||
public:
|
||||
|
||||
//! Constructor.
|
||||
Dynamics_CollisionBRepShape (const TopoDS_Shape& theShape,
|
||||
Dynamics_CollisionBRepFlags theFlags = Dynamics_CollisionBRepFlags_DEFAULTS)
|
||||
{
|
||||
Init (theShape, theFlags);
|
||||
}
|
||||
|
||||
//! Initialize from triangulation.
|
||||
Standard_EXPORT bool Init (const TopoDS_Shape& theShape,
|
||||
Dynamics_CollisionBRepFlags theFlags);
|
||||
|
||||
};
|
||||
|
||||
#endif // _Dynamics_CollisionBRepShape_HeaderFile
|
38
src/Dynamics/Dynamics_CollisionBRepShapeConvex.hxx
Normal file
38
src/Dynamics/Dynamics_CollisionBRepShapeConvex.hxx
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_CollisionBRepShapeConvex_HeaderFile
|
||||
#define _Dynamics_CollisionBRepShapeConvex_HeaderFile
|
||||
|
||||
#include <Dynamics_CollisionBRepShape.hxx>
|
||||
|
||||
//! Define the collision body from triangulation data (convex).
|
||||
class Dynamics_CollisionBRepShapeConvex : public Dynamics_CollisionBRepShape
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_CollisionBRepShapeConvex, Dynamics_CollisionBRepShape)
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
Dynamics_CollisionBRepShapeConvex (const TopoDS_Shape& theShape,
|
||||
const gp_Trsf& theTrsf,
|
||||
Dynamics_CollisionBRepFlags theFlags = Dynamics_CollisionBRepFlags_CONVEX_DEFAULTS)
|
||||
: Dynamics_CollisionBRepShape (theShape, theFlags), myLocation (theTrsf) {}
|
||||
|
||||
//! Return location.
|
||||
virtual const gp_Trsf& Location() const Standard_OVERRIDE { return myLocation; }
|
||||
|
||||
protected:
|
||||
gp_Trsf myLocation;
|
||||
};
|
||||
|
||||
#endif // _Dynamics_CollisionBRepShapeConvex_HeaderFile
|
453
src/Dynamics/Dynamics_CollisionBody.cxx
Normal file
453
src/Dynamics/Dynamics_CollisionBody.cxx
Normal file
@@ -0,0 +1,453 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_CollisionBody.hxx>
|
||||
|
||||
#include <Dynamics_Internal.hxx>
|
||||
#include <Dynamics_CollisionShape.hxx>
|
||||
#include <Dynamics_Constraint.hxx>
|
||||
#include <Dynamics_MotionState.hxx>
|
||||
#include <Dynamics_World.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
static btVector3 gpXyz2Vec3Bt (const gp_XYZ& theXYZ)
|
||||
{
|
||||
return btVector3 (btScalar(theXYZ.X()), btScalar(theXYZ.Y()), btScalar(theXYZ.Z()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_CollisionBody, Standard_Transient)
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_CollisionBody
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_CollisionBody::Dynamics_CollisionBody()
|
||||
: myWorld (NULL)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_CollisionBody
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_CollisionBody::Dynamics_CollisionBody (const Handle(Dynamics_CollisionShape)& theShape)
|
||||
: myWorld(NULL)
|
||||
{
|
||||
SetShape (theShape);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Dynamics_CollisionBody
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_CollisionBody::~Dynamics_CollisionBody()
|
||||
{
|
||||
clearMain();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetShape
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::SetShape (const Handle(Dynamics_CollisionShape)& theShape,
|
||||
const gp_Trsf& theTrsf)
|
||||
{
|
||||
myShape = theShape;
|
||||
myMotionState.Nullify();
|
||||
#ifdef HAVE_BULLET
|
||||
|
||||
// btCollisionObject cannot hold NULL collision shape (no NULL check in Bullet),
|
||||
// so remove object from the world, by keep reference for another ::SetShape() call
|
||||
bool toRemoveOld = myShape.IsNull(), toAdd = false;
|
||||
if (btRigidBody* aRigidBody = myBody.get() != NULL ? btRigidBody::upcast (myBody.get()) : NULL)
|
||||
{
|
||||
(void )aRigidBody;
|
||||
toRemoveOld = true;
|
||||
}
|
||||
if (toRemoveOld)
|
||||
{
|
||||
if (!myConstraint.IsNull())
|
||||
{
|
||||
if (myConstraint->DynamicsWorld() != nullptr)
|
||||
{
|
||||
myConstraint->DynamicsWorld()->RemoveConstraint (myConstraint);
|
||||
}
|
||||
myConstraint.Nullify();
|
||||
}
|
||||
|
||||
Dynamics_World* aWorld = myWorld;
|
||||
removeFromWorld();
|
||||
myWorld = aWorld;
|
||||
myBody.reset();
|
||||
}
|
||||
if (myShape.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (myBody.get() == NULL)
|
||||
{
|
||||
toAdd = true;
|
||||
myBody.reset (new btCollisionObject());
|
||||
myBody->setCollisionFlags (myBody->getCollisionFlags() | btCollisionObject::CF_DISABLE_VISUALIZE_OBJECT);
|
||||
}
|
||||
|
||||
btTransform aTrsfBt;
|
||||
Dynamics_MotionState::TrsfBtFromGp (aTrsfBt, theTrsf);
|
||||
|
||||
myBody->setCollisionShape (myShape->CollisionShape());
|
||||
myBody->setWorldTransform (aTrsfBt);
|
||||
if (toAdd && myWorld != NULL)
|
||||
{
|
||||
addToWorld (myWorld);
|
||||
}
|
||||
#else
|
||||
(void )theTrsf;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetShape
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::SetShape (const Handle(Dynamics_CollisionShape)& theShape,
|
||||
const Handle(Dynamics_MotionState)& theMotionState,
|
||||
const float theMass)
|
||||
{
|
||||
myShape = theShape;
|
||||
myMotionState = theMotionState;
|
||||
#ifdef HAVE_BULLET
|
||||
bool toAdd = false, toRemoveOld = true;
|
||||
if (toRemoveOld)
|
||||
{
|
||||
if (!myConstraint.IsNull())
|
||||
{
|
||||
if (myConstraint->DynamicsWorld() != nullptr)
|
||||
{
|
||||
myConstraint->DynamicsWorld()->RemoveConstraint (myConstraint);
|
||||
}
|
||||
myConstraint.Nullify();
|
||||
}
|
||||
|
||||
Dynamics_World* aWorld = myWorld;
|
||||
removeFromWorld();
|
||||
myWorld = aWorld;
|
||||
myBody.reset();
|
||||
}
|
||||
|
||||
if (myBody.get() == NULL)
|
||||
{
|
||||
toAdd = true;
|
||||
btVector3 aLocalInertia (0.0f, 0.0f, 0.0f);
|
||||
myShape->CollisionShape()->calculateLocalInertia (theMass, aLocalInertia);
|
||||
|
||||
btRigidBody::btRigidBodyConstructionInfo aBodyInfo (theMass, myMotionState->MotionState(), myShape->CollisionShape(), aLocalInertia);
|
||||
myBody.reset (new btRigidBody (aBodyInfo));
|
||||
|
||||
|
||||
myBody->setFriction (1.0f);
|
||||
myBody->setRollingFriction (0.1f);
|
||||
myBody->setSpinningFriction (0.1f);
|
||||
myBody->setAnisotropicFriction (myShape->CollisionShape()->getAnisotropicRollingFrictionDirection(),
|
||||
btCollisionObject::CF_ANISOTROPIC_ROLLING_FRICTION);
|
||||
}
|
||||
|
||||
if (toAdd && myWorld != NULL)
|
||||
{
|
||||
addToWorld (myWorld);
|
||||
}
|
||||
#else
|
||||
(void )theMass;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : addToWorld
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::addToWorld (Dynamics_World* theWorld)
|
||||
{
|
||||
removeFromWorld();
|
||||
#ifdef HAVE_BULLET
|
||||
myWorld = theWorld;
|
||||
if (myBody.get() == NULL || myWorld == NULL || myShape.IsNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
btDiscreteDynamicsWorld* aWorld = myWorld->myDynamicsWorld.get();
|
||||
if (btRigidBody* aRigidBody = btRigidBody::upcast (myBody.get()))
|
||||
{
|
||||
++myWorld->myNbRigidBodies;
|
||||
aWorld->addRigidBody (aRigidBody);
|
||||
}
|
||||
else
|
||||
{
|
||||
aWorld->addCollisionObject (myBody.get());
|
||||
}
|
||||
if (myAction.get() != NULL)
|
||||
{
|
||||
aWorld->addAction (myAction.get());
|
||||
}
|
||||
#else
|
||||
(void )theWorld;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : removeFromWorld
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::removeFromWorld()
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
if (myWorld != NULL && myBody.get() != NULL)
|
||||
{
|
||||
btDiscreteDynamicsWorld* aWorld = myWorld->myDynamicsWorld.get();
|
||||
if (myAction.get() != NULL)
|
||||
{
|
||||
aWorld->removeAction (myAction.get());
|
||||
}
|
||||
if (btRigidBody* aRigidBody = btRigidBody::upcast (myBody.get()))
|
||||
{
|
||||
aWorld->removeRigidBody (aRigidBody);
|
||||
--myWorld->myNbRigidBodies;
|
||||
}
|
||||
else
|
||||
{
|
||||
aWorld->removeCollisionObject (myBody.get());
|
||||
}
|
||||
}
|
||||
myWorld = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : clearMain
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::clearMain()
|
||||
{
|
||||
removeFromWorld();
|
||||
#ifdef HAVE_BULLET
|
||||
myAction.reset();
|
||||
myBody.reset();
|
||||
myMotionState.Nullify();
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : WorldPosition
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
gp_Pnt Dynamics_CollisionBody::WorldPosition() const
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
if (myBody.get() == NULL)
|
||||
{
|
||||
return gp_Pnt (0.0, 0.0, 0.0);
|
||||
}
|
||||
|
||||
const btTransform aTrsfBt = myBody->getWorldTransform();
|
||||
return gp_Pnt (aTrsfBt.getOrigin().x(), aTrsfBt.getOrigin().y(), aTrsfBt.getOrigin().z());
|
||||
#else
|
||||
return gp_Pnt (0.0, 0.0, 0.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : WorldLocation
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
gp_Trsf Dynamics_CollisionBody::WorldLocation() const
|
||||
{
|
||||
gp_Trsf aTrsf;
|
||||
#ifdef HAVE_BULLET
|
||||
if (myBody.get() == NULL)
|
||||
{
|
||||
return aTrsf;
|
||||
}
|
||||
|
||||
const btTransform aTrsfBt = myBody->getWorldTransform();
|
||||
Dynamics_MotionState::TrsfGpFromBt (aTrsf, aTrsfBt);
|
||||
#endif
|
||||
return aTrsf;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetWorldLocation
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::SetWorldLocation (const gp_Trsf& theLoc)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
if (myBody.get() != NULL)
|
||||
{
|
||||
btTransform aTrsfBt;
|
||||
Dynamics_MotionState::TrsfBtFromGp (aTrsfBt, theLoc);
|
||||
myBody->setWorldTransform (aTrsfBt);
|
||||
}
|
||||
#else
|
||||
(void )theLoc;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : WorldMotionLocation
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
gp_Trsf Dynamics_CollisionBody::WorldMotionLocation() const
|
||||
{
|
||||
gp_Trsf aTrsf;
|
||||
#ifdef HAVE_BULLET
|
||||
btRigidBody* aBody = btRigidBody::upcast (myBody.get());
|
||||
if (aBody == NULL || aBody->getMotionState() == NULL)
|
||||
{
|
||||
return WorldLocation();
|
||||
}
|
||||
|
||||
btTransform aTrsfBt;
|
||||
aBody->getMotionState()->getWorldTransform (aTrsfBt);
|
||||
Dynamics_MotionState::TrsfGpFromBt (aTrsf, aTrsfBt);
|
||||
#endif
|
||||
return aTrsf;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ApplyCentralForce
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::ApplyCentralForce (const gp_XYZ& theForce)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
btRigidBody* aBody = btRigidBody::upcast (myBody.get());
|
||||
if (aBody == NULL || aBody->getMotionState() == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
aBody->activate (true);
|
||||
aBody->applyCentralForce (gpXyz2Vec3Bt (theForce));
|
||||
#else
|
||||
(void )theForce;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ApplyCentralImpulse
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::ApplyCentralImpulse (const gp_XYZ& theImpulse)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
btRigidBody* aBody = btRigidBody::upcast (myBody.get());
|
||||
if (aBody == NULL || aBody->getMotionState() == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
aBody->activate (true);
|
||||
aBody->applyCentralImpulse (gpXyz2Vec3Bt (theImpulse));
|
||||
#else
|
||||
(void )theImpulse;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ApplyTorque
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::ApplyTorque (const gp_XYZ& theTorque)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
btRigidBody* aBody = btRigidBody::upcast (myBody.get());
|
||||
if (aBody == NULL || aBody->getMotionState() == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
aBody->activate (true);
|
||||
aBody->applyTorque (gpXyz2Vec3Bt (theTorque));
|
||||
#else
|
||||
(void )theTorque;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ApplyForce
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::ApplyForce (const gp_XYZ& theForce,
|
||||
const gp_Pnt& theRelPos)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
btRigidBody* aBody = btRigidBody::upcast (myBody.get());
|
||||
if (aBody == NULL || aBody->getMotionState() == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
aBody->activate (true);
|
||||
aBody->applyForce (gpXyz2Vec3Bt (theForce), gpXyz2Vec3Bt (theRelPos.XYZ()));
|
||||
#else
|
||||
(void )theForce;
|
||||
(void )theRelPos;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ApplyImpulse
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::ApplyImpulse (const gp_XYZ& theImpulse,
|
||||
const gp_Pnt& theRelPos)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
btRigidBody* aBody = btRigidBody::upcast (myBody.get());
|
||||
if (aBody == NULL || aBody->getMotionState() == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
aBody->activate (true);
|
||||
aBody->applyImpulse (gpXyz2Vec3Bt (theImpulse), gpXyz2Vec3Bt (theRelPos.XYZ()));
|
||||
#else
|
||||
(void )theImpulse;
|
||||
(void )theRelPos;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ApplyTorqueImpulse
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionBody::ApplyTorqueImpulse (const gp_XYZ& theTorque)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
btRigidBody* aBody = btRigidBody::upcast (myBody.get());
|
||||
if (aBody == NULL || aBody->getMotionState() == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
aBody->activate (true);
|
||||
aBody->applyTorqueImpulse (gpXyz2Vec3Bt (theTorque));
|
||||
#else
|
||||
(void )theTorque;
|
||||
#endif
|
||||
}
|
128
src/Dynamics/Dynamics_CollisionBody.hxx
Normal file
128
src/Dynamics/Dynamics_CollisionBody.hxx
Normal file
@@ -0,0 +1,128 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_CollisionBody_HeaderFile
|
||||
#define _Dynamics_CollisionBody_HeaderFile
|
||||
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <NCollection_Vector.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class Dynamics_CollisionShape;
|
||||
class Dynamics_Constraint;
|
||||
class Dynamics_MotionState;
|
||||
class Dynamics_World;
|
||||
|
||||
class btActionInterface;
|
||||
class btCollisionObject;
|
||||
class btCollisionShape;
|
||||
class btTransform;
|
||||
|
||||
//! Class defining collision body.
|
||||
class Dynamics_CollisionBody : public Standard_Transient
|
||||
{
|
||||
friend class Dynamics_Constraint;
|
||||
friend class Dynamics_World;
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_CollisionBody, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT Dynamics_CollisionBody();
|
||||
|
||||
//! Constructor.
|
||||
Standard_EXPORT Dynamics_CollisionBody (const Handle(Dynamics_CollisionShape)& theShape);
|
||||
|
||||
//! Destructor, automatically removes the body from the world.
|
||||
Standard_EXPORT virtual ~Dynamics_CollisionBody();
|
||||
|
||||
//! Return the world.
|
||||
Dynamics_World* DynamicsWorld() { return myWorld; }
|
||||
|
||||
//! Return the shape.
|
||||
const Handle(Dynamics_CollisionShape)& Shape() const { return myShape; }
|
||||
|
||||
//! Assign new shape.
|
||||
Standard_EXPORT void SetShape (const Handle(Dynamics_CollisionShape)& theShape,
|
||||
const gp_Trsf& theTrsf = gp_Trsf());
|
||||
|
||||
//! Assign new shape.
|
||||
Standard_EXPORT void SetShape (const Handle(Dynamics_CollisionShape)& theShape,
|
||||
const Handle(Dynamics_MotionState)& theMotionState,
|
||||
const float theMass);
|
||||
|
||||
//! Return motion state.
|
||||
const Handle(Dynamics_MotionState)& MotionState() const { return myMotionState; }
|
||||
|
||||
//! Return constraint.
|
||||
const Handle(Dynamics_Constraint)& Constraint() const { return myConstraint; }
|
||||
|
||||
//! Return the position (origin) in the world.
|
||||
Standard_EXPORT gp_Pnt WorldPosition() const;
|
||||
|
||||
//! Return the location in the world.
|
||||
Standard_EXPORT gp_Trsf WorldLocation() const;
|
||||
|
||||
//! Return the location in the world.
|
||||
Standard_EXPORT void SetWorldLocation (const gp_Trsf& theLoc);
|
||||
|
||||
//! Return the location in the world.
|
||||
Standard_EXPORT gp_Trsf WorldMotionLocation() const;
|
||||
|
||||
//! Alias for btRigidBody::applyCentralImpulse().
|
||||
Standard_EXPORT void ApplyCentralForce (const gp_XYZ& theForce);
|
||||
|
||||
//! Alias for btRigidBody::applyCentralImpulse().
|
||||
Standard_EXPORT void ApplyCentralImpulse(const gp_XYZ& theImpulse);
|
||||
|
||||
//! Alias for btRigidBody::applyForce().
|
||||
Standard_EXPORT void ApplyForce (const gp_XYZ& theForce, const gp_Pnt& theRelPos);
|
||||
|
||||
//! Alias for btRigidBody::applyTorque().
|
||||
Standard_EXPORT void ApplyTorque (const gp_XYZ& theTorque);
|
||||
|
||||
//! Alias for btRigidBody::applyImpulse().
|
||||
Standard_EXPORT void ApplyImpulse(const gp_XYZ& theImpulse, const gp_Pnt& theRelPos);
|
||||
|
||||
//! Alias for btRigidBody::applyTorqueImpulse().
|
||||
Standard_EXPORT void ApplyTorqueImpulse (const gp_XYZ& theTorque);
|
||||
|
||||
public:
|
||||
|
||||
//! Return collision body.
|
||||
btCollisionObject* collisionBody() { return myBody.get(); }
|
||||
|
||||
protected:
|
||||
|
||||
//! Add body to the world.
|
||||
Standard_EXPORT virtual void addToWorld (Dynamics_World* theWorld);
|
||||
|
||||
//! Remove body from the world.
|
||||
Standard_EXPORT virtual void removeFromWorld();
|
||||
|
||||
//! Release the memory.
|
||||
Standard_EXPORT void clearMain();
|
||||
|
||||
protected:
|
||||
|
||||
Handle(Dynamics_CollisionShape) myShape;
|
||||
Handle(Dynamics_MotionState) myMotionState;
|
||||
Handle(Dynamics_Constraint) myConstraint;
|
||||
std::shared_ptr<btActionInterface> myAction;
|
||||
std::shared_ptr<btCollisionObject> myBody;
|
||||
Dynamics_World* myWorld;
|
||||
|
||||
};
|
||||
|
||||
#endif // _Dynamics_CollisionBody_HeaderFile
|
51
src/Dynamics/Dynamics_CollisionBoxShape.cxx
Normal file
51
src/Dynamics/Dynamics_CollisionBoxShape.cxx
Normal file
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_CollisionBoxShape.hxx>
|
||||
|
||||
#include <Dynamics_Internal.hxx>
|
||||
|
||||
#include <gp_Ax3.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_CollisionBoxShape, Dynamics_CollisionShape)
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_CollisionBoxShape
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_CollisionBoxShape::Dynamics_CollisionBoxShape (const Bnd_OBB& theOBB)
|
||||
{
|
||||
if (!theOBB.IsVoid())
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
myShape = new btBoxShape (btVector3 (btScalar(theOBB.XHSize()), btScalar(theOBB.YHSize()), btScalar(theOBB.ZHSize())));
|
||||
myLocation.SetTransformation (gp_Ax3 (theOBB.Center(), theOBB.ZDirection(), theOBB.XDirection()), gp::XOY());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_CollisionBoxShape
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_CollisionBoxShape::Dynamics_CollisionBoxShape (const Bnd_Box& theAABB)
|
||||
{
|
||||
if (!theAABB.IsVoid())
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
const gp_XYZ aSize = theAABB.CornerMax().XYZ() - theAABB.CornerMin().XYZ();
|
||||
myShape = new btBoxShape (btVector3 (btScalar(aSize.X() * 0.5), btScalar(aSize.Y() * 0.5), btScalar(aSize.Z() * 0.5)));
|
||||
myLocation.SetTranslation ((theAABB.CornerMin().XYZ() + theAABB.CornerMax().XYZ()) * 0.5);
|
||||
#endif
|
||||
}
|
||||
}
|
40
src/Dynamics/Dynamics_CollisionBoxShape.hxx
Normal file
40
src/Dynamics/Dynamics_CollisionBoxShape.hxx
Normal file
@@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2018-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_CollisionBoxShape_HeaderFile
|
||||
#define _Dynamics_CollisionBoxShape_HeaderFile
|
||||
|
||||
#include <Dynamics_CollisionShape.hxx>
|
||||
|
||||
#include <Bnd_OBB.hxx>
|
||||
|
||||
//! Define the collision shape as OBB.
|
||||
class Dynamics_CollisionBoxShape : public Dynamics_CollisionShape
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_CollisionBoxShape, Dynamics_CollisionShape)
|
||||
public:
|
||||
|
||||
//! Constructor from OBB.
|
||||
Standard_EXPORT Dynamics_CollisionBoxShape (const Bnd_OBB& theOBB);
|
||||
|
||||
//! Constructor from AABB.
|
||||
Standard_EXPORT Dynamics_CollisionBoxShape (const Bnd_Box& theAABB);
|
||||
|
||||
//! Return shape location.
|
||||
virtual const gp_Trsf& Location() const Standard_OVERRIDE { return myLocation; }
|
||||
|
||||
protected:
|
||||
gp_Trsf myLocation;
|
||||
};
|
||||
|
||||
#endif // _Dynamics_CollisionBoxShape_HeaderFile
|
77
src/Dynamics/Dynamics_CollisionCompoundShape.cxx
Normal file
77
src/Dynamics/Dynamics_CollisionCompoundShape.cxx
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_CollisionCompoundShape.hxx>
|
||||
|
||||
#include <Dynamics_Internal.hxx>
|
||||
#include <Dynamics_MotionState.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_CollisionCompoundShape, Dynamics_CollisionShape)
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_CollisionCompoundShape
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_CollisionCompoundShape::Dynamics_CollisionCompoundShape()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Dynamics_CollisionCompoundShape
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_CollisionCompoundShape::~Dynamics_CollisionCompoundShape()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Init
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Dynamics_CollisionCompoundShape::Init()
|
||||
{
|
||||
releaseShape();
|
||||
if (mySubShapes.IsEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
btTransform aTrsfBt;
|
||||
aTrsfBt.setIdentity();
|
||||
|
||||
btCompoundShape* aCompShape = new btCompoundShape();
|
||||
myShape = aCompShape;
|
||||
for (int aChildIter = mySubShapes.Lower(); aChildIter <= mySubShapes.Upper(); ++aChildIter)
|
||||
{
|
||||
const Handle(Dynamics_CollisionShape)& aShape = mySubShapes.Value (aChildIter);
|
||||
if (!aShape.IsNull()
|
||||
&& aShape->IsValid())
|
||||
{
|
||||
const gp_Trsf& aTrsf = aShape->Location();
|
||||
Dynamics_MotionState::TrsfBtFromGp (aTrsfBt, aTrsf);
|
||||
aCompShape->addChildShape (aTrsfBt, aShape->myShape);
|
||||
}
|
||||
}
|
||||
if (aCompShape->getNumChildShapes() == 0)
|
||||
{
|
||||
releaseShape();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
45
src/Dynamics/Dynamics_CollisionCompoundShape.hxx
Normal file
45
src/Dynamics/Dynamics_CollisionCompoundShape.hxx
Normal file
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_CollisionCompoundShape_HeaderFile
|
||||
#define _Dynamics_CollisionCompoundShape_HeaderFile
|
||||
|
||||
#include <NCollection_Array1.hxx>
|
||||
|
||||
#include <Dynamics_CollisionShape.hxx>
|
||||
|
||||
//! Define the collision body from triangulation data.
|
||||
class Dynamics_CollisionCompoundShape : public Dynamics_CollisionShape
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_CollisionCompoundShape, Dynamics_CollisionShape)
|
||||
public:
|
||||
|
||||
//! Constructor.
|
||||
Standard_EXPORT Dynamics_CollisionCompoundShape();
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Dynamics_CollisionCompoundShape();
|
||||
|
||||
//! Modify sub-shapes.
|
||||
NCollection_Array1<Handle(Dynamics_CollisionShape)>& ChangeSubShapes() { return mySubShapes; }
|
||||
|
||||
//! Initialize the collision shape after modification of sub-shape
|
||||
Standard_EXPORT bool Init();
|
||||
|
||||
protected:
|
||||
|
||||
NCollection_Array1<Handle(Dynamics_CollisionShape)> mySubShapes;
|
||||
|
||||
};
|
||||
|
||||
#endif // _Dynamics_CollisionCompoundShape_HeaderFile
|
41
src/Dynamics/Dynamics_CollisionPlane.cxx
Normal file
41
src/Dynamics/Dynamics_CollisionPlane.cxx
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_CollisionPlane.hxx>
|
||||
|
||||
#include <Dynamics_Internal.hxx>
|
||||
|
||||
#include <gp_Pln.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_CollisionPlane, Dynamics_CollisionShape)
|
||||
|
||||
// =======================================================================
|
||||
// function : InitPlane
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionPlane::InitPlane (const gp_Pln& thePlane)
|
||||
{
|
||||
releaseShape();
|
||||
#ifdef HAVE_BULLET
|
||||
// ABCD does not work as expected for unknown reason
|
||||
//NCollection_Vec4<double> aCoef;
|
||||
//thePlane.Coefficients (aCoef.x(), aCoef.y(), aCoef.z(), aCoef.w());
|
||||
//myShape = new btStaticPlaneShape (btVector3 (btScalar(aCoef.x()), btScalar(aCoef.y()), btScalar(aCoef.z())), btScalar(aCoef.w()));
|
||||
myShape = new btStaticPlaneShape (btVector3 (btScalar(thePlane.Axis().Direction().X()),
|
||||
btScalar(thePlane.Axis().Direction().Y()),
|
||||
btScalar(thePlane.Axis().Direction().Z())),
|
||||
btScalar(0.0));
|
||||
#else
|
||||
(void )thePlane;
|
||||
#endif
|
||||
}
|
38
src/Dynamics/Dynamics_CollisionPlane.hxx
Normal file
38
src/Dynamics/Dynamics_CollisionPlane.hxx
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_CollisionPlane_HeaderFile
|
||||
#define _Dynamics_CollisionPlane_HeaderFile
|
||||
|
||||
#include <Dynamics_CollisionShape.hxx>
|
||||
|
||||
class gp_Pln;
|
||||
|
||||
//! Infinite collision plane.
|
||||
class Dynamics_CollisionPlane : public Dynamics_CollisionShape
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_CollisionPlane, Dynamics_CollisionShape)
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
Dynamics_CollisionPlane (const gp_Pln& thePlane)
|
||||
{
|
||||
InitPlane (thePlane);
|
||||
}
|
||||
|
||||
//! Initialize the collision plane.
|
||||
Standard_EXPORT void InitPlane (const gp_Pln& thePlane);
|
||||
|
||||
};
|
||||
|
||||
#endif // _Dynamics_CollisionPlane_HeaderFile
|
59
src/Dynamics/Dynamics_CollisionShape.cxx
Normal file
59
src/Dynamics/Dynamics_CollisionShape.cxx
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_CollisionShape.hxx>
|
||||
|
||||
#include <Dynamics_Internal.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_CollisionShape, Standard_Transient)
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_CollisionShape
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_CollisionShape::Dynamics_CollisionShape()
|
||||
: myShape (NULL)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_CollisionShape
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_CollisionShape::Dynamics_CollisionShape (btCollisionShape* theShape)
|
||||
: myShape (theShape)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Dynamics_CollisionShape
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_CollisionShape::~Dynamics_CollisionShape()
|
||||
{
|
||||
releaseShape();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : releaseShape
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_CollisionShape::releaseShape()
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
delete myShape;
|
||||
#endif
|
||||
myShape = NULL;
|
||||
}
|
65
src/Dynamics/Dynamics_CollisionShape.hxx
Normal file
65
src/Dynamics/Dynamics_CollisionShape.hxx
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_CollisionShape_HeaderFile
|
||||
#define _Dynamics_CollisionShape_HeaderFile
|
||||
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
|
||||
class btCollisionShape;
|
||||
|
||||
//! Define the collision shape.
|
||||
class Dynamics_CollisionShape : public Standard_Transient
|
||||
{
|
||||
friend class Dynamics_CollisionBody;
|
||||
friend class Dynamics_CollisionCompoundShape;
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_CollisionShape, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT Dynamics_CollisionShape();
|
||||
|
||||
//! Constructor.
|
||||
Standard_EXPORT Dynamics_CollisionShape (btCollisionShape* theShape);
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Dynamics_CollisionShape();
|
||||
|
||||
//! Return true if shape object is defined.
|
||||
bool IsValid() const { return myShape != NULL; }
|
||||
|
||||
//! Return collision shape pointer.
|
||||
btCollisionShape* CollisionShape() const { return myShape; }
|
||||
|
||||
//! Return shape location.
|
||||
//! Default implementation always returns an identity location,
|
||||
//! because it is expected that location is put into Motion State instead.
|
||||
//! This method can be overridden for storing an initial location.
|
||||
virtual const gp_Trsf& Location() const
|
||||
{
|
||||
static const gp_Trsf THE_IDENT_LOC;
|
||||
return THE_IDENT_LOC;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! Release memory.
|
||||
Standard_EXPORT void releaseShape();
|
||||
|
||||
protected:
|
||||
btCollisionShape* myShape;
|
||||
};
|
||||
|
||||
#endif // _Dynamics_CollisionShape_HeaderFile
|
221
src/Dynamics/Dynamics_Constraint.cxx
Normal file
221
src/Dynamics/Dynamics_Constraint.cxx
Normal file
@@ -0,0 +1,221 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_Constraint.hxx>
|
||||
|
||||
#include <Dynamics_Internal.hxx>
|
||||
#include <Dynamics_CollisionBody.hxx>
|
||||
#include <Dynamics_World.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_Constraint, Standard_Transient)
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_Constraint
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_Constraint::Dynamics_Constraint()
|
||||
: myConstraint (nullptr)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Dynamics_Constraint
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_Constraint::~Dynamics_Constraint()
|
||||
{
|
||||
releaseConstraint();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : releaseConstraint
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Constraint::releaseConstraint()
|
||||
{
|
||||
removeFromWorld();
|
||||
#ifdef HAVE_BULLET
|
||||
delete myConstraint;
|
||||
#endif
|
||||
myConstraint = nullptr;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : addToWorld
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Constraint::addToWorld (Dynamics_World* theWorld)
|
||||
{
|
||||
removeFromWorld();
|
||||
#ifdef HAVE_BULLET
|
||||
myWorld = theWorld;
|
||||
if (myConstraint == nullptr || theWorld == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
btDiscreteDynamicsWorld* aWorld = theWorld->myDynamicsWorld.get();
|
||||
aWorld->addConstraint (myConstraint);
|
||||
#else
|
||||
(void )theWorld;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : removeFromWorld
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Constraint::removeFromWorld()
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
if (myWorld != nullptr && myConstraint != nullptr)
|
||||
{
|
||||
btDiscreteDynamicsWorld* aWorld = myWorld->myDynamicsWorld.get();
|
||||
aWorld->removeConstraint (myConstraint);
|
||||
}
|
||||
myWorld = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : CreateGeneric6Dof
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Constraint::CreateGeneric6Dof (const Handle(Dynamics_CollisionBody)& theBody,
|
||||
const gp_XYZ& theLinearLower,
|
||||
const gp_XYZ& theLinearUpper,
|
||||
const gp_XYZ& theAngularLower,
|
||||
const gp_XYZ& theAngularUpper)
|
||||
{
|
||||
Dynamics_World* aWorld = myWorld;
|
||||
releaseConstraint();
|
||||
if (theBody.IsNull())
|
||||
{
|
||||
throw Standard_ProgramError ("Dynamics_Constraint, Internal Error - NULL Rigid Body");
|
||||
}
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
btRigidBody* aRigidBody = btRigidBody::upcast (theBody->collisionBody());
|
||||
if (aRigidBody == nullptr)
|
||||
{
|
||||
throw Standard_ProgramError ("Dynamics_Constraint, Internal Error - no Rigid Body");
|
||||
}
|
||||
|
||||
const btTransform aFrameInBody = btTransform::getIdentity();
|
||||
myConstraint = new btGeneric6DofConstraint (*aRigidBody, aFrameInBody, false);
|
||||
myConstraint->setDbgDrawSize (5.0f);
|
||||
SetLinearLimits (theLinearLower, theLinearUpper);
|
||||
SetAngularLimits(theAngularLower, theAngularUpper);
|
||||
theBody->myConstraint = this;
|
||||
if (aWorld != nullptr)
|
||||
{
|
||||
addToWorld (aWorld);
|
||||
}
|
||||
else if (theBody->myWorld != nullptr)
|
||||
{
|
||||
theBody->myWorld->AddConstraint (this);
|
||||
//addToWorld (theBody->myWorld);
|
||||
}
|
||||
#else
|
||||
(void )aWorld;
|
||||
(void )theLinearLower;
|
||||
(void )theLinearUpper;
|
||||
(void )theAngularLower;
|
||||
(void )theAngularUpper;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : LinearLimits
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Dynamics_Constraint::LinearLimits (gp_XYZ& theLower, gp_XYZ& theUpper) const
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
if (const btGeneric6DofConstraint* aConstr = dynamic_cast<const btGeneric6DofConstraint*>(myConstraint))
|
||||
{
|
||||
btVector3 aLower, anUpper;
|
||||
aConstr->getLinearLowerLimit (aLower);
|
||||
aConstr->getLinearUpperLimit (anUpper);
|
||||
theLower.SetCoord (aLower.x(), aLower.y(), aLower.z());
|
||||
theUpper.SetCoord (anUpper.x(), anUpper.y(), anUpper.z());
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
theLower.SetCoord ( 1.0, 1.0, 1.0);
|
||||
theUpper.SetCoord (-1.0, -1.0, -1.0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetLinearLimits
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Constraint::SetLinearLimits (const gp_XYZ& theLower, const gp_XYZ& theUpper)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
if (btGeneric6DofConstraint* aConstr = dynamic_cast<btGeneric6DofConstraint*>(myConstraint))
|
||||
{
|
||||
aConstr->setLinearLowerLimit (btVector3 ((btScalar )theLower.X(), (btScalar )theLower.Y(), (btScalar )theLower.Z()));
|
||||
aConstr->setLinearUpperLimit (btVector3 ((btScalar )theUpper.X(), (btScalar )theUpper.Y(), (btScalar )theUpper.Z()));
|
||||
return;
|
||||
}
|
||||
#else
|
||||
(void )theLower;
|
||||
(void )theUpper;
|
||||
#endif
|
||||
throw Standard_ProgramError ("Dynamics_Constraint::SetLinearLimits(), invalid constraint type");
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : AngularLimits
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Dynamics_Constraint::AngularLimits (gp_XYZ& theLower, gp_XYZ& theUpper) const
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
if (const btGeneric6DofConstraint* aConstr = dynamic_cast<const btGeneric6DofConstraint*>(myConstraint))
|
||||
{
|
||||
btVector3 aLower, anUpper;
|
||||
aConstr->getAngularLowerLimit (aLower);
|
||||
aConstr->getAngularUpperLimit (anUpper);
|
||||
theLower.SetCoord (aLower.x(), aLower.y(), aLower.z());
|
||||
theUpper.SetCoord (anUpper.x(), anUpper.y(), anUpper.z());
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
theLower.SetCoord ( 1.0, 1.0, 1.0);
|
||||
theUpper.SetCoord (-1.0, -1.0, -1.0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetAngularLimits
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Constraint::SetAngularLimits (const gp_XYZ& theLower, const gp_XYZ& theUpper)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
if (btGeneric6DofConstraint* aConstr = dynamic_cast<btGeneric6DofConstraint*>(myConstraint))
|
||||
{
|
||||
aConstr->setAngularLowerLimit (btVector3 ((btScalar )theLower.X(), (btScalar )theLower.Y(), (btScalar )theLower.Z()));
|
||||
aConstr->setAngularUpperLimit (btVector3 ((btScalar )theUpper.X(), (btScalar )theUpper.Y(), (btScalar )theUpper.Z()));
|
||||
return;
|
||||
}
|
||||
#else
|
||||
(void )theLower;
|
||||
(void )theUpper;
|
||||
#endif
|
||||
throw Standard_ProgramError ("Dynamics_Constraint::SetAngularLimits(), invalid constraint type");
|
||||
}
|
85
src/Dynamics/Dynamics_Constraint.hxx
Normal file
85
src/Dynamics/Dynamics_Constraint.hxx
Normal file
@@ -0,0 +1,85 @@
|
||||
// Copyright (c) 2018-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_Constraint_HeaderFile
|
||||
#define _Dynamics_Constraint_HeaderFile
|
||||
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
|
||||
class btTypedConstraint;
|
||||
class Dynamics_CollisionBody;
|
||||
class Dynamics_World;
|
||||
|
||||
//! Define the motion state.
|
||||
class Dynamics_Constraint : public Standard_Transient
|
||||
{
|
||||
friend class Dynamics_World;
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_Constraint, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT Dynamics_Constraint();
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Dynamics_Constraint();
|
||||
|
||||
//! Return true if Constraint is defined.
|
||||
bool IsValid() const { return myConstraint != NULL; }
|
||||
|
||||
//! Return Constraint pointer.
|
||||
btTypedConstraint* TypedConstraint() const { return myConstraint; }
|
||||
|
||||
Standard_EXPORT void CreateGeneric6Dof (const Handle(Dynamics_CollisionBody)& theBody,
|
||||
const gp_XYZ& theLinearLower,
|
||||
const gp_XYZ& theLinearUpper,
|
||||
const gp_XYZ& theAngularLower,
|
||||
const gp_XYZ& theAngularUpper);
|
||||
|
||||
//! Return the world.
|
||||
Dynamics_World* DynamicsWorld() { return myWorld; }
|
||||
|
||||
//! Return linear limits per axis.
|
||||
//! Upper value below Lower means that there is NO limit.
|
||||
Standard_EXPORT bool LinearLimits (gp_XYZ& theLower, gp_XYZ& theUpper) const;
|
||||
|
||||
//! Set linear limits per axis (in radians).
|
||||
Standard_EXPORT void SetLinearLimits (const gp_XYZ& theLower, const gp_XYZ& theUpper);
|
||||
|
||||
//! Return angular limits per axis (in radians).
|
||||
//! Upper value below Lower means that there is NO limit.
|
||||
Standard_EXPORT bool AngularLimits(gp_XYZ& theLower, gp_XYZ& theUpper) const;
|
||||
|
||||
//! Set angular limits per axis (in radians).
|
||||
Standard_EXPORT void SetAngularLimits (const gp_XYZ& theLower, const gp_XYZ& theUpper);
|
||||
|
||||
protected:
|
||||
|
||||
//! Release memory.
|
||||
Standard_EXPORT void releaseConstraint();
|
||||
|
||||
//! Add body to the world.
|
||||
Standard_EXPORT void addToWorld (Dynamics_World* theWorld);
|
||||
|
||||
//! Remove body from the world.
|
||||
Standard_EXPORT void removeFromWorld();
|
||||
|
||||
protected:
|
||||
|
||||
Dynamics_World* myWorld;
|
||||
btTypedConstraint* myConstraint;
|
||||
|
||||
};
|
||||
|
||||
#endif // _Dynamics_Constraint_HeaderFile
|
345
src/Dynamics/Dynamics_DebugDrawer.cxx
Normal file
345
src/Dynamics/Dynamics_DebugDrawer.cxx
Normal file
@@ -0,0 +1,345 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
|
||||
#include <Dynamics_DebugDrawer.hxx>
|
||||
|
||||
#include <AIS_TextLabel.hxx>
|
||||
#include <Message.hxx>
|
||||
#include <Message_Messenger.hxx>
|
||||
#include <Prs3d_LineAspect.hxx>
|
||||
#include <Prs3d_PointAspect.hxx>
|
||||
#include <V3d_Viewer.hxx>
|
||||
#include <V3d_View.hxx>
|
||||
|
||||
namespace
|
||||
{
|
||||
//! Convert vec3 into vec4ub color.
|
||||
Graphic3d_Vec4ub colorBt2vec4ub (const btVector3& theColor)
|
||||
{
|
||||
return Graphic3d_Vec4ub ((unsigned char)(int)(theColor.x() * 255.0f),
|
||||
(unsigned char)(int)(theColor.y() * 255.0f),
|
||||
(unsigned char)(int)(theColor.z() * 255.0f),
|
||||
255);
|
||||
}
|
||||
}
|
||||
|
||||
//! Auxiliary presentation of line segments and points.
|
||||
class Dynamics_DebugDrawer::Dynamics_DebugPrs : public AIS_InteractiveObject
|
||||
{
|
||||
DEFINE_STANDARD_RTTI_INLINE(Dynamics_DebugPrs, AIS_InteractiveObject)
|
||||
public:
|
||||
//! Empty constructor.
|
||||
Dynamics_DebugPrs()
|
||||
{
|
||||
SetMutable (true);
|
||||
SetInfiniteState (true);
|
||||
mySegments = new ColoredNodeBuffer();
|
||||
myPoints = new ColoredNodeBuffer();
|
||||
myDrawer->SetLineAspect (new Prs3d_LineAspect (Quantity_NOC_RED, Aspect_TOL_SOLID, 1.0f));
|
||||
myDrawer->SetPointAspect(new Prs3d_PointAspect(Aspect_TOM_PLUS, Quantity_NOC_RED, 1.0f));
|
||||
}
|
||||
|
||||
//! Colored node.
|
||||
struct ColoredNode
|
||||
{
|
||||
Graphic3d_Vec3 Position;
|
||||
Graphic3d_Vec4ub Color;
|
||||
};
|
||||
|
||||
//! Return vector of colored segments.
|
||||
std::vector<ColoredNode>& ChangeSegments() { return mySegments->Nodes; }
|
||||
|
||||
//! Return vector of colored points.
|
||||
std::vector<ColoredNode>& ChangePoints() { return myPoints->Nodes; }
|
||||
|
||||
//! Clear previous data.
|
||||
void Clear()
|
||||
{
|
||||
if (!mySegments->Nodes.empty()
|
||||
|| !myPoints->Nodes.empty())
|
||||
{
|
||||
mySegments->Nodes.clear();
|
||||
myPoints ->Nodes.clear();
|
||||
//SetToUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
//! Setup view bounding box to be used instead of min/max range of points in this presentation.
|
||||
//! This would allow avoiding issues with infinite presentations passed from Bullet (e.g. for btStaticPlaneShape).
|
||||
void SetViewBox (const Bnd_Box& theBox) { myViewBox = theBox; }
|
||||
|
||||
protected:
|
||||
|
||||
//! Return TRUE for supported display modes.
|
||||
virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0; }
|
||||
|
||||
//! Compute presentation.
|
||||
virtual void Compute (const Handle(PrsMgr_PresentationManager)& ,
|
||||
const Handle(Prs3d_Presentation)& thePrs,
|
||||
const Standard_Integer theMode) Standard_OVERRIDE
|
||||
{
|
||||
thePrs->SetInfiniteState (true);
|
||||
if (theMode != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Graphic3d_Vec3d aMinMax[2];
|
||||
bool toCalcMinMax = myViewBox.IsVoid();
|
||||
if (!toCalcMinMax)
|
||||
{
|
||||
aMinMax[0].SetValues (myViewBox.CornerMin().X(), myViewBox.CornerMin().Y(), myViewBox.CornerMin().Z());
|
||||
aMinMax[1].SetValues (myViewBox.CornerMax().X(), myViewBox.CornerMax().Y(), myViewBox.CornerMax().Z());
|
||||
}
|
||||
|
||||
if (mySegments->Init())
|
||||
{
|
||||
const Handle(Graphic3d_Group)& aGroup = thePrs->NewGroup();
|
||||
aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
|
||||
aGroup->AddPrimitiveArray (Graphic3d_TOPA_SEGMENTS, Handle(Graphic3d_IndexBuffer)(), mySegments, Handle(Graphic3d_BoundBuffer)(), toCalcMinMax);
|
||||
if (!toCalcMinMax)
|
||||
{
|
||||
aGroup->SetMinMaxValues (aMinMax[0].x(), aMinMax[0].y(), aMinMax[0].z(),
|
||||
aMinMax[1].x(), aMinMax[1].y(), aMinMax[1].z());
|
||||
}
|
||||
}
|
||||
if (myPoints->Init())
|
||||
{
|
||||
const Handle(Graphic3d_Group)& aGroup = thePrs->NewGroup();
|
||||
aGroup->SetGroupPrimitivesAspect (myDrawer->PointAspect()->Aspect());
|
||||
aGroup->AddPrimitiveArray (Graphic3d_TOPA_POINTS, Handle(Graphic3d_IndexBuffer)(), myPoints, Handle(Graphic3d_BoundBuffer)(), toCalcMinMax);
|
||||
if (!toCalcMinMax)
|
||||
{
|
||||
aGroup->SetMinMaxValues (aMinMax[0].x(), aMinMax[0].y(), aMinMax[0].z(),
|
||||
aMinMax[1].x(), aMinMax[1].y(), aMinMax[1].z());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//! Empty selection builder.
|
||||
virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
|
||||
{
|
||||
(void )theSel;
|
||||
(void )theMode;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//! Buffer holding colored nodes.
|
||||
//! This implementation wraps std::vector array, so that NCollection_Buffer wraps external memory and initialized with NULL allocator.
|
||||
class ColoredNodeBuffer : public Graphic3d_Buffer
|
||||
{
|
||||
public:
|
||||
//! Data array.
|
||||
std::vector<ColoredNode> Nodes;
|
||||
|
||||
//! Empty constructor; passes a NULL allocator.
|
||||
ColoredNodeBuffer() : Graphic3d_Buffer (Handle(NCollection_BaseAllocator)()) {}
|
||||
|
||||
//! Wraps buffer from std::vector.
|
||||
bool Init()
|
||||
{
|
||||
release();
|
||||
if (Nodes.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Graphic3d_Buffer defines attributes definition at the end of memory buffer,
|
||||
// so that we are extending std::vector capacity to cover this memory block.
|
||||
const size_t aReserve = (sizeof(Nodes[0]) + sizeof(Graphic3d_Attribute) - 1) / sizeof(Graphic3d_Attribute);
|
||||
Nodes.reserve (Nodes.size() + aReserve);
|
||||
|
||||
static const Graphic3d_Attribute anAttribs[2] =
|
||||
{
|
||||
{ Graphic3d_TOA_POS, Graphic3d_TOD_VEC3 },
|
||||
{ Graphic3d_TOA_COLOR, Graphic3d_TOD_VEC4UB }
|
||||
};
|
||||
|
||||
NbAttributes = 2;
|
||||
Stride = anAttribs[0].Stride() + anAttribs[1].Stride();
|
||||
NbElements = (int )Nodes.size();
|
||||
myData = (Standard_Byte* )&Nodes[0];
|
||||
mySize = size_t(Stride) * size_t(NbElements);
|
||||
ChangeAttribute (0) = anAttribs[0];
|
||||
ChangeAttribute (1) = anAttribs[1];
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Handle(ColoredNodeBuffer) mySegments;
|
||||
Handle(ColoredNodeBuffer) myPoints;
|
||||
Bnd_Box myViewBox;
|
||||
|
||||
};
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_DebugDrawer
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_DebugDrawer::Dynamics_DebugDrawer()
|
||||
: myZLayer (Graphic3d_ZLayerId_Topmost),
|
||||
myDebugMode (btIDebugDraw::DBG_DrawWireframe | btIDebugDraw::DBG_DrawContactPoints | btIDebugDraw::DBG_DrawText | btIDebugDraw::DBG_DrawFeaturesText)
|
||||
{
|
||||
//myDebugMode = -1;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Dynamics_DebugDrawer
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_DebugDrawer::~Dynamics_DebugDrawer()
|
||||
{
|
||||
FrameClear (nullptr);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : FrameClear
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_DebugDrawer::FrameClear (AIS_InteractiveContext* theCtx)
|
||||
{
|
||||
for (NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator aPrsIter (myTmpPrsList); aPrsIter.More(); aPrsIter.Next())
|
||||
{
|
||||
if (aPrsIter.Value()->HasInteractiveContext())
|
||||
{
|
||||
if (theCtx == nullptr)
|
||||
{
|
||||
throw Standard_ProgramError ("Internal Error: Dynamics_DebugDrawer::FrameClear() is called with NULL context");
|
||||
}
|
||||
theCtx->Remove (aPrsIter.Value(), false);
|
||||
}
|
||||
}
|
||||
myTmpPrsList.Clear();
|
||||
if (!myTmpPrs.IsNull())
|
||||
{
|
||||
myTmpPrs->Clear();
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : FrameBegin
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_DebugDrawer::FrameBegin (const Handle(AIS_InteractiveContext)& theCtx)
|
||||
{
|
||||
FrameClear (theCtx.get());
|
||||
if (myTmpPrs.IsNull())
|
||||
{
|
||||
myTmpPrs = new Dynamics_DebugPrs();
|
||||
myTmpPrs->SetZLayer (myZLayer);
|
||||
}
|
||||
{
|
||||
Handle(V3d_View) aView = theCtx->CurrentViewer()->ActiveViewIterator().Value();
|
||||
const Bnd_Box aViewBox = aView->View()->MinMaxValues();
|
||||
myTmpPrs->SetViewBox (aViewBox);
|
||||
}
|
||||
myTmpPrsList.Append (myTmpPrs);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : FrameEnd
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_DebugDrawer::FrameEnd (const Handle(AIS_InteractiveContext)& theCtx)
|
||||
{
|
||||
theCtx->RecomputePrsOnly (myTmpPrs, false);
|
||||
for (NCollection_Sequence<Handle(AIS_InteractiveObject)>::Iterator aPrsIter (myTmpPrsList); aPrsIter.More(); aPrsIter.Next())
|
||||
{
|
||||
theCtx->Display (aPrsIter.Value(), 0, -1, false);
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : drawLine
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_DebugDrawer::drawLine (const btVector3& theFrom,
|
||||
const btVector3& theTo,
|
||||
const btVector3& theColor)
|
||||
{
|
||||
Dynamics_DebugPrs::ColoredNode aNode;
|
||||
aNode.Color = colorBt2vec4ub (theColor);
|
||||
aNode.Position.SetValues (theFrom.x(), theFrom.y(), theFrom.z());
|
||||
myTmpPrs->ChangeSegments().push_back (aNode);
|
||||
aNode.Position.SetValues (theTo.x(), theTo.y(), theTo.z());
|
||||
myTmpPrs->ChangeSegments().push_back (aNode);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : drawLine
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_DebugDrawer::drawLine (const btVector3& theFrom,
|
||||
const btVector3& theTo,
|
||||
const btVector3& theFromColor,
|
||||
const btVector3& theToColor)
|
||||
{
|
||||
Dynamics_DebugPrs::ColoredNode aNode;
|
||||
aNode.Color = colorBt2vec4ub (theFromColor);
|
||||
aNode.Position.SetValues (theFrom.x(), theFrom.y(), theFrom.z());
|
||||
myTmpPrs->ChangeSegments().push_back (aNode);
|
||||
aNode.Color = colorBt2vec4ub (theToColor);
|
||||
aNode.Position.SetValues (theTo.x(), theTo.y(), theTo.z());
|
||||
myTmpPrs->ChangeSegments().push_back (aNode);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : drawContactPoint
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_DebugDrawer::drawContactPoint (const btVector3& thePointOnB,
|
||||
const btVector3& theNormalOnB,
|
||||
btScalar theDistance,
|
||||
int theLifeTime,
|
||||
const btVector3& theColor)
|
||||
{
|
||||
Dynamics_DebugPrs::ColoredNode aNode;
|
||||
aNode.Color = colorBt2vec4ub (theColor);
|
||||
aNode.Position.SetValues (thePointOnB.x(), thePointOnB.y(), thePointOnB.z());
|
||||
myTmpPrs->ChangePoints().push_back (aNode);
|
||||
(void )theNormalOnB;
|
||||
(void )theDistance;
|
||||
(void )theLifeTime;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : reportErrorWarning
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_DebugDrawer::reportErrorWarning (const char* theWarningString)
|
||||
{
|
||||
Message::SendWarning (theWarningString);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : draw3dText
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_DebugDrawer::draw3dText (const btVector3& theLocation,
|
||||
const char* theTextString)
|
||||
{
|
||||
Handle(AIS_TextLabel) aLabel = new AIS_TextLabel();
|
||||
aLabel->SetMutable(true);
|
||||
aLabel->SetZLayer (myZLayer);
|
||||
aLabel->SetInfiniteState (true);
|
||||
aLabel->SetText (theTextString);
|
||||
aLabel->SetPosition (gp_Pnt (theLocation.x(), theLocation.y(), theLocation.z()));
|
||||
myTmpPrsList.Append (aLabel);
|
||||
}
|
||||
|
||||
#endif
|
90
src/Dynamics/Dynamics_DebugDrawer.hxx
Normal file
90
src/Dynamics/Dynamics_DebugDrawer.hxx
Normal file
@@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2018-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_DebugDrawer_HeaderFile
|
||||
#define _Dynamics_DebugDrawer_HeaderFile
|
||||
|
||||
#include <AIS_InteractiveContext.hxx>
|
||||
|
||||
#include <Dynamics_Internal.hxx>
|
||||
|
||||
//! Define the debugging drawer.
|
||||
class Dynamics_DebugDrawer : public btIDebugDraw
|
||||
{
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT Dynamics_DebugDrawer();
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Dynamics_DebugDrawer();
|
||||
|
||||
//! Return TRUE if temporary presentations have been displayed (and not cleared) in Interactive Context.
|
||||
bool IsEmpty() const { return myTmpPrsList.IsEmpty(); }
|
||||
|
||||
//! Remove temporary presentations from context.
|
||||
Standard_EXPORT void FrameClear (AIS_InteractiveContext* theCtx);
|
||||
|
||||
//! Begin frame rendering.
|
||||
Standard_EXPORT void FrameBegin (const Handle(AIS_InteractiveContext)& theCtx);
|
||||
|
||||
//! End frame rendering.
|
||||
Standard_EXPORT void FrameEnd (const Handle(AIS_InteractiveContext)& theCtx);
|
||||
|
||||
public:
|
||||
|
||||
//! Draw the line segment.
|
||||
Standard_EXPORT virtual void drawLine (const btVector3& theFrom,
|
||||
const btVector3& theTo,
|
||||
const btVector3& theColor) Standard_OVERRIDE;
|
||||
|
||||
//! Draw the line segment.
|
||||
Standard_EXPORT virtual void drawLine (const btVector3& theFrom,
|
||||
const btVector3& theTo,
|
||||
const btVector3& theFromColor,
|
||||
const btVector3& theToColor) Standard_OVERRIDE;
|
||||
|
||||
//! Draw contact point.
|
||||
Standard_EXPORT virtual void drawContactPoint (const btVector3& thePointOnB,
|
||||
const btVector3& theNormalOnB,
|
||||
btScalar theDistance,
|
||||
int theLifeTime,
|
||||
const btVector3& theColor) Standard_OVERRIDE;
|
||||
|
||||
//! Print message.
|
||||
Standard_EXPORT virtual void reportErrorWarning (const char* theWarningString) Standard_OVERRIDE;
|
||||
|
||||
//! Draw text.
|
||||
Standard_EXPORT virtual void draw3dText (const btVector3& theLocation,
|
||||
const char* theTextString) Standard_OVERRIDE;
|
||||
|
||||
//! Return debug mode.
|
||||
virtual int getDebugMode() const Standard_OVERRIDE { return myDebugMode; }
|
||||
|
||||
//! Set debug mode.
|
||||
virtual void setDebugMode (int theDebugMode) Standard_OVERRIDE { myDebugMode = theDebugMode; }
|
||||
|
||||
private:
|
||||
|
||||
class Dynamics_DebugPrs;
|
||||
|
||||
private:
|
||||
|
||||
Handle(Dynamics_DebugPrs) myTmpPrs;
|
||||
NCollection_Sequence<Handle(AIS_InteractiveObject)> myTmpPrsList;
|
||||
Graphic3d_ZLayerId myZLayer;
|
||||
Standard_Integer myDebugMode;
|
||||
|
||||
};
|
||||
|
||||
#endif // _Dynamics_DebugDrawer_HeaderFile
|
131
src/Dynamics/Dynamics_Graphic3dTriangulation.cxx
Normal file
131
src/Dynamics/Dynamics_Graphic3dTriangulation.cxx
Normal file
@@ -0,0 +1,131 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_Graphic3dTriangulation.hxx>
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_Graphic3dTriangulation
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_Graphic3dTriangulation::Dynamics_Graphic3dTriangulation (const Handle(Graphic3d_ArrayOfTriangles)& theTris)
|
||||
: myPosOffset (0)
|
||||
{
|
||||
if (!theTris.IsNull())
|
||||
{
|
||||
myVerts = theTris->Attributes();
|
||||
myIndices = theTris->Indices();
|
||||
}
|
||||
|
||||
if (myVerts.IsNull()
|
||||
|| myIndices.IsNull()
|
||||
|| !(myIndices->Stride == 2 || myIndices->Stride == 4))
|
||||
{
|
||||
throw Standard_ProgramError ("Dynamics_Graphic3dTriangulation constructor called with NULL object!");
|
||||
}
|
||||
|
||||
bool hasPos = false;
|
||||
myPosOffset = 0;
|
||||
for (Standard_Integer anAttribIter = 0; anAttribIter < myVerts->NbAttributes; ++anAttribIter)
|
||||
{
|
||||
const Graphic3d_Attribute& anAttrib = myVerts->Attribute (anAttribIter);
|
||||
if (anAttrib.Id == Graphic3d_TOA_POS)
|
||||
{
|
||||
if (anAttrib.DataType != Graphic3d_TOD_VEC3
|
||||
&& anAttrib.DataType != Graphic3d_TOD_VEC4)
|
||||
{
|
||||
throw Standard_ProgramError ("Dynamics_Graphic3dTriangulation constructor called with unsupported data!");
|
||||
}
|
||||
hasPos = true;
|
||||
break;
|
||||
}
|
||||
|
||||
myPosOffset += Graphic3d_Attribute::Stride (anAttrib.DataType);
|
||||
}
|
||||
if (!hasPos)
|
||||
{
|
||||
throw Standard_ProgramError ("Dynamics_Graphic3dTriangulation constructor called with NULL object!");
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Dynamics_Graphic3dTriangulation
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_Graphic3dTriangulation::~Dynamics_Graphic3dTriangulation()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : getLockedVertexIndexBase
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Graphic3dTriangulation::getLockedVertexIndexBase (unsigned char** theVertexBase,
|
||||
int& theNbVerts,
|
||||
PHY_ScalarType& theType,
|
||||
int& theStride,
|
||||
unsigned char** theIndexBase,
|
||||
int& theIndexStride,
|
||||
int& theNbFaces,
|
||||
PHY_ScalarType& theIndicesType,
|
||||
int theSubPart)
|
||||
{
|
||||
if (theSubPart != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
theType = PHY_FLOAT;
|
||||
theNbVerts = myVerts->NbElements;
|
||||
theStride = myVerts->Stride;
|
||||
*theVertexBase = myVerts->changeValue (0) + myPosOffset;
|
||||
|
||||
theIndicesType = myIndices->Stride == 2 ? PHY_SHORT : PHY_INTEGER;
|
||||
*theIndexBase = myIndices->changeValue (0);
|
||||
theNbFaces = myIndices->NbElements / 3;
|
||||
theIndexStride = myIndices->Stride * 3;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : getLockedReadOnlyVertexIndexBase
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_Graphic3dTriangulation::getLockedReadOnlyVertexIndexBase (const unsigned char** theVertexBase,
|
||||
int& theNbVerts,
|
||||
PHY_ScalarType& theType,
|
||||
int& theStride,
|
||||
const unsigned char** theIndexBase,
|
||||
int& theIndexStride,
|
||||
int& theNbFaces,
|
||||
PHY_ScalarType& theIndicesType,
|
||||
int theSubPart) const
|
||||
{
|
||||
if (theSubPart != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
theType = PHY_FLOAT;
|
||||
theNbVerts = myVerts->NbElements;
|
||||
theStride = myVerts->Stride;
|
||||
*theVertexBase = myVerts->value (0) + myPosOffset;
|
||||
|
||||
theIndicesType = myIndices->Stride == 2 ? PHY_SHORT : PHY_INTEGER;
|
||||
*theIndexBase = myIndices->value (0);
|
||||
theNbFaces = myIndices->NbElements / 3;
|
||||
theIndexStride = myIndices->Stride * 3;
|
||||
}
|
||||
|
||||
#endif // HAVE_BULLET
|
82
src/Dynamics/Dynamics_Graphic3dTriangulation.hxx
Normal file
82
src/Dynamics/Dynamics_Graphic3dTriangulation.hxx
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_Graphic3dTriangulation_HeaderFile
|
||||
#define _Dynamics_Graphic3dTriangulation_HeaderFile
|
||||
|
||||
#include <Dynamics_Internal.hxx>
|
||||
|
||||
#include <Graphic3d_ArrayOfTriangles.hxx>
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
|
||||
//! Interface for Graphic3d_ArrayOfTriangles defining continuous triangulation data.
|
||||
ATTRIBUTE_ALIGNED16(class) Dynamics_Graphic3dTriangulation : public btStridingMeshInterface
|
||||
{
|
||||
public:
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR()
|
||||
|
||||
//! Constructor.
|
||||
Standard_EXPORT Dynamics_Graphic3dTriangulation (const Handle(Graphic3d_ArrayOfTriangles)& theTris);
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Dynamics_Graphic3dTriangulation();
|
||||
|
||||
//! Get read/write access to a subpart of a triangle mesh.
|
||||
Standard_EXPORT virtual void getLockedVertexIndexBase (unsigned char** theVertexBase,
|
||||
int& theNbVerts,
|
||||
PHY_ScalarType& theType,
|
||||
int& theStride,
|
||||
unsigned char** theIndexBase,
|
||||
int& theIndexStride,
|
||||
int& theNbFaces,
|
||||
PHY_ScalarType& theIndicesType,
|
||||
int theSubPart) Standard_OVERRIDE;
|
||||
|
||||
//! Get read access to a subpart of a triangle mesh.
|
||||
Standard_EXPORT virtual void getLockedReadOnlyVertexIndexBase (const unsigned char** theVertexBase,
|
||||
int& theNbVerts,
|
||||
PHY_ScalarType& theType,
|
||||
int& theStride,
|
||||
const unsigned char** theIndexBase,
|
||||
int& theIndexStride,
|
||||
int& theNbFaces,
|
||||
PHY_ScalarType& theIndicesType,
|
||||
int theSubPart) const Standard_OVERRIDE;
|
||||
|
||||
//! Finishes the access to a subpart of the triangle mesh.
|
||||
virtual void unLockVertexBase (int theSubPart) Standard_OVERRIDE { (void )theSubPart; }
|
||||
virtual void unLockReadOnlyVertexBase (int theSubPart) const Standard_OVERRIDE { (void )theSubPart; }
|
||||
|
||||
//! Returns the number of seperate subparts; each subpart has a continuous array of vertices and indices.
|
||||
virtual int getNumSubParts() const Standard_OVERRIDE { return 1; }
|
||||
|
||||
virtual void preallocateVertices (int theNbVerts) Standard_OVERRIDE { (void )theNbVerts; }
|
||||
virtual void preallocateIndices (int theNbIndices) Standard_OVERRIDE { (void )theNbIndices; }
|
||||
|
||||
//virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||
//virtual bool hasPremadeAabb() const Standard_OVERRIDE { return false; }
|
||||
//virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const Standard_OVERRIDE;
|
||||
//virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const Standard_OVERRIDE
|
||||
|
||||
protected:
|
||||
|
||||
Handle(Graphic3d_Buffer) myVerts;
|
||||
Handle(Graphic3d_IndexBuffer) myIndices;
|
||||
size_t myPosOffset;
|
||||
|
||||
};
|
||||
|
||||
#endif // HAVE_BULLET
|
||||
|
||||
#endif // _Dynamics_Graphic3dTriangulation_HeaderFile
|
31
src/Dynamics/Dynamics_Internal.hxx
Normal file
31
src/Dynamics/Dynamics_Internal.hxx
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_Internal_HeaderFile
|
||||
#define _Dynamics_Internal_HeaderFile
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
#include <Standard_WarningsDisable.hxx>
|
||||
|
||||
#include <btBulletDynamicsCommon.h>
|
||||
//#include <BulletCollision/Gimpact/btGImpactShape.h>
|
||||
#include <BulletCollision/CollisionDispatch/btGhostObject.h>
|
||||
#include <BulletCollision/CollisionShapes/btShapeHull.h>
|
||||
#include <BulletDynamics/Character/btKinematicCharacterController.h>
|
||||
|
||||
#include <Standard_WarningsRestore.hxx>
|
||||
#else
|
||||
class btTransform {};
|
||||
#endif
|
||||
|
||||
#endif // _Dynamics_Internal_HeaderFile
|
169
src/Dynamics/Dynamics_MotionState.cxx
Normal file
169
src/Dynamics/Dynamics_MotionState.cxx
Normal file
@@ -0,0 +1,169 @@
|
||||
// Copyright (c) 2018-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_MotionState.hxx>
|
||||
|
||||
#include <Dynamics_Internal.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_MotionState, Standard_Transient)
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
ATTRIBUTE_ALIGNED16(struct) Dynamics_MotionState::Dynamics_MotionStateProxy : public btDefaultMotionState
|
||||
{
|
||||
Dynamics_MotionStateProxy (Dynamics_MotionState* theHolder,
|
||||
const btTransform& theStartTrans = btTransform::getIdentity(),
|
||||
const btTransform& theCenterOfMassOffset = btTransform::getIdentity(),
|
||||
const gp_Trsf& thePrsOffset = gp_Trsf())
|
||||
: btDefaultMotionState (theStartTrans, theCenterOfMassOffset),
|
||||
myHolder (theHolder),
|
||||
myPrsOffset (thePrsOffset) {}
|
||||
|
||||
virtual void setWorldTransform (const btTransform& theCenterOfMassWorldTrans) Standard_OVERRIDE
|
||||
{
|
||||
btDefaultMotionState::setWorldTransform (theCenterOfMassWorldTrans);
|
||||
|
||||
btTransform aTrsfBt;
|
||||
getWorldTransform (aTrsfBt);
|
||||
|
||||
gp_Trsf aTrsf;
|
||||
Dynamics_MotionState::TrsfGpFromBt (aTrsf, aTrsfBt);
|
||||
aTrsf *= myPrsOffset;
|
||||
myHolder->setWorldTransform (aTrsf);
|
||||
}
|
||||
private:
|
||||
Dynamics_MotionState* myHolder;
|
||||
gp_Trsf myPrsOffset;
|
||||
};
|
||||
#endif
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_MotionState
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_MotionState::Dynamics_MotionState()
|
||||
: myMotionState (NULL),
|
||||
myToDisplaceCenterOfMass (false)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Dynamics_MotionState
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_MotionState::~Dynamics_MotionState()
|
||||
{
|
||||
releaseMotionState();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : InitProxy
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_MotionState::InitProxy (const gp_Trsf& theStartTrans,
|
||||
const gp_Trsf& theCenterOfMassOffset,
|
||||
const gp_Trsf& thePrsOffset)
|
||||
{
|
||||
releaseMotionState();
|
||||
#ifdef HAVE_BULLET
|
||||
btTransform aTrsfBt, aMassOffsetBt;
|
||||
Dynamics_MotionState::TrsfBtFromGp (aTrsfBt, theStartTrans);
|
||||
Dynamics_MotionState::TrsfBtFromGp (aMassOffsetBt, theCenterOfMassOffset);
|
||||
myMotionState = new Dynamics_MotionStateProxy (this, aTrsfBt, aMassOffsetBt, thePrsOffset);
|
||||
#else
|
||||
(void )theStartTrans;
|
||||
(void )theCenterOfMassOffset;
|
||||
(void )thePrsOffset;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : InitDefault
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_MotionState::InitDefault (const btTransform& theStartTrans,
|
||||
const btTransform& theCenterOfMassOffset)
|
||||
{
|
||||
releaseMotionState();
|
||||
#ifdef HAVE_BULLET
|
||||
myMotionState = new btDefaultMotionState (theStartTrans, theCenterOfMassOffset);
|
||||
#else
|
||||
(void )theStartTrans;
|
||||
(void )theCenterOfMassOffset;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : setWorldTransform
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_MotionState::setWorldTransform (const gp_Trsf& theTrsf)
|
||||
{
|
||||
(void )theTrsf;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : releaseMotionState
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_MotionState::releaseMotionState()
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
delete myMotionState;
|
||||
#endif
|
||||
myMotionState = NULL;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : TrsfGpFromBt
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_MotionState::TrsfGpFromBt (gp_Trsf& theLoc, const btTransform& theTrsf)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
const btVector3& anOrigin = theTrsf.getOrigin();
|
||||
const btMatrix3x3& aMat3bt = theTrsf.getBasis();
|
||||
theLoc.SetValues (aMat3bt.getRow (0).x(), aMat3bt.getRow (0).y(), aMat3bt.getRow (0).z(), anOrigin.x(),
|
||||
aMat3bt.getRow (1).x(), aMat3bt.getRow (1).y(), aMat3bt.getRow (1).z(), anOrigin.y(),
|
||||
aMat3bt.getRow (2).x(), aMat3bt.getRow (2).y(), aMat3bt.getRow (2).z(), anOrigin.z());
|
||||
#else
|
||||
(void )theTrsf;
|
||||
(void )theLoc;
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : TrsfBtFromGp
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_MotionState::TrsfBtFromGp (btTransform& theTrsf, const gp_Trsf& theLoc)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
theTrsf.setIdentity();
|
||||
if (theLoc.Form() == gp_Identity)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const gp_Mat aMat3 = theLoc.VectorialPart();
|
||||
btVector3 anOrigin (btScalar (theLoc.TranslationPart().X()), btScalar (theLoc.TranslationPart().Y()), btScalar (theLoc.TranslationPart().Z()));
|
||||
btMatrix3x3 aMat3bt (btScalar (aMat3.Value (1, 1)), btScalar (aMat3.Value (1, 2)), btScalar (aMat3.Value (1, 3)),
|
||||
btScalar (aMat3.Value (2, 1)), btScalar (aMat3.Value (2, 2)), btScalar (aMat3.Value (2, 3)),
|
||||
btScalar (aMat3.Value (3, 1)), btScalar (aMat3.Value (3, 2)), btScalar (aMat3.Value (3, 3)));
|
||||
theTrsf.setOrigin(anOrigin);
|
||||
theTrsf.setBasis (aMat3bt);
|
||||
#else
|
||||
(void )theTrsf;
|
||||
(void )theLoc;
|
||||
#endif
|
||||
}
|
86
src/Dynamics/Dynamics_MotionState.hxx
Normal file
86
src/Dynamics/Dynamics_MotionState.hxx
Normal file
@@ -0,0 +1,86 @@
|
||||
// Copyright (c) 2018-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_MotionState_HeaderFile
|
||||
#define _Dynamics_MotionState_HeaderFile
|
||||
|
||||
#include <gp_Trsf.hxx>
|
||||
#include <Standard_Transient.hxx>
|
||||
#include <Standard_Type.hxx>
|
||||
|
||||
class btMotionState;
|
||||
class btTransform;
|
||||
|
||||
//! Define the motion state.
|
||||
class Dynamics_MotionState : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_MotionState, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Convert transformation definition from OCCT to Bullet structure.
|
||||
Standard_EXPORT static void TrsfBtFromGp (btTransform& theTrsf, const gp_Trsf& theLoc);
|
||||
|
||||
//! Convert transformation definition from Bullet to OCCT structure.
|
||||
Standard_EXPORT static void TrsfGpFromBt (gp_Trsf& theLoc, const btTransform& theTrsf);
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT Dynamics_MotionState();
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Dynamics_MotionState();
|
||||
|
||||
//! Create a proxy motion state.
|
||||
//! @param theStartTrans initial transformation
|
||||
//! @param theCenterOfMassOffset offset to the center of mass
|
||||
//! @param thePrsOffset optional transformation from collision shape to presentation shape
|
||||
Standard_EXPORT void InitProxy (const gp_Trsf& theStartTrans,
|
||||
const gp_Trsf& theCenterOfMassOffset,
|
||||
const gp_Trsf& thePrsOffset = gp_Trsf());
|
||||
|
||||
//! Create a default motion state.
|
||||
Standard_EXPORT void InitDefault (const btTransform& theStartTrans,
|
||||
const btTransform& theCenterOfMassOffset);
|
||||
|
||||
//! Return true if motion state is defined.
|
||||
bool IsValid() const { return myMotionState != NULL; }
|
||||
|
||||
//! Return motion state pointer.
|
||||
btMotionState* MotionState() const { return myMotionState; }
|
||||
|
||||
//! Option displaying center of mass; FALSE by default.
|
||||
bool ToDisplaceCenterOfMass() const { return myToDisplaceCenterOfMass; }
|
||||
|
||||
//! Set option displaying center of mass.
|
||||
void SetDisplaceCenterOfMass (bool theToDisplace) { myToDisplaceCenterOfMass = theToDisplace; }
|
||||
|
||||
protected:
|
||||
|
||||
//! Virtual callback.
|
||||
Standard_EXPORT virtual void setWorldTransform (const gp_Trsf& theTrsf);
|
||||
|
||||
//! Release memory.
|
||||
Standard_EXPORT void releaseMotionState();
|
||||
|
||||
protected:
|
||||
//! Proxy btMotionState implementation.
|
||||
struct Dynamics_MotionStateProxy;
|
||||
|
||||
protected:
|
||||
|
||||
btMotionState* myMotionState;
|
||||
bool myToDisplaceCenterOfMass;
|
||||
|
||||
};
|
||||
|
||||
#endif // _Dynamics_MotionState_HeaderFile
|
31
src/Dynamics/Dynamics_Parameters.cxx
Normal file
31
src/Dynamics/Dynamics_Parameters.cxx
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_Parameters.hxx>
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_Parameters, Standard_Transient)
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_Parameters
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_Parameters::Dynamics_Parameters()
|
||||
: myRigidBodyYaw (-1),
|
||||
myRigidBodyPitch (15),
|
||||
myRigidBodyRoll (15),
|
||||
myFirstPersonHeight (1.75f),
|
||||
myFirstPersonWidth (0.46f),
|
||||
myFirstPersonStepHeight (0.35f)
|
||||
{
|
||||
//
|
||||
}
|
78
src/Dynamics/Dynamics_Parameters.hxx
Normal file
78
src/Dynamics/Dynamics_Parameters.hxx
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_Parameters_HeaderFile
|
||||
#define _Dynamics_Parameters_HeaderFile
|
||||
|
||||
#include <Standard_Type.hxx>
|
||||
|
||||
//! Class defining global dynamics parameters.
|
||||
class Dynamics_Parameters : public Standard_Transient
|
||||
{
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_Parameters, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Empty constructor.
|
||||
Standard_EXPORT Dynamics_Parameters();
|
||||
|
||||
//! Return rigid body yaw constraint in degrees; -1 by default.
|
||||
//! -1 means no constraint.
|
||||
int RigidBodyYawConstraint() const { return myRigidBodyYaw; }
|
||||
|
||||
//! Set rigid body yaw constraint in degrees.
|
||||
void SetRigidBodyYawConstraint (int theAngle) { myRigidBodyYaw = theAngle; }
|
||||
|
||||
//! Return rigid body pitch constraint in degrees; 15 degrees by default.
|
||||
//! -1 means no constraint.
|
||||
int RigidBodyPitchConstraint() const { return myRigidBodyPitch; }
|
||||
|
||||
//! Set rigid body pitch constraint in degrees.
|
||||
void SetRigidBodyPitchConstraint (int theAngle) { myRigidBodyPitch = theAngle; }
|
||||
|
||||
//! Return rigid body roll constraint in degrees; 15 degrees by default.
|
||||
//! -1 means no constraint.
|
||||
int RigidBodyRollConstraint() const { return myRigidBodyRoll; }
|
||||
|
||||
//! Set rigid body roll constraint in degrees.
|
||||
void SetRigidBodyRollConstraint (int theAngle) { myRigidBodyRoll = theAngle; }
|
||||
|
||||
//! Return height of first person capsule, in meters; 1.75 by default.
|
||||
float FirstPersonHeight() const { return myFirstPersonHeight; }
|
||||
|
||||
//! Set height of first person capsule.
|
||||
void SetFirstPersonHeight (float theHeight) { myFirstPersonHeight = theHeight; }
|
||||
|
||||
//! Return width (diameter) of first person capsule, in meters; 0.46 by default.
|
||||
float FirstPersonWidth() const { return myFirstPersonWidth; }
|
||||
|
||||
//! Set width of first person capsule.
|
||||
void SetFirstPersonWidth (float theWidth) { myFirstPersonWidth = theWidth; }
|
||||
|
||||
//! Return step height of first person, in meters; 0.35 by default.
|
||||
float FirstPersonStepHeight() const { return myFirstPersonStepHeight; }
|
||||
|
||||
//! Set step height of first person.
|
||||
void SetFirstPersonStepHeight (float theStepHeight) { myFirstPersonStepHeight = theStepHeight; }
|
||||
|
||||
protected:
|
||||
|
||||
int myRigidBodyYaw; //!< rigid body yaw constraint
|
||||
int myRigidBodyPitch; //!< rigid body pitch constraint
|
||||
int myRigidBodyRoll; //!< rigid body roll constraint
|
||||
float myFirstPersonHeight; //!< height of first person capsule, in meters
|
||||
float myFirstPersonWidth; //!< width (diameter) of first person capsule, in meters
|
||||
float myFirstPersonStepHeight; //!< step height of first person, in meters
|
||||
|
||||
};
|
||||
|
||||
#endif // _Dynamics_Parameters_HeaderFile
|
102
src/Dynamics/Dynamics_PolyTriangulation.cxx
Normal file
102
src/Dynamics/Dynamics_PolyTriangulation.cxx
Normal file
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_PolyTriangulation.hxx>
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_PolyTriangulation
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_PolyTriangulation::Dynamics_PolyTriangulation (const Handle(Poly_Triangulation)& thePolyTri)
|
||||
: myPolyTri (thePolyTri)
|
||||
{
|
||||
if (myPolyTri.IsNull())
|
||||
{
|
||||
throw Standard_ProgramError ("Dynamics_PolyTriangulation constructor called with NULL object!");
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Dynamics_PolyTriangulation
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_PolyTriangulation::~Dynamics_PolyTriangulation()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : getLockedVertexIndexBase
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_PolyTriangulation::getLockedVertexIndexBase (unsigned char** theVertexBase,
|
||||
int& theNbVerts,
|
||||
PHY_ScalarType& theType,
|
||||
int& theStride,
|
||||
unsigned char** theIndexBase,
|
||||
int& theIndexStride,
|
||||
int& theNbFaces,
|
||||
PHY_ScalarType& theIndicesType,
|
||||
int theSubPart)
|
||||
{
|
||||
if (theSubPart != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
theType = myPolyTri->InternalNodes().IsDoublePrecision() ? PHY_DOUBLE : PHY_FLOAT;
|
||||
theNbVerts = myPolyTri->NbNodes();
|
||||
theStride = myPolyTri->InternalNodes().Stride();
|
||||
*theVertexBase = reinterpret_cast<unsigned char* >(myPolyTri->InternalNodes().changeValue (0))
|
||||
- theStride; // step back since indexation starts with 1 in Poly_Triangulation
|
||||
|
||||
theIndicesType = PHY_INTEGER;
|
||||
*theIndexBase = reinterpret_cast<unsigned char* >(&myPolyTri->InternalTriangles().ChangeFirst());
|
||||
theNbFaces = myPolyTri->NbTriangles();
|
||||
theIndexStride = sizeof(Poly_Triangle);
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : getLockedReadOnlyVertexIndexBase
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_PolyTriangulation::getLockedReadOnlyVertexIndexBase (const unsigned char** theVertexBase,
|
||||
int& theNbVerts,
|
||||
PHY_ScalarType& theType,
|
||||
int& theStride,
|
||||
const unsigned char** theIndexBase,
|
||||
int& theIndexStride,
|
||||
int& theNbFaces,
|
||||
PHY_ScalarType& theIndicesType,
|
||||
int theSubPart) const
|
||||
{
|
||||
if (theSubPart != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
theType = myPolyTri->InternalNodes().IsDoublePrecision() ? PHY_DOUBLE : PHY_FLOAT;
|
||||
theNbVerts = myPolyTri->NbNodes();
|
||||
theStride = myPolyTri->InternalNodes().Stride();
|
||||
*theVertexBase = reinterpret_cast<const unsigned char* >(myPolyTri->InternalNodes().changeValue (0))
|
||||
- theStride; // step back since indexation starts with 1 in Poly_Triangulation
|
||||
|
||||
theIndicesType = PHY_INTEGER;
|
||||
*theIndexBase = reinterpret_cast<const unsigned char* >(&myPolyTri->InternalTriangles().First());
|
||||
theNbFaces = myPolyTri->NbTriangles();
|
||||
theIndexStride = sizeof(Poly_Triangle);
|
||||
}
|
||||
|
||||
#endif // HAVE_BULLET
|
80
src/Dynamics/Dynamics_PolyTriangulation.hxx
Normal file
80
src/Dynamics/Dynamics_PolyTriangulation.hxx
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_PolyTriangulation_HeaderFile
|
||||
#define _Dynamics_PolyTriangulation_HeaderFile
|
||||
|
||||
#include <Poly_Triangulation.hxx>
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
|
||||
#include <Dynamics_Internal.hxx>
|
||||
|
||||
//! Interface for Poly_Triangulation defining continuous triangulation data.
|
||||
ATTRIBUTE_ALIGNED16(class) Dynamics_PolyTriangulation : public btStridingMeshInterface
|
||||
{
|
||||
public:
|
||||
BT_DECLARE_ALIGNED_ALLOCATOR()
|
||||
|
||||
//! Constructor.
|
||||
Standard_EXPORT Dynamics_PolyTriangulation (const Handle(Poly_Triangulation)& thePolyTri);
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Dynamics_PolyTriangulation();
|
||||
|
||||
//! Get read/write access to a subpart of a triangle mesh.
|
||||
Standard_EXPORT virtual void getLockedVertexIndexBase (unsigned char** theVertexBase,
|
||||
int& theNbVerts,
|
||||
PHY_ScalarType& theType,
|
||||
int& theStride,
|
||||
unsigned char** theIndexBase,
|
||||
int& theIndexStride,
|
||||
int& theNbFaces,
|
||||
PHY_ScalarType& theIndicesType,
|
||||
int theSubPart) Standard_OVERRIDE;
|
||||
|
||||
//! Get read access to a subpart of a triangle mesh.
|
||||
Standard_EXPORT virtual void getLockedReadOnlyVertexIndexBase (const unsigned char** theVertexBase,
|
||||
int& theNbVerts,
|
||||
PHY_ScalarType& theType,
|
||||
int& theStride,
|
||||
const unsigned char** theIndexBase,
|
||||
int& theIndexStride,
|
||||
int& theNbFaces,
|
||||
PHY_ScalarType& theIndicesType,
|
||||
int theSubPart) const Standard_OVERRIDE;
|
||||
|
||||
//! Finishes the access to a subpart of the triangle mesh.
|
||||
virtual void unLockVertexBase (int theSubPart) Standard_OVERRIDE { (void )theSubPart; }
|
||||
virtual void unLockReadOnlyVertexBase (int theSubPart) const Standard_OVERRIDE { (void )theSubPart; }
|
||||
|
||||
//! Returns the number of separate subparts; each subpart has a continuous array of vertices and indices.
|
||||
virtual int getNumSubParts() const Standard_OVERRIDE { return 1; }
|
||||
|
||||
virtual void preallocateVertices (int theNbVerts) Standard_OVERRIDE { (void )theNbVerts; }
|
||||
virtual void preallocateIndices (int theNbIndices) Standard_OVERRIDE { (void )theNbIndices; }
|
||||
|
||||
//virtual void InternalProcessAllTriangles(btInternalTriangleIndexCallback* callback,const btVector3& aabbMin,const btVector3& aabbMax) const;
|
||||
//virtual bool hasPremadeAabb() const Standard_OVERRIDE { return false; }
|
||||
//virtual void setPremadeAabb(const btVector3& aabbMin, const btVector3& aabbMax ) const Standard_OVERRIDE;
|
||||
//virtual void getPremadeAabb(btVector3* aabbMin, btVector3* aabbMax ) const Standard_OVERRIDE
|
||||
|
||||
protected:
|
||||
|
||||
Handle(Poly_Triangulation) myPolyTri;
|
||||
|
||||
};
|
||||
|
||||
#endif // HAVE_BULLET
|
||||
|
||||
#endif // _Dynamics_PolyTriangulation_HeaderFile
|
312
src/Dynamics/Dynamics_World.cxx
Normal file
312
src/Dynamics/Dynamics_World.cxx
Normal file
@@ -0,0 +1,312 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#include <Dynamics_World.hxx>
|
||||
|
||||
#include <Dynamics_Internal.hxx>
|
||||
#include <Dynamics_CollisionPlane.hxx>
|
||||
#include <Dynamics_Constraint.hxx>
|
||||
#include <Dynamics_Parameters.hxx>
|
||||
|
||||
#include <gp_Pln.hxx>
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
#include <Dynamics_DebugDrawer.hxx>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#ifdef NDEBUG
|
||||
#pragma comment(lib, "BulletDynamics.lib")
|
||||
#pragma comment(lib, "BulletCollision.lib")
|
||||
#pragma comment(lib, "LinearMath.lib")
|
||||
#else
|
||||
#pragma comment(lib, "BulletDynamics_Debug.lib")
|
||||
#pragma comment(lib, "BulletCollision_Debug.lib")
|
||||
#pragma comment(lib, "LinearMath_Debug.lib")
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
IMPLEMENT_STANDARD_RTTIEXT(Dynamics_World, Standard_Transient)
|
||||
|
||||
// =======================================================================
|
||||
// function : Dynamics_World
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_World::Dynamics_World (const Handle(Dynamics_Parameters)& theDefaultStyle) :
|
||||
#ifdef HAVE_BULLET
|
||||
myGhostPairCallback (new btGhostPairCallback()),
|
||||
myCollisionConfiguration (new btDefaultCollisionConfiguration()),
|
||||
myOverlappingPairCache (new btDbvtBroadphase()),
|
||||
mySolver (new btSequentialImpulseConstraintSolver()),
|
||||
myCharacter (new Dynamics_Character()),
|
||||
myGround (new Dynamics_CollisionBody()),
|
||||
#endif
|
||||
myLengthUnitScale (1.0),
|
||||
myLastWorldTick (0.0),
|
||||
myFixedTimeStep (1.0 / 120.0),
|
||||
myNbMaxSubTicks (20),
|
||||
myNbRigidBodies (0)
|
||||
{
|
||||
myDefaultDrawer = theDefaultStyle;
|
||||
if (theDefaultStyle.IsNull())
|
||||
{
|
||||
myDefaultDrawer = new Dynamics_Parameters();
|
||||
}
|
||||
#ifdef HAVE_BULLET
|
||||
myCharacter->Init (theDefaultStyle->FirstPersonHeight(), theDefaultStyle->FirstPersonWidth(), theDefaultStyle->FirstPersonStepHeight());
|
||||
myOverlappingPairCache->getOverlappingPairCache()->setInternalGhostPairCallback (myGhostPairCallback.get());
|
||||
myDispatcher.reset (new btCollisionDispatcher (myCollisionConfiguration.get()));
|
||||
myDynamicsWorld.reset (new btDiscreteDynamicsWorld (myDispatcher.get(), myOverlappingPairCache.get(), mySolver.get(), myCollisionConfiguration.get()));
|
||||
myDynamicsWorld->setGravity (btVector3 (0.0f, 0.0f, btScalar(-9.8 * myLengthUnitScale)));
|
||||
|
||||
myGround->addToWorld (this);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : ~Dynamics_World
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
Dynamics_World::~Dynamics_World()
|
||||
{
|
||||
for (NCollection_IndexedMap<Handle(Dynamics_Constraint)>::Iterator aConstrIter (myConstraints); aConstrIter.More(); aConstrIter.Next())
|
||||
{
|
||||
aConstrIter.Value()->removeFromWorld();
|
||||
}
|
||||
for (NCollection_IndexedMap<Handle(Dynamics_CollisionBody)>::Iterator aBodyIter (myCollisionBodies); aBodyIter.More(); aBodyIter.Next())
|
||||
{
|
||||
aBodyIter.Value()->removeFromWorld();
|
||||
}
|
||||
if (!myCharacter.IsNull())
|
||||
{
|
||||
myCharacter->removeFromWorld();
|
||||
}
|
||||
if (!myGround.IsNull())
|
||||
{
|
||||
myGround->removeFromWorld();
|
||||
}
|
||||
myConstraints.Clear();
|
||||
myCollisionBodies.Clear();
|
||||
myCharacter.Nullify();
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
myDynamicsWorld.reset();
|
||||
mySolver.reset();
|
||||
myOverlappingPairCache.reset();
|
||||
myDispatcher.reset();
|
||||
myCollisionConfiguration.reset();
|
||||
myGhostPairCallback.reset();
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : UpdateFirstPersonSize
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_World::UpdateFirstPersonSize()
|
||||
{
|
||||
if (!myCharacter.IsNull())
|
||||
{
|
||||
myCharacter->Init (myLengthUnitScale * myDefaultDrawer->FirstPersonHeight(), myLengthUnitScale * myDefaultDrawer->FirstPersonWidth(), myLengthUnitScale * myDefaultDrawer->FirstPersonStepHeight());
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetLengthUnitScale
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_World::SetLengthUnitScale (double theScale)
|
||||
{
|
||||
myLengthUnitScale = theScale;
|
||||
#ifdef HAVE_BULLET
|
||||
myDynamicsWorld->setGravity (btVector3 (0.0f, 0.0f, btScalar(-9.8 * myLengthUnitScale)));
|
||||
#endif
|
||||
UpdateFirstPersonSize();
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetSceneBoundaries
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_World::SetSceneBoundaries (const Bnd_Box& theBndBox)
|
||||
{
|
||||
mySceneBox = theBndBox;
|
||||
if (mySceneBox.IsVoid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_BULLET
|
||||
const gp_XYZ aMin = mySceneBox.CornerMin().XYZ();
|
||||
const gp_XYZ aMax = mySceneBox.CornerMax().XYZ();
|
||||
gp_XYZ aCenter = (aMin + aMax) * 0.5;
|
||||
aCenter.SetZ (aMin.Z());
|
||||
|
||||
gp_Pln aPlane (gp_Pnt (0.0, 0.0, 0.0), gp_Dir (0.0, 0.0, 1.0));
|
||||
Handle(Dynamics_CollisionPlane) aPlaneShape = new Dynamics_CollisionPlane (aPlane);
|
||||
|
||||
gp_Trsf aTrsf;
|
||||
aTrsf.SetTranslation (gp_Vec (aCenter));
|
||||
myGround->SetShape (aPlaneShape, aTrsf);
|
||||
#endif
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : AddCollisionBody
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_World::AddCollisionBody (const Handle(Dynamics_CollisionBody)& theBody)
|
||||
{
|
||||
const int anExtendOld = myCollisionBodies.Extent();
|
||||
if (myCollisionBodies.Add (theBody) > anExtendOld)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
theBody->addToWorld (this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : RemoveCollisionBody
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_World::RemoveCollisionBody (const Handle(Dynamics_CollisionBody)& theBody)
|
||||
{
|
||||
Handle(Dynamics_CollisionBody) aTmpCopy = theBody;
|
||||
if (myCollisionBodies.RemoveKey (theBody))
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
theBody->removeFromWorld();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : AddConstraint
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_World::AddConstraint (const Handle(Dynamics_Constraint)& theConstraint)
|
||||
{
|
||||
const int anExtendOld = myConstraints.Extent();
|
||||
if (myConstraints.Add (theConstraint) > anExtendOld)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
theConstraint->addToWorld (this);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : RemoveConstraint
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_World::RemoveConstraint (const Handle(Dynamics_Constraint)& theConstraint)
|
||||
{
|
||||
Handle(Dynamics_Constraint) aTmpCopy = theConstraint;
|
||||
if (myConstraints.RemoveKey (theConstraint))
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
theConstraint->removeFromWorld();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetPaused
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
void Dynamics_World::SetPaused (bool theToPause)
|
||||
{
|
||||
if (IsPaused() == theToPause)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (theToPause)
|
||||
{
|
||||
myWorldTimer.Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
myWorldTimer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : SetEnableDebugDrawer
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Dynamics_World::SetEnableDebugDrawer (bool theToDebug,
|
||||
AIS_InteractiveContext* theCtx)
|
||||
{
|
||||
#ifdef HAVE_BULLET
|
||||
if (theToDebug)
|
||||
{
|
||||
if (myDebugDrawer.get() == nullptr)
|
||||
{
|
||||
myDebugDrawer.reset (new Dynamics_DebugDrawer());
|
||||
myDynamicsWorld->setDebugDrawer (myDebugDrawer.get());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (myDebugDrawer.get() != nullptr)
|
||||
{
|
||||
const bool toUpdate = !myDebugDrawer->IsEmpty();
|
||||
myDynamicsWorld->setDebugDrawer (nullptr);
|
||||
myDebugDrawer->FrameClear (theCtx);
|
||||
myDebugDrawer.reset();
|
||||
return toUpdate;
|
||||
}
|
||||
#else
|
||||
(void )theToDebug;
|
||||
(void )theCtx;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// =======================================================================
|
||||
// function : StepSimulation
|
||||
// purpose :
|
||||
// =======================================================================
|
||||
bool Dynamics_World::StepSimulation (const Handle(AIS_InteractiveContext)& theCtx)
|
||||
{
|
||||
const double aTime = myWorldTimer.ElapsedTime();
|
||||
const double aTimeDiff = aTime - myLastWorldTick;
|
||||
SetPaused (false);
|
||||
if (Abs (aTimeDiff - myLastWorldTick) < gp::Resolution())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
myLastWorldTick = aTime;
|
||||
#ifdef HAVE_BULLET
|
||||
if (myDynamicsWorld->stepSimulation (btScalar(aTimeDiff), myNbMaxSubTicks, btScalar(myFixedTimeStep)) <= 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Dynamics_DebugDrawer* aDebugDraw = myDebugDrawer.get())
|
||||
{
|
||||
if (!theCtx.IsNull())
|
||||
{
|
||||
aDebugDraw->FrameBegin (theCtx);
|
||||
myDynamicsWorld->debugDrawWorld();
|
||||
aDebugDraw->FrameEnd (theCtx);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
(void )theCtx;
|
||||
return false;
|
||||
#endif
|
||||
}
|
143
src/Dynamics/Dynamics_World.hxx
Normal file
143
src/Dynamics/Dynamics_World.hxx
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright (c) 2017-2021 OPEN CASCADE SAS
|
||||
//
|
||||
// This file is part of Open CASCADE Technology software library.
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU Lesser General Public License version 2.1 as published
|
||||
// by the Free Software Foundation, with special exception defined in the file
|
||||
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
|
||||
// distribution for complete text of the license and disclaimer of any warranty.
|
||||
//
|
||||
// Alternatively, this file may be used under the terms of Open CASCADE
|
||||
// commercial license or contractual agreement.
|
||||
|
||||
#ifndef _Dynamics_World_HeaderFile
|
||||
#define _Dynamics_World_HeaderFile
|
||||
|
||||
#include <Dynamics_CollisionBody.hxx>
|
||||
#include <Dynamics_Character.hxx>
|
||||
|
||||
#include <Bnd_Box.hxx>
|
||||
#include <NCollection_IndexedMap.hxx>
|
||||
#include <OSD_Timer.hxx>
|
||||
|
||||
class btBroadphaseInterface;
|
||||
class btCollisionDispatcher;
|
||||
class btDefaultCollisionConfiguration;
|
||||
class btDiscreteDynamicsWorld;
|
||||
class btGhostPairCallback;
|
||||
class btSequentialImpulseConstraintSolver;
|
||||
|
||||
class Dynamics_DebugDrawer;
|
||||
class Dynamics_Parameters;
|
||||
class AIS_InteractiveContext;
|
||||
|
||||
//! Physics engine - world holder.
|
||||
class Dynamics_World : public Standard_Transient
|
||||
{
|
||||
friend class Dynamics_CollisionBody;
|
||||
friend class Dynamics_Constraint;
|
||||
friend class Dynamics_Character;
|
||||
DEFINE_STANDARD_RTTIEXT(Dynamics_World, Standard_Transient)
|
||||
public:
|
||||
|
||||
//! Main constructor.
|
||||
Standard_EXPORT Dynamics_World (const Handle(Dynamics_Parameters)& theDefaultStyle = Handle(Dynamics_Parameters)());
|
||||
|
||||
//! Destructor.
|
||||
Standard_EXPORT virtual ~Dynamics_World();
|
||||
|
||||
//! Add collision body to the world.
|
||||
Standard_EXPORT void AddCollisionBody (const Handle(Dynamics_CollisionBody)& theBody);
|
||||
|
||||
//! Remove collision body from the world.
|
||||
Standard_EXPORT void RemoveCollisionBody (const Handle(Dynamics_CollisionBody)& theBody);
|
||||
|
||||
//! Add constraint to the world.
|
||||
Standard_EXPORT void AddConstraint (const Handle(Dynamics_Constraint)& theConstraint);
|
||||
|
||||
//! Remove constraint from the world.
|
||||
Standard_EXPORT void RemoveConstraint (const Handle(Dynamics_Constraint)& theConstraint);
|
||||
|
||||
//! Return the character object.
|
||||
const Handle(Dynamics_Character)& Character() const { return myCharacter; }
|
||||
|
||||
//! Return scene boundaries.
|
||||
const Bnd_Box& SceneBoundaries() const { return mySceneBox; }
|
||||
|
||||
//! Define scene boundaries.
|
||||
Standard_EXPORT void SetSceneBoundaries (const Bnd_Box& theBndBox);
|
||||
|
||||
//! Return length unit scale factor (as scale factor for meters); 1.0 by default.
|
||||
double LengthUnitScale() const { return myLengthUnitScale; }
|
||||
|
||||
//! Set length unit scale factor.
|
||||
Standard_EXPORT void SetLengthUnitScale (double theScale);
|
||||
|
||||
//! Update first-person capsule size basing on Drawer parameters.
|
||||
Standard_EXPORT void UpdateFirstPersonSize();
|
||||
|
||||
//! Return time step in seconds for computing dynamics within discrete math; 1/120 by default.
|
||||
double FixedTimeStep() const { return myFixedTimeStep; }
|
||||
|
||||
//! Setup time step in seconds.
|
||||
void SetFixedTimeStep (double theStepSeconds) { myFixedTimeStep = theStepSeconds; }
|
||||
|
||||
//! Return maximum number of sub steps in case if time increment is greater than fixed time step.
|
||||
//! 20 by default, which means that within default 1/120 fixed time step
|
||||
//! the playback should not be lower than 6 FPS for proper computations.
|
||||
int MaximumSubSteps() const { return myNbMaxSubTicks; }
|
||||
|
||||
//! Setup maximum number of sub steps in case if time increment is greater than fixed time step.
|
||||
void SetMaximumSubSteps (int theNbMaxSubTicks) { myNbMaxSubTicks = theNbMaxSubTicks; }
|
||||
|
||||
//! Return TRUE if world timer is in paused state; TRUE by default.
|
||||
bool IsPaused() const { return !myWorldTimer.IsStarted(); }
|
||||
|
||||
//! Start/pause world timer.
|
||||
//! Note that StepSimulation() will automatically resume timer!
|
||||
Standard_EXPORT void SetPaused (bool theToPause);
|
||||
|
||||
//! Proceed the simulation over Time step units.
|
||||
//! Note that if world timer was in paused state, it will be automatically resumed!
|
||||
//! @param theMaxSubSteps maximum number of sub-steps in case if time increment is greater then fixed time step
|
||||
//! @param theCtx interactive context for drawing debug information
|
||||
//! @return TRUE if simulation was updated
|
||||
Standard_EXPORT bool StepSimulation (const Handle(AIS_InteractiveContext)& theCtx);
|
||||
|
||||
//! Return TRUE if debug drawer is enabled.
|
||||
bool ToEnableDebugDrawer() const { return myDebugDrawer.get() != NULL; }
|
||||
|
||||
//! Set if debug drawer should be enabled/disabled.
|
||||
Standard_EXPORT bool SetEnableDebugDrawer (bool theToDebug,
|
||||
AIS_InteractiveContext* theCtx);
|
||||
|
||||
//! Return the number of registered rigid bodies.
|
||||
int NbRigidBodies() const { return myNbRigidBodies; }
|
||||
|
||||
protected:
|
||||
|
||||
std::shared_ptr<btGhostPairCallback> myGhostPairCallback;
|
||||
std::shared_ptr<btDefaultCollisionConfiguration> myCollisionConfiguration;
|
||||
std::shared_ptr<btCollisionDispatcher> myDispatcher;
|
||||
std::shared_ptr<btBroadphaseInterface> myOverlappingPairCache;
|
||||
std::shared_ptr<btSequentialImpulseConstraintSolver> mySolver;
|
||||
std::shared_ptr<Dynamics_DebugDrawer> myDebugDrawer;
|
||||
std::shared_ptr<btDiscreteDynamicsWorld> myDynamicsWorld;
|
||||
|
||||
Handle(Dynamics_Parameters) myDefaultDrawer; //!< default attributes
|
||||
Handle(Dynamics_Character) myCharacter;
|
||||
Handle(Dynamics_CollisionBody) myGround;
|
||||
NCollection_IndexedMap<Handle(Dynamics_CollisionBody)> myCollisionBodies;
|
||||
NCollection_IndexedMap<Handle(Dynamics_Constraint)> myConstraints;
|
||||
Bnd_Box mySceneBox;
|
||||
OSD_Timer myWorldTimer;
|
||||
Standard_Real myLengthUnitScale;
|
||||
Standard_Real myLastWorldTick;
|
||||
Standard_Real myFixedTimeStep;
|
||||
Standard_Integer myNbMaxSubTicks;
|
||||
Standard_Integer myNbRigidBodies;
|
||||
|
||||
};
|
||||
|
||||
#endif // _Dynamics_World_HeaderFile
|
32
src/Dynamics/FILES
Normal file
32
src/Dynamics/FILES
Normal file
@@ -0,0 +1,32 @@
|
||||
Dynamics_Character.cxx
|
||||
Dynamics_Character.hxx
|
||||
Dynamics_CharacterState.hxx
|
||||
Dynamics_CollisionBody.cxx
|
||||
Dynamics_CollisionBody.hxx
|
||||
Dynamics_CollisionBoxShape.cxx
|
||||
Dynamics_CollisionBoxShape.hxx
|
||||
Dynamics_CollisionBRepFlags.hxx
|
||||
Dynamics_CollisionBRepShape.cxx
|
||||
Dynamics_CollisionBRepShape.hxx
|
||||
Dynamics_CollisionBRepShapeConvex.hxx
|
||||
Dynamics_CollisionCompoundShape.cxx
|
||||
Dynamics_CollisionCompoundShape.hxx
|
||||
Dynamics_CollisionPlane.cxx
|
||||
Dynamics_CollisionPlane.hxx
|
||||
Dynamics_CollisionShape.cxx
|
||||
Dynamics_CollisionShape.hxx
|
||||
Dynamics_Constraint.cxx
|
||||
Dynamics_Constraint.hxx
|
||||
Dynamics_DebugDrawer.cxx
|
||||
Dynamics_DebugDrawer.hxx
|
||||
Dynamics_Graphic3dTriangulation.cxx
|
||||
Dynamics_Graphic3dTriangulation.hxx
|
||||
Dynamics_Internal.hxx
|
||||
Dynamics_MotionState.cxx
|
||||
Dynamics_MotionState.hxx
|
||||
Dynamics_Parameters.cxx
|
||||
Dynamics_Parameters.hxx
|
||||
Dynamics_PolyTriangulation.cxx
|
||||
Dynamics_PolyTriangulation.hxx
|
||||
Dynamics_World.cxx
|
||||
Dynamics_World.hxx
|
@@ -15,4 +15,5 @@ CSF_gdi32
|
||||
CSF_OpenGlLibs
|
||||
CSF_XwLibs
|
||||
CSF_FREETYPE
|
||||
CSF_BULLET
|
||||
CSF_TBB
|
||||
|
@@ -9,3 +9,4 @@ AIS
|
||||
StdSelect
|
||||
DsgPrs
|
||||
PrsDim
|
||||
Dynamics
|
||||
|
@@ -624,6 +624,21 @@ static EM_BOOL onResizeCallback (int theEventType, const EmscriptenUiEvent* theE
|
||||
return EM_FALSE;
|
||||
}
|
||||
|
||||
//! Update canvas bounding rectangle.
|
||||
EM_JS(void, occJSUpdateBoundingClientRect, (), {
|
||||
Module._myCanvasRect = Module.canvas.getBoundingClientRect();
|
||||
});
|
||||
|
||||
//! Get canvas bounding top.
|
||||
EM_JS(int, occJSGetBoundingClientTop, (), {
|
||||
return Math.round(Module._myCanvasRect.top);
|
||||
});
|
||||
|
||||
//! Get canvas bounding left.
|
||||
EM_JS(int, occJSGetBoundingClientLeft, (), {
|
||||
return Math.round(Module._myCanvasRect.left);
|
||||
});
|
||||
|
||||
//! Handle mouse input event.
|
||||
static EM_BOOL onWasmMouseCallback (int theEventType, const EmscriptenMouseEvent* theEvent, void* )
|
||||
{
|
||||
@@ -632,6 +647,17 @@ static EM_BOOL onWasmMouseCallback (int theEventType, const EmscriptenMouseEvent
|
||||
&& !ViewerTest::CurrentView().IsNull())
|
||||
{
|
||||
Handle(Wasm_Window) aWindow = Handle(Wasm_Window)::DownCast (ViewerTest::CurrentView()->Window());
|
||||
if (theEventType == EMSCRIPTEN_EVENT_MOUSEMOVE
|
||||
|| theEventType == EMSCRIPTEN_EVENT_MOUSEUP)
|
||||
{
|
||||
// these events are bound to EMSCRIPTEN_EVENT_TARGET_WINDOW, and coordinates should be converted
|
||||
occJSUpdateBoundingClientRect();
|
||||
EmscriptenMouseEvent anEvent = *theEvent;
|
||||
anEvent.targetX -= occJSGetBoundingClientLeft();
|
||||
anEvent.targetY -= occJSGetBoundingClientTop();
|
||||
return aWindow->ProcessMouseEvent (*aViewCtrl, theEventType, &anEvent) ? EM_TRUE : EM_FALSE;
|
||||
}
|
||||
|
||||
return aWindow->ProcessMouseEvent (*aViewCtrl, theEventType, theEvent) ? EM_TRUE : EM_FALSE;
|
||||
}
|
||||
return EM_FALSE;
|
||||
@@ -730,13 +756,17 @@ void ViewerTest_EventManager::SetupWindowCallbacks (const Handle(Aspect_Window)&
|
||||
// so that if web application changes canvas size by other means it should use another way to tell OCCT about resize
|
||||
emscripten_set_resize_callback (EMSCRIPTEN_EVENT_TARGET_WINDOW, anOpaque, toUseCapture, onResizeCallback);
|
||||
|
||||
// bind these events to window to track mouse movements outside of canvas
|
||||
//emscripten_set_mouseup_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
//emscripten_set_mousemove_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
//emscripten_set_mouseleave_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
emscripten_set_mouseup_callback (EMSCRIPTEN_EVENT_TARGET_WINDOW, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
emscripten_set_mousemove_callback (EMSCRIPTEN_EVENT_TARGET_WINDOW, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
|
||||
emscripten_set_mousedown_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
emscripten_set_mouseup_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
emscripten_set_mousemove_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
emscripten_set_dblclick_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
emscripten_set_click_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
emscripten_set_mouseenter_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
emscripten_set_mouseleave_callback (aTargetId, anOpaque, toUseCapture, onWasmMouseCallback);
|
||||
emscripten_set_wheel_callback (aTargetId, anOpaque, toUseCapture, onWasmWheelCallback);
|
||||
|
||||
emscripten_set_touchstart_callback (aTargetId, anOpaque, toUseCapture, onWasmTouchCallback);
|
||||
|
@@ -289,12 +289,15 @@ bool Wasm_Window::ProcessMouseEvent (Aspect_WindowInputListener& theListener,
|
||||
}
|
||||
case EMSCRIPTEN_EVENT_MOUSEDOWN:
|
||||
case EMSCRIPTEN_EVENT_MOUSEUP:
|
||||
{
|
||||
if (theEventType == EMSCRIPTEN_EVENT_MOUSEDOWN)
|
||||
{
|
||||
if (aNewPos2i.x() < 0 || aNewPos2i.x() > mySize.x()
|
||||
|| aNewPos2i.y() < 0 || aNewPos2i.y() > mySize.y())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (theListener.UpdateMouseButtons (aNewPos2i, aButtons, aFlags, isEmulated))
|
||||
{
|
||||
theListener.ProcessInput();
|
||||
|
Reference in New Issue
Block a user