view: translate/rotate view with gamepad
This commit is contained in:
parent
b79473a881
commit
9137cba3b4
1
Makefile
1
Makefile
@ -38,6 +38,7 @@ endif
|
||||
|
||||
OBJS = \
|
||||
src/main.o \
|
||||
src/view.o \
|
||||
src/volk/volk.o \
|
||||
src/file.o \
|
||||
src/pack.o \
|
||||
|
||||
45
include/view.h
Normal file
45
include/view.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "directxmath/directxmath.h"
|
||||
|
||||
struct view {
|
||||
// positions
|
||||
XMVECTOR eye;
|
||||
XMVECTOR at;
|
||||
|
||||
// vectors
|
||||
XMVECTOR up;
|
||||
XMVECTOR forward;
|
||||
XMVECTOR normal; // cross(forward, up)
|
||||
XMVECTOR direction; // rotationaxis(forward, pitch)
|
||||
|
||||
// angles
|
||||
float pitch;
|
||||
|
||||
void applyTransform(float delta_forward, float delta_strafe, float delta_elevation,
|
||||
float delta_yaw, float delta_pitch);
|
||||
|
||||
inline XMMATRIX getView()
|
||||
{
|
||||
return XMMatrixLookAtLH(eye, at, up);
|
||||
}
|
||||
|
||||
inline float clampPitch(float delta_pitch)
|
||||
{
|
||||
float newPitch = pitch + delta_pitch;
|
||||
if (newPitch > 1.57f) newPitch = 1.57f;
|
||||
if (newPitch < -1.57f) newPitch = -1.57f;
|
||||
return newPitch;
|
||||
}
|
||||
|
||||
inline XMVECTOR getNormal()
|
||||
{
|
||||
return XMVector3Normalize(XMVector3Cross(forward, up));
|
||||
}
|
||||
|
||||
inline XMVECTOR getDirection()
|
||||
{
|
||||
XMMATRIX mrn = XMMatrixRotationAxis(normal, pitch);
|
||||
return XMVector3Transform(forward, mrn);
|
||||
}
|
||||
};
|
||||
@ -44,7 +44,7 @@ VSOutput VSMain(VSInput input)
|
||||
{
|
||||
VSOutput output = (VSOutput)0;
|
||||
float4 Position = float4(input.Position.xyz + input.BlockPosition, 1.0);
|
||||
output.Position = mul(Scene.Projection, mul(Scene.View, Position));
|
||||
output.Position = mul(Scene.Projection, mul(Scene.View, Position.xzyw)) * float4(-1, -1, 1, 1);
|
||||
|
||||
float2 textureOffset = float2(input.TextureID % 8, input.TextureID / 8) * 16;
|
||||
output.Texture = float4(yf(input.Texture.xy, 16), textureOffset);
|
||||
|
||||
121
src/main.cpp
121
src/main.cpp
@ -14,6 +14,7 @@
|
||||
#include "vulkan_helper.h"
|
||||
#include "shader_data.h"
|
||||
#include "minmax.h"
|
||||
#include "view.h"
|
||||
|
||||
#include "collada/scene.h"
|
||||
#include "collada/scene/vulkan.h"
|
||||
@ -285,9 +286,72 @@ inline static double getTime(int64_t start_time)
|
||||
return (double)(time / 1000) * 0.000001;
|
||||
}
|
||||
|
||||
static int const max_gamepads = 16;
|
||||
static SDL_Gamepad * gamepads[max_gamepads];
|
||||
static int gamepad_count = 0;
|
||||
|
||||
void add_gamepad(SDL_JoystickID instance_id)
|
||||
{
|
||||
SDL_Gamepad * gamepad = SDL_OpenGamepad(instance_id);
|
||||
char const * name = SDL_GetGamepadName(gamepad);
|
||||
if (gamepad_count >= max_gamepads) {
|
||||
printf("too many gamepads; ignoring gamepad %d %s\n", instance_id, name);
|
||||
SDL_CloseGamepad(gamepad);
|
||||
} else {
|
||||
printf("add gamepad %d %s\n", instance_id, name);
|
||||
gamepads[gamepad_count] = gamepad;
|
||||
gamepad_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void remove_gamepad(SDL_JoystickID instance_id)
|
||||
{
|
||||
for (int i = 0; i < gamepad_count; i++) {
|
||||
if (SDL_GetGamepadID(gamepads[i]) == instance_id) {
|
||||
int tail = (gamepad_count - i) - 1;
|
||||
SDL_CloseGamepad(gamepads[i]);
|
||||
memcpy(&gamepads[i], &gamepads[i+1], tail * (sizeof (gamepads[0])));
|
||||
gamepad_count -= 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert(!"remove_gamepad");
|
||||
}
|
||||
|
||||
void gamepad_update(view & viewState)
|
||||
{
|
||||
for (int i = 0; i < gamepad_count; i++) {
|
||||
SDL_Gamepad * gamepad = gamepads[i];
|
||||
int16_t i_leftx = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTX);
|
||||
int16_t i_lefty = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFTY);
|
||||
int16_t i_rightx = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTX);
|
||||
int16_t i_righty = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHTY);
|
||||
int16_t i_left_trigger = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_LEFT_TRIGGER);
|
||||
int16_t i_right_trigger = SDL_GetGamepadAxis(gamepad, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER);
|
||||
|
||||
constexpr float scale = 1.0f / 32767.0f;
|
||||
float leftx = (float)i_leftx * scale;
|
||||
float lefty = (float)i_lefty * scale;
|
||||
float rightx = (float)i_rightx * scale;
|
||||
float righty = (float)i_righty * scale;
|
||||
float left_trigger = (float)i_left_trigger * scale;
|
||||
float right_trigger = (float)i_right_trigger * scale;
|
||||
|
||||
constexpr float translate_rate = 0.5;
|
||||
float delta_forward = -lefty * translate_rate;
|
||||
float delta_strafe = leftx * translate_rate;
|
||||
float delta_elevation = (left_trigger - right_trigger) * translate_rate;
|
||||
float delta_yaw = rightx * -0.035;
|
||||
float delta_pitch = righty * -0.035;
|
||||
|
||||
viewState.applyTransform(delta_forward, delta_strafe, delta_elevation,
|
||||
delta_yaw, delta_pitch);
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
SDL_CHECK(SDL_Init(SDL_INIT_VIDEO));
|
||||
SDL_CHECK(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD));
|
||||
SDL_CHECK(SDL_Vulkan_LoadLibrary(NULL));
|
||||
volkInitialize();
|
||||
|
||||
@ -566,8 +630,8 @@ int main()
|
||||
VK_CHECK(vkCreateSampler(device, &samplerCreateInfo1, nullptr, &textureSamplers[1]));
|
||||
VkSamplerCreateInfo samplerCreateInfo2{
|
||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||
.magFilter = VK_FILTER_LINEAR,
|
||||
.minFilter = VK_FILTER_LINEAR,
|
||||
.magFilter = VK_FILTER_NEAREST,
|
||||
.minFilter = VK_FILTER_NEAREST,
|
||||
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
||||
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||
@ -610,10 +674,35 @@ int main()
|
||||
physicalDeviceMemoryProperties,
|
||||
surfaceFormat.format,
|
||||
depthFormat,
|
||||
textureSamplers[0],
|
||||
textureSamplers[2],
|
||||
shadowDepthImageViewDepth);
|
||||
minecraft_state.init();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// initialize view
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
int cameraIndex = collada_state.find_node_index_by_name("Camera001");
|
||||
int cameraTargetIndex = collada_state.find_node_index_by_name("EidelwindRigPelvis");
|
||||
int lightIndex = collada_state.find_node_index_by_name("Camera001");
|
||||
int lightTargetIndex = collada_state.find_node_index_by_name("EidelwindRigPelvis");
|
||||
//int lightMaterialIndex = collada_state.find_material_index_by_name("LightMaterial");
|
||||
int lightMaterialIndex = -1;
|
||||
|
||||
// view
|
||||
|
||||
XMVECTOR eye = XMVector3Transform(XMVectorZero(), collada_state.node_state.node_instances[cameraIndex].world);
|
||||
XMVECTOR at = XMVector3Transform(XMVectorZero(), collada_state.node_state.node_instances[cameraTargetIndex].world);
|
||||
XMVECTOR up = XMVectorSet(0, 0, 1, 0);
|
||||
|
||||
view viewState;
|
||||
viewState.eye = eye;
|
||||
//viewState.at = at;
|
||||
viewState.up = up;
|
||||
viewState.forward = XMVectorSetZ(XMVector3Normalize(at - eye), 0);
|
||||
viewState.pitch = 0;
|
||||
viewState.applyTransform(0, 0, 0, 0, 0);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// loop
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
@ -626,13 +715,6 @@ int main()
|
||||
int64_t start_time;
|
||||
SDL_GetCurrentTime(&start_time);
|
||||
|
||||
int cameraIndex = collada_state.find_node_index_by_name("Camera001");
|
||||
int cameraTargetIndex = collada_state.find_node_index_by_name("EidelwindRigPelvis");
|
||||
int lightIndex = collada_state.find_node_index_by_name("Camera001");
|
||||
int lightTargetIndex = collada_state.find_node_index_by_name("EidelwindRigPelvis");
|
||||
//int lightMaterialIndex = collada_state.find_material_index_by_name("LightMaterial");
|
||||
int lightMaterialIndex = -1;
|
||||
|
||||
collada_state.update(0);
|
||||
|
||||
while (quit == false) {
|
||||
@ -671,7 +753,19 @@ int main()
|
||||
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
|
||||
SDL_CHECK(SDL_GetWindowSize(window, &windowSize.x, &windowSize.y));
|
||||
}
|
||||
if (event.type == SDL_EVENT_GAMEPAD_ADDED) {
|
||||
add_gamepad(event.gdevice.which);
|
||||
}
|
||||
if (event.type == SDL_EVENT_GAMEPAD_REMOVED) {
|
||||
remove_gamepad(event.gdevice.which);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// gamepad update
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
gamepad_update(viewState);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// collada update
|
||||
@ -708,8 +802,9 @@ int main()
|
||||
collada_state.vulkan.change_frame(commandBuffer, frameIndex);
|
||||
|
||||
XMMATRIX projection = currentProjection();
|
||||
XMMATRIX view = currentView(collada_state.node_state.node_instances[cameraIndex],
|
||||
collada_state.node_state.node_instances[cameraTargetIndex]);
|
||||
//XMMATRIX view = currentView(collada_state.node_state.node_instances[cameraIndex],
|
||||
//collada_state.node_state.node_instances[cameraTargetIndex]);
|
||||
XMMATRIX view = viewState.getView();
|
||||
XMMATRIX shadowProjection = XMMatrixOrthographicLH(150, 150, -1000, 1000);
|
||||
XMMATRIX shadowView = currentView(collada_state.node_state.node_instances[lightIndex],
|
||||
collada_state.node_state.node_instances[lightTargetIndex]);
|
||||
|
||||
18
src/view.cpp
Normal file
18
src/view.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
#include "directxmath/directxmath.h"
|
||||
|
||||
#include "view.h"
|
||||
|
||||
constexpr float at_distance = 10.0;
|
||||
|
||||
void view::applyTransform(float delta_forward, float delta_strafe, float delta_elevation,
|
||||
float delta_yaw, float delta_pitch)
|
||||
{
|
||||
pitch = clampPitch(delta_pitch);
|
||||
|
||||
forward = XMVector3Transform(forward, XMMatrixRotationZ(delta_yaw));
|
||||
normal = getNormal(); // on forward change
|
||||
direction = getDirection(); // on forward/normal/pitch change
|
||||
|
||||
eye += forward * delta_forward + normal * delta_strafe + up * delta_elevation;
|
||||
at = eye + direction * at_distance;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user