我正在制作第一人称相机,基于学习更多关于四元数的教程。这个相机有一个更奇怪的错误,如果按住“空格”并且您按住“左控件”同时仍然按住“空格”,即使左控件应该更改值它仍然认为“空格”被按住。
// Simple camera controller
namespace PlayerController {
void update(CharacterController& controller) {
controller.movementAxis.x = Input::isKeyDown(GLFW_KEY_W)
? -1.0f
: Input::isKeyDown(GLFW_KEY_S)
? 1.0f
: 0.0f;
controller.movementAxis.z = Input::isKeyDown(GLFW_KEY_D)
? 1.0f
: Input::isKeyDown(GLFW_KEY_A)
? -1.0f
: 0.0f;
controller.movementAxis.y = Input::isKeyDown(GLFW_KEY_LEFT_CONTROL)
? -1.0f
: Input::isKeyDown(GLFW_KEY_SPACE)
? 1.0f
: 0.0f;
controller.viewAxis.x = Input::deltaMouseX;
controller.viewAxis.y = Input::deltaMouseY;
}
}
// the actual controller that determines the positions and orientations
namespace CharacterSystem {
// Internal Variables
static float terminalVelocity = 8.0f;
void update(CharacterController& controller, Camera& camera, Rigidbody& rb)
{
float speed = controller.controllerBaseSpeed;
if (controller.isRunning)
{
speed = controller.controllerRunSpeed;
}
rb.acceleration = camera.forward * controller.movementAxis.x;
rb.acceleration += camera.right * controller.movementAxis.z;
// The y-axis just changes the player's global y position
// instead of using their local up axis
rb.acceleration.y += controller.movementAxis.y;
// Only normalize the acceleration if it is greater than 0. This
// way we avoid division by 0 errors
float accelerationMagnitudeSquared = glm::length2(rb.acceleration);
if (accelerationMagnitudeSquared > 0)
{
float denominator = glm::inversesqrt(accelerationMagnitudeSquared);
rb.acceleration *= denominator * speed;
}
rb.velocity += rb.acceleration * Application::deltaTime;
camera.position += rb.velocity * Application::deltaTime;
// If acceleration is 0, apply friction to decelerate the object
if (glm::all(glm::epsilonEqual(rb.acceleration, glm::vec3(0.0f), 0.001f)))
{
rb.velocity *= rb.friction * Application::deltaTime;
}
if (glm::length2(rb.velocity) >= terminalVelocity)
{
rb.velocity = glm::normalize(rb.velocity) * terminalVelocity;
}
// Snap the velocity to 0 when it gets close enough
if (glm::all(glm::epsilonEqual(rb.velocity, glm::vec3(0.0f), 0.001f)))
{
rb.velocity = glm::vec3(0.0f);
}
// Mouse movements don't need to be smoothed over time.
// They alread represent a change in position
controller.viewAxis *= controller.movementSensitivity * 1000;
if (controller.viewAxis.x != 0.0f)
{
// Yaw globally
glm::quat yaw = glm::quat(glm::vec3(0.0f, glm::radians(controller.viewAxis.x) * Application::deltaTime, 0.0f));
camera.orientation = camera.orientation * yaw;
}
if (controller.viewAxis.y != 0.0f)
{
// Pitch locally (this effects order of operation with quaternion multiplication)
glm::quat pitch = glm::quat(glm::vec3(glm::radians(-controller.viewAxis.y) * Application::deltaTime, 0.0f, 0.0f));
camera.orientation = pitch * camera.orientation;
}
}
this is the input handler for the program
namespace Input {
bool keyPressedData[GLFW_KEY_LAST] = {};
bool mouseButtonPressedData[GLFW_MOUSE_BUTTON_LAST] = {};
int previousKey = 0;
float mouseX = 0.0f;
float mouseY = 0.0f;
float mouseScrollX = 0.0f;
float mouseScrollY = 0.0f;
float deltaMouseX = 0.0f;
float deltaMouseY = 0.0f;
static float lastMouseX = 0.0f;
static float lastMouseY = 0.0f;
static bool firstFrame = true;
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (key >= 0 && key < GLFW_KEY_LAST) {
keyPressedData[key] = (action == GLFW_PRESS) || (action == GLFW_REPEAT);
}
}
void mouseCallback(GLFWwindow* window, double xpos, double ypos)
{
mouseX = (float)xpos;
mouseY = (float)ypos;
if (firstFrame)
{
// Set these to the mouse position the first frame so that
// we don't get large erratic values the first frame
lastMouseX = (float)xpos;
lastMouseY = (float)ypos;
firstFrame = false;
}
int windowWidth;
int windowHeight;
glfwGetWindowSize(window, &windowWidth, &windowHeight);
bool cursorLocked = glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED;
if (!cursorLocked &&
(mouseX >= (float)windowWidth || mouseX <= 0.0f || mouseY >= (float)windowHeight || mouseY <= 0.0f))
{
deltaMouseX = 0.0f;
deltaMouseY = 0.0f;
}
else
{
deltaMouseX = ((float)xpos - lastMouseX);
deltaMouseY = (lastMouseY - (float)ypos);
}
lastMouseX = (float)xpos;
lastMouseY = (float)ypos;
}
void endFrame()
{
deltaMouseX = 0.0f;
deltaMouseY = 0.0f;
}
bool isKeyDown(int key)
{
if (key >= 0 && key < GLFW_KEY_LAST)
{
return keyPressedData[key];
}
return false;
}
}
我已经尝试了几个角色控制器的变体,它们仍然有相同的错误。我一直在尝试,当按下交换相机前进方向的键时,方向只会改变,但它会继续朝同一方向前进。