First person gamepad camera for Android (move with LT, look around with RT)
This commit is contained in:
parent
d8e362cc8e
commit
2e101fdd1e
3 changed files with 104 additions and 36 deletions
|
|
@ -6,7 +6,6 @@
|
||||||
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define GLM_FORCE_RADIANS
|
#define GLM_FORCE_RADIANS
|
||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
@ -133,4 +132,68 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Update camera passing separate axis data (gamepad)
|
||||||
|
// Returns true if view or position has been changed
|
||||||
|
bool updatePad(glm::vec2 axisLeft, glm::vec2 axisRight, float deltaTime)
|
||||||
|
{
|
||||||
|
bool retVal = false;
|
||||||
|
|
||||||
|
if (type == CameraType::firstperson)
|
||||||
|
{
|
||||||
|
// Use the common console thumbstick layout
|
||||||
|
// Left = view, right = move
|
||||||
|
|
||||||
|
const float deadZone = 0.0015f;
|
||||||
|
const float range = 1.0f - deadZone;
|
||||||
|
|
||||||
|
glm::vec3 camFront;
|
||||||
|
camFront.x = -cos(glm::radians(rotation.x)) * sin(glm::radians(rotation.y));
|
||||||
|
camFront.y = sin(glm::radians(rotation.x));
|
||||||
|
camFront.z = cos(glm::radians(rotation.x)) * cos(glm::radians(rotation.y));
|
||||||
|
camFront = glm::normalize(camFront);
|
||||||
|
|
||||||
|
float moveSpeed = deltaTime * movementSpeed * 2.0f;
|
||||||
|
float rotSpeed = deltaTime * 50.0f;
|
||||||
|
|
||||||
|
// Move
|
||||||
|
if (fabsf(axisLeft.y) > deadZone)
|
||||||
|
{
|
||||||
|
float pos = (fabsf(axisLeft.y) - deadZone) / range;
|
||||||
|
position -= camFront * pos * ((axisLeft.y < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
|
||||||
|
retVal = true;
|
||||||
|
}
|
||||||
|
if (fabsf(axisLeft.x) > deadZone)
|
||||||
|
{
|
||||||
|
float pos = (fabsf(axisLeft.x) - deadZone) / range;
|
||||||
|
position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * pos * ((axisLeft.x < 0.0f) ? -1.0f : 1.0f) * moveSpeed;
|
||||||
|
retVal = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate
|
||||||
|
if (fabsf(axisRight.x) > deadZone)
|
||||||
|
{
|
||||||
|
float pos = (fabsf(axisRight.x) - deadZone) / range;
|
||||||
|
rotation.y += pos * ((axisRight.x < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
|
||||||
|
retVal = true;
|
||||||
|
}
|
||||||
|
if (fabsf(axisRight.y) > deadZone)
|
||||||
|
{
|
||||||
|
float pos = (fabsf(axisRight.y) - deadZone) / range;
|
||||||
|
rotation.x -= pos * ((axisRight.y < 0.0f) ? -1.0f : 1.0f) * rotSpeed;
|
||||||
|
retVal = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// todo: move code from example base class for look-at
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retVal)
|
||||||
|
{
|
||||||
|
updateViewMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
@ -517,31 +517,40 @@ void VulkanExampleBase::renderLoop()
|
||||||
// todo : check if gamepad is present
|
// todo : check if gamepad is present
|
||||||
// todo : time based and relative axis positions
|
// todo : time based and relative axis positions
|
||||||
bool updateView = false;
|
bool updateView = false;
|
||||||
// Rotate
|
if (camera.type != Camera::CameraType::firstperson)
|
||||||
if (std::abs(gamePadState.axes.x) > deadZone)
|
|
||||||
{
|
{
|
||||||
rotation.y += gamePadState.axes.x * 0.5f * rotationSpeed;
|
// Rotate
|
||||||
camera.rotate(glm::vec3(0.0f, gamePadState.axes.x * 0.5f, 0.0f));
|
if (std::abs(gamePadState.axisLeft.x) > deadZone)
|
||||||
updateView = true;
|
{
|
||||||
|
rotation.y += gamePadState.axisLeft.x * 0.5f * rotationSpeed;
|
||||||
|
camera.rotate(glm::vec3(0.0f, gamePadState.axisLeft.x * 0.5f, 0.0f));
|
||||||
|
updateView = true;
|
||||||
|
}
|
||||||
|
if (std::abs(gamePadState.axisLeft.y) > deadZone)
|
||||||
|
{
|
||||||
|
rotation.x -= gamePadState.axisLeft.y * 0.5f * rotationSpeed;
|
||||||
|
camera.rotate(glm::vec3(gamePadState.axisLeft.y * 0.5f, 0.0f, 0.0f));
|
||||||
|
updateView = true;
|
||||||
|
}
|
||||||
|
// Zoom
|
||||||
|
if (std::abs(gamePadState.axisRight.y) > deadZone)
|
||||||
|
{
|
||||||
|
zoom -= gamePadState.axisRight.y * 0.01f * zoomSpeed;
|
||||||
|
updateView = true;
|
||||||
|
}
|
||||||
|
if (updateView)
|
||||||
|
{
|
||||||
|
viewChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (std::abs(gamePadState.axes.y) > deadZone)
|
else
|
||||||
{
|
{
|
||||||
rotation.x -= gamePadState.axes.y * 0.5f * rotationSpeed;
|
updateView = camera.updatePad(gamePadState.axisLeft, gamePadState.axisRight, frameTimer);
|
||||||
camera.rotate(glm::vec3(gamePadState.axes.y * 0.5f, 0.0f, 0.0f));
|
if (updateView)
|
||||||
updateView = true;
|
{
|
||||||
|
viewChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Zoom
|
|
||||||
if (std::abs(gamePadState.axes.rz) > deadZone)
|
|
||||||
{
|
|
||||||
zoom -= gamePadState.axes.rz * 0.01f * zoomSpeed;
|
|
||||||
updateView = true;
|
|
||||||
}
|
|
||||||
if (updateView)
|
|
||||||
{
|
|
||||||
viewChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
|
|
@ -1128,7 +1137,7 @@ void VulkanExampleBase::handleMessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (camera.firtsperson)
|
if (camera.firstperson)
|
||||||
{
|
{
|
||||||
switch (wParam)
|
switch (wParam)
|
||||||
{
|
{
|
||||||
|
|
@ -1150,7 +1159,7 @@ void VulkanExampleBase::handleMessages(HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
|
||||||
keyPressed((uint32_t)wParam);
|
keyPressed((uint32_t)wParam);
|
||||||
break;
|
break;
|
||||||
case WM_KEYUP:
|
case WM_KEYUP:
|
||||||
if (camera.firtsperson)
|
if (camera.firstperson)
|
||||||
{
|
{
|
||||||
switch (wParam)
|
switch (wParam)
|
||||||
{
|
{
|
||||||
|
|
@ -1242,10 +1251,12 @@ int32_t VulkanExampleBase::handleAppInput(struct android_app* app, AInputEvent*
|
||||||
{
|
{
|
||||||
if (AInputEvent_getSource(event) == AINPUT_SOURCE_JOYSTICK)
|
if (AInputEvent_getSource(event) == AINPUT_SOURCE_JOYSTICK)
|
||||||
{
|
{
|
||||||
vulkanExample->gamePadState.axes.x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_X, 0);
|
// Left thumbstick
|
||||||
vulkanExample->gamePadState.axes.y = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Y, 0);
|
vulkanExample->gamePadState.axisLeft.x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_X, 0);
|
||||||
vulkanExample->gamePadState.axes.z = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Z, 0);
|
vulkanExample->gamePadState.axisLeft.y = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Y, 0);
|
||||||
vulkanExample->gamePadState.axes.rz = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RZ, 0);
|
// Right thumbstick
|
||||||
|
vulkanExample->gamePadState.axisRight.x = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_Z, 0);
|
||||||
|
vulkanExample->gamePadState.axisRight.y = AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_RZ, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -180,16 +180,10 @@ public:
|
||||||
} depthStencil;
|
} depthStencil;
|
||||||
|
|
||||||
// Gamepad state (only one pad supported)
|
// Gamepad state (only one pad supported)
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
struct
|
glm::vec2 axisLeft = glm::vec2(0.0f);
|
||||||
{
|
glm::vec2 axisRight = glm::vec2(0.0f);
|
||||||
float x = 0.0f;
|
|
||||||
float y = 0.0f;
|
|
||||||
float z = 0.0f;
|
|
||||||
float rz = 0.0f;
|
|
||||||
} axes;
|
|
||||||
} gamePadState;
|
} gamePadState;
|
||||||
|
|
||||||
// OS specific
|
// OS specific
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue