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 = \
|
OBJS = \
|
||||||
src/main.o \
|
src/main.o \
|
||||||
|
src/view.o \
|
||||||
src/volk/volk.o \
|
src/volk/volk.o \
|
||||||
src/file.o \
|
src/file.o \
|
||||||
src/pack.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;
|
VSOutput output = (VSOutput)0;
|
||||||
float4 Position = float4(input.Position.xyz + input.BlockPosition, 1.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;
|
float2 textureOffset = float2(input.TextureID % 8, input.TextureID / 8) * 16;
|
||||||
output.Texture = float4(yf(input.Texture.xy, 16), textureOffset);
|
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 "vulkan_helper.h"
|
||||||
#include "shader_data.h"
|
#include "shader_data.h"
|
||||||
#include "minmax.h"
|
#include "minmax.h"
|
||||||
|
#include "view.h"
|
||||||
|
|
||||||
#include "collada/scene.h"
|
#include "collada/scene.h"
|
||||||
#include "collada/scene/vulkan.h"
|
#include "collada/scene/vulkan.h"
|
||||||
@ -285,9 +286,72 @@ inline static double getTime(int64_t start_time)
|
|||||||
return (double)(time / 1000) * 0.000001;
|
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()
|
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));
|
SDL_CHECK(SDL_Vulkan_LoadLibrary(NULL));
|
||||||
volkInitialize();
|
volkInitialize();
|
||||||
|
|
||||||
@ -566,8 +630,8 @@ int main()
|
|||||||
VK_CHECK(vkCreateSampler(device, &samplerCreateInfo1, nullptr, &textureSamplers[1]));
|
VK_CHECK(vkCreateSampler(device, &samplerCreateInfo1, nullptr, &textureSamplers[1]));
|
||||||
VkSamplerCreateInfo samplerCreateInfo2{
|
VkSamplerCreateInfo samplerCreateInfo2{
|
||||||
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
|
||||||
.magFilter = VK_FILTER_LINEAR,
|
.magFilter = VK_FILTER_NEAREST,
|
||||||
.minFilter = VK_FILTER_LINEAR,
|
.minFilter = VK_FILTER_NEAREST,
|
||||||
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR,
|
||||||
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||||
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
|
||||||
@ -610,10 +674,35 @@ int main()
|
|||||||
physicalDeviceMemoryProperties,
|
physicalDeviceMemoryProperties,
|
||||||
surfaceFormat.format,
|
surfaceFormat.format,
|
||||||
depthFormat,
|
depthFormat,
|
||||||
textureSamplers[0],
|
textureSamplers[2],
|
||||||
shadowDepthImageViewDepth);
|
shadowDepthImageViewDepth);
|
||||||
minecraft_state.init();
|
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
|
// loop
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -626,13 +715,6 @@ int main()
|
|||||||
int64_t start_time;
|
int64_t start_time;
|
||||||
SDL_GetCurrentTime(&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);
|
collada_state.update(0);
|
||||||
|
|
||||||
while (quit == false) {
|
while (quit == false) {
|
||||||
@ -671,8 +753,20 @@ int main()
|
|||||||
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
|
if (event.type == SDL_EVENT_WINDOW_RESIZED) {
|
||||||
SDL_CHECK(SDL_GetWindowSize(window, &windowSize.x, &windowSize.y));
|
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
|
// collada update
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
@ -708,8 +802,9 @@ int main()
|
|||||||
collada_state.vulkan.change_frame(commandBuffer, frameIndex);
|
collada_state.vulkan.change_frame(commandBuffer, frameIndex);
|
||||||
|
|
||||||
XMMATRIX projection = currentProjection();
|
XMMATRIX projection = currentProjection();
|
||||||
XMMATRIX view = currentView(collada_state.node_state.node_instances[cameraIndex],
|
//XMMATRIX view = currentView(collada_state.node_state.node_instances[cameraIndex],
|
||||||
collada_state.node_state.node_instances[cameraTargetIndex]);
|
//collada_state.node_state.node_instances[cameraTargetIndex]);
|
||||||
|
XMMATRIX view = viewState.getView();
|
||||||
XMMATRIX shadowProjection = XMMatrixOrthographicLH(150, 150, -1000, 1000);
|
XMMATRIX shadowProjection = XMMatrixOrthographicLH(150, 150, -1000, 1000);
|
||||||
XMMATRIX shadowView = currentView(collada_state.node_state.node_instances[lightIndex],
|
XMMATRIX shadowView = currentView(collada_state.node_state.node_instances[lightIndex],
|
||||||
collada_state.node_state.node_instances[lightTargetIndex]);
|
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