Files
PhysX4.1/physx/samples/samplenorthpole/SampleNorthPoleCameraController.cpp
2025-11-28 23:13:44 +05:30

222 lines
8.2 KiB
C++

//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
#include "SampleNorthPole.h"
#include "SampleNorthPoleCameraController.h"
#include "PxRigidDynamic.h"
#include "geometry/PxCapsuleGeometry.h"
#include "PxShape.h"
#include "characterkinematic/PxCapsuleController.h"
#include <SampleBaseInputEventIds.h>
#include <SamplePlatform.h>
#include <SampleUserInput.h>
#include <SampleUserInputIds.h>
#include <SampleUserInputDefines.h>
using namespace SampleRenderer;
using namespace SampleFramework;
SampleNorthPoleCameraController::SampleNorthPoleCameraController(PxCapsuleController& controlled, SampleNorthPole& base) :
mCCT (controlled),
mBase (base),
mTargetYaw (0.0f-PxPi/2),
mTargetPitch (0.0f),
mPitchMin (-PxHalfPi*.99f),
mPitchMax (PxHalfPi*.99f),
mGamepadPitchInc (0.0f),
mGamepadYawInc (0.0f),
mGamepadForwardInc (0.0f),
mGamepadLateralInc (0.0f),
mSensibility (0.001f),
mFwd (false),
mBwd (false),
mLeft (false),
mRight (false),
mKeyShiftDown (false),
mRunningSpeed (10.0f),
mWalkingSpeed (2.5f),
mFilterMemory (0.0f)
{
mFilterMemory = float(computeCameraTarget().y);
}
void SampleNorthPoleCameraController::collectInputEvents(std::vector<const SampleFramework::InputEvent*>& inputEvents)
{
//digital keyboard events
DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_FORWARD, SCAN_CODE_FORWARD, SCAN_CODE_FORWARD, SCAN_CODE_FORWARD );
DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_BACKWARD, SCAN_CODE_BACKWARD, SCAN_CODE_BACKWARD, SCAN_CODE_BACKWARD );
DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_LEFT, SCAN_CODE_LEFT, SCAN_CODE_LEFT, SCAN_CODE_LEFT );
DIGITAL_INPUT_EVENT_DEF(CAMERA_MOVE_RIGHT, SCAN_CODE_RIGHT, SCAN_CODE_RIGHT, SCAN_CODE_RIGHT );
DIGITAL_INPUT_EVENT_DEF(CAMERA_SHIFT_SPEED, SCAN_CODE_LEFT_SHIFT, OSXKEY_SHIFT, LINUXKEY_SHIFT );
//analog gamepad events
ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_ROTATE_LEFT_RIGHT, GAMEPAD_ROTATE_SENSITIVITY, GAMEPAD_RIGHT_STICK_X, GAMEPAD_RIGHT_STICK_X, LINUXKEY_UNKNOWN );
ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_ROTATE_UP_DOWN, GAMEPAD_ROTATE_SENSITIVITY, GAMEPAD_RIGHT_STICK_Y, GAMEPAD_RIGHT_STICK_Y, LINUXKEY_UNKNOWN );
ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_MOVE_LEFT_RIGHT, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_X, GAMEPAD_LEFT_STICK_X, LINUXKEY_UNKNOWN );
ANALOG_INPUT_EVENT_DEF(CAMERA_GAMEPAD_MOVE_FORWARD_BACK, GAMEPAD_DEFAULT_SENSITIVITY, GAMEPAD_LEFT_STICK_Y, GAMEPAD_LEFT_STICK_Y, LINUXKEY_UNKNOWN );
}
void SampleNorthPoleCameraController::onDigitalInputEvent(const SampleFramework::InputEvent& ie, bool val)
{
if(val)
{
if(ie.m_Id == CAMERA_MOVE_FORWARD) mFwd = true;
else if(ie.m_Id == CAMERA_MOVE_BACKWARD) mBwd = true;
else if(ie.m_Id == CAMERA_MOVE_LEFT) mLeft = true;
else if(ie.m_Id == CAMERA_MOVE_RIGHT) mRight = true;
else if(ie.m_Id == CAMERA_SHIFT_SPEED) mKeyShiftDown = true;
}
else
{
if(ie.m_Id == CAMERA_MOVE_FORWARD) mFwd = false;
else if(ie.m_Id == CAMERA_MOVE_BACKWARD) mBwd = false;
else if(ie.m_Id == CAMERA_MOVE_LEFT) mLeft = false;
else if(ie.m_Id == CAMERA_MOVE_RIGHT) mRight = false;
else if(ie.m_Id == CAMERA_SHIFT_SPEED) mKeyShiftDown = false;
}
}
static PX_FORCE_INLINE PxReal remapAxisValue(PxReal absolutePosition)
{
return absolutePosition * absolutePosition * absolutePosition * 5.0f;
}
void SampleNorthPoleCameraController::onAnalogInputEvent(const SampleFramework::InputEvent& ie, float val)
{
if(ie.m_Id == CAMERA_GAMEPAD_ROTATE_LEFT_RIGHT)
{
mGamepadYawInc = -remapAxisValue(val);
}
else if(ie.m_Id == CAMERA_GAMEPAD_ROTATE_UP_DOWN)
{
// PT: ideally we'd need an option to "invert Y axis" here
// mGamepadPitchInc = - remapAxisValue(val);
mGamepadPitchInc = remapAxisValue(val);
}
else if(ie.m_Id == CAMERA_GAMEPAD_MOVE_LEFT_RIGHT)
{
mGamepadLateralInc = val;
}
else if(ie.m_Id == CAMERA_GAMEPAD_MOVE_FORWARD_BACK)
{
mGamepadForwardInc = val;
}
}
void SampleNorthPoleCameraController::onPointerInputEvent(const SampleFramework::InputEvent &ie, physx::PxU32 x, physx::PxU32 y, physx::PxReal dx, physx::PxReal dy, bool val)
{
if (ie.m_Id == CAMERA_MOUSE_LOOK)
{
mTargetYaw -= dx * mSensibility;
mTargetPitch += dy * mSensibility;
}
}
void SampleNorthPoleCameraController::setView(PxReal pitch, PxReal yaw)
{
mTargetPitch = pitch;
mTargetYaw = yaw;
}
PxExtendedVec3 SampleNorthPoleCameraController::computeCameraTarget()
{
PxRigidActor* characterActor = mCCT.getActor();
PxShape* shape;
characterActor->getShapes(&shape,1);
PxCapsuleGeometry geom;
shape->getCapsuleGeometry(geom);
const PxExtendedVec3 headPos = PxExtendedVec3(0,geom.halfHeight+geom.radius,0);
return mCCT.getPosition() + headPos;
}
static PX_INLINE float feedbackFilter(float val, float& memory, float sharpness)
{
if(sharpness<0.0f) sharpness = 0.0f;
else if(sharpness>1.0f) sharpness = 1.0f;
return memory = val * sharpness + memory * (1.0f - sharpness);
}
void SampleNorthPoleCameraController::update(Camera& camera, PxReal dtime)
{
PxSceneReadLock scopedLock(mBase.getActiveScene());
// Update CCT
if(!mBase.isPaused())
{
PxVec3 targetKeyDisplacement(0);
PxVec3 targetPadDisplacement(0);
PxVec3 forward = camera.getViewDir();
forward.y = 0;
forward.normalize();
PxVec3 up = PxVec3(0,1,0);
PxVec3 right = forward.cross(up);
if(mFwd) targetKeyDisplacement += forward;
if(mBwd) targetKeyDisplacement -= forward;
if(mRight) targetKeyDisplacement += right;
if(mLeft) targetKeyDisplacement -= right;
targetKeyDisplacement *= mKeyShiftDown ? mRunningSpeed : mWalkingSpeed;
targetKeyDisplacement += PxVec3(0,-9.81f,0);
targetKeyDisplacement *= dtime;
targetPadDisplacement += forward * mGamepadForwardInc * mRunningSpeed;
targetPadDisplacement += right * mGamepadLateralInc * mRunningSpeed;
targetPadDisplacement += PxVec3(0,-9.81f,0);
targetPadDisplacement *= dtime;
// PxU32 flags = mCCT.move(targetKeyDisplacement + targetPadDisplacement, 0.001f, dtime, PxControllerFilters(0));
PxU32 flags = mCCT.move(targetKeyDisplacement + targetPadDisplacement, 0.0f, dtime, PxControllerFilters(0));
PX_UNUSED(flags);
}
// Update camera
{
mTargetYaw += mGamepadYawInc * dtime;
mTargetPitch += mGamepadPitchInc * dtime;
// Clamp pitch
if(mTargetPitch<mPitchMin) mTargetPitch = mPitchMin;
if(mTargetPitch>mPitchMax) mTargetPitch = mPitchMax;
camera.setRot(PxVec3(-mTargetPitch,-mTargetYaw,0));
PxExtendedVec3 camTarget = computeCameraTarget();
const float filteredHeight = feedbackFilter((float)camTarget.y, mFilterMemory, dtime*6.0f);
camTarget.y = filteredHeight;
const PxF32 distanceToTarget = 0.0f;
const PxVec3 target = toVec3(camTarget) - camera.getViewDir()*distanceToTarget;
camera.setPos(target);
}
}