WIP crafter.math

This commit is contained in:
Jorijn van der Graaf 2025-05-04 05:15:31 +02:00
commit 84099f07ed
11 changed files with 139 additions and 310 deletions

View file

@ -1,26 +1,15 @@
module;
#include <cstdint>
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "VulkanBuffer.h"
#include "camera.hpp"
#include <vulkan/vulkan.h>
module Crafter.Graphics;
import Crafter.Math;
using namespace Crafter;
Camera::Camera() {
old::Camera camera;
camera.type = old::Camera::CameraType::firstperson;
camera.setPerspective(90.0f, 16 / 9, 0.1f, 512.0f);
camera.setRotation(glm::vec3(180.0f, 150, 0));
camera.setTranslation(glm::vec3(-100.0f, -130.0f, -100.0f));
Camera::Camera(float fov, float aspectRatio, float near, float far) {
projection = Matrix<float, 4, 4, 1>::Projection(fov, aspectRatio, near, far);
view = Matrix<float, 4, 4, 1>::Idenity();
projectionView = camera.matrices.perspective*camera.matrices.view;
}

View file

@ -1,26 +1,18 @@
module;
#include <cstdint>
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "VulkanBuffer.h"
#include "camera.hpp"
export module Crafter.Graphics:Camera;
import :VulkanBuffer;
import Crafter.Component;
import Crafter.Math;
namespace Crafter {
export class Camera : public Component {
public:
glm::mat4 projection;
glm::mat4 view;
glm::mat4 projectionView;
Camera();
Matrix<float, 4, 4, 1> projection;
Matrix<float, 4, 4, 1> view;
Matrix<float, 4, 4, 1> projectionView;
Camera(float fov, float aspectRatio, float near, float far);
};
}

View file

@ -4,13 +4,7 @@ module;
#include <vulkan/vulkan.h>
#include <cstring>
#include <iostream>
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <cmath>
export module Crafter.Graphics:MeshShader;
import Crafter.Component;
@ -23,10 +17,10 @@ namespace Crafter {
export template <typename VertexType>
class MeshShader {
public:
glm::mat4 transform;
//glm::mat4 transform;
ComponentRefOwning<Mesh<VertexType>> mesh;
ComponentRefOwning<Camera> camera;
Buffer<glm::mat4> mvp;
Buffer<float> mvp;
std::uint32_t threadCount;
MeshShader(Mesh<VertexType>* mesh, Camera* camera) : threadCount(std::ceil(static_cast<double>(mesh->indexCount)/64/3)), mvp(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), mesh(mesh), camera(camera) {
@ -37,7 +31,7 @@ namespace Crafter {
set.Write(0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2, &mesh.component->indicies.descriptor);
}
void Update() {
mvp.value[0] = camera.component->projectionView*transform;
//mvp.value[0] = camera.component->projectionView*transform;
}
};
}

View file

@ -29,7 +29,7 @@ namespace Crafter {
float z;
float w;
};
export struct Vertex_xf32_yf32_zf32_wf32_uf32_vf32 {
export struct __attribute__((packed)) VertexUV {
float x;
float y;
float z;

View file

@ -4,15 +4,7 @@ module;
#include <vulkan/vulkan.h>
#include <array>
#include "VulkanInitializers.hpp"
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/matrix_inverse.hpp>
#include <glm/gtc/type_ptr.hpp>
#include "VulkanBuffer.h"
#include "camera.hpp"
#include <unordered_map>
export module Crafter.Graphics:VulkanPipeline;
@ -157,7 +149,7 @@ namespace Crafter {
// Pipeline
VkPipelineInputAssemblyStateCreateInfo inputAssemblyState = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE);
VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE, 0);
VkPipelineRasterizationStateCreateInfo rasterizationState = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_BACK_BIT, VK_FRONT_FACE_CLOCKWISE, 0);
VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE);
VkPipelineColorBlendStateCreateInfo colorBlendState = vks::initializers::pipelineColorBlendStateCreateInfo(1, &blendAttachmentState);
VkPipelineDepthStencilStateCreateInfo depthStencilState = vks::initializers::pipelineDepthStencilStateCreateInfo(VK_TRUE, VK_TRUE, VK_COMPARE_OP_LESS_OR_EQUAL);

View file

@ -28,6 +28,10 @@ export namespace Crafter {
MousePoint mouseDelta;
bool mouseLeftHeld = false;
bool mouseRightHeld = false;
bool heldkeys[255] = {};
Event<void> onKeyDown[255];
Event<void> onKeyHold[255];
Event<void> onKeyUp[255];
ComponentRefVectorOwning<UiElement> elements;
std::string name;
std::uint32_t width;

View file

@ -33,6 +33,8 @@ module;
#include <wayland-client-protocol.h>
#include <linux/input-event-codes.h>
#include <cmath>
#include <xkbcommon/xkbcommon.h>
#include <cstdio>
module Crafter.Graphics;
@ -100,6 +102,91 @@ wl_pointer_listener WindowWayland::pointer_listener = {
.axis = WindowWayland::PointerListenerHandleAxis,
};
xkb_keymap* xkb_keymap;
xkb_context* xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
xkb_state* xkb_state;
void keyboard_keymap(void *data, wl_keyboard *keyboard, uint32_t format, int fd, uint32_t size) {
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
close(fd);
fprintf(stderr, "Unsupported keymap format\n");
return;
}
void *map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
close(fd);
perror("mmap");
return;
}
xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
xkb_keymap = xkb_keymap_new_from_string(xkb_context, (const char *)map, XKB_KEYMAP_FORMAT_TEXT_V1,XKB_KEYMAP_COMPILE_NO_FLAGS);
munmap(map, size);
close(fd);
xkb_state = xkb_state_new(xkb_keymap);
}
void keyboard_enter(void *data, wl_keyboard *keyboard, uint32_t serial, wl_surface *surface, wl_array *keys) {
}
void keyboard_leave(void *data, wl_keyboard *keyboard, uint32_t serial, wl_surface *surface) {
}
void keyboard_key(void *data, wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
if (!xkb_state) {
return;
}
WindowWayland* window = reinterpret_cast<WindowWayland*>(data);
xkb_keycode_t keycode = key + 8;
xkb_keysym_t keysym = xkb_state_key_get_one_sym(xkb_state, keycode);
char utf8[8] = {0};
int len = xkb_keysym_to_utf8(keysym, utf8, sizeof(utf8));
if (len != 0) {
char keypress = utf8[0];
if(state == WL_KEYBOARD_KEY_STATE_PRESSED) {
if(window->heldkeys[keypress]) {
window->onKeyHold[keypress].Invoke();
} else{
window->onKeyDown[keypress].Invoke();
}
} else{
window->onKeyUp[keypress].Invoke();
}
} else {
// // fallback for keys like Return, Escape, etc.
// char name[64];
// if (xkb_keysym_get_name(keysym, name, sizeof(name)) > 0) {
// printf("Key %s pressed (non-printable or multi-char)\n", name);
// }
}
}
void keyboard_modifiers(void *data, wl_keyboard *keyboard, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
}
void keyboard_repeat_info(void *data, wl_keyboard *keyboard, int32_t rate, int32_t delay) {
}
wl_keyboard_listener WindowWayland::keyboard_listener = {
.keymap = keyboard_keymap,
.enter = keyboard_enter,
.leave = keyboard_leave,
.key = keyboard_key,
.modifiers = keyboard_modifiers,
.repeat_info = keyboard_repeat_info,
};
void WindowWayland::seat_handle_capabilities(void* data, wl_seat* seat, uint32_t capabilities) {
WindowWayland* window = reinterpret_cast<WindowWayland*>(data);
window->seat = seat;
@ -107,6 +194,10 @@ void WindowWayland::seat_handle_capabilities(void* data, wl_seat* seat, uint32_t
wl_pointer* pointer = wl_seat_get_pointer(seat);
wl_pointer_add_listener(pointer, &pointer_listener, window);
}
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) {
wl_keyboard* keyboard = wl_seat_get_keyboard(seat);
wl_keyboard_add_listener(keyboard, &keyboard_listener, NULL);
}
}
wl_seat_listener WindowWayland::seat_listener = {

View file

@ -32,6 +32,7 @@ export namespace Crafter {
wl_display* display = NULL;
inline static wl_compositor* compositor = NULL;
static wl_pointer_listener pointer_listener;
static wl_keyboard_listener keyboard_listener;
static wl_seat_listener seat_listener;
static wl_registry_listener registry_listener;
static xdg_surface_listener xdg_surface_listener;

View file

@ -1,256 +0,0 @@
/*
* Basic camera class providing a look-at and first-person camera
*
* Copyright (C) 2016-2024 by Sascha Willems - www.saschawillems.de
*
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/
#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <glm/gtc/matrix_transform.hpp>
namespace old {
class Camera
{
private:
float fov;
float znear, zfar;
void updateViewMatrix()
{
glm::mat4 currentMatrix = matrices.view;
glm::mat4 rotM = glm::mat4(1.0f);
glm::mat4 transM;
rotM = glm::rotate(rotM, glm::radians(rotation.x * (flipY ? -1.0f : 1.0f)), glm::vec3(1.0f, 0.0f, 0.0f));
rotM = glm::rotate(rotM, glm::radians(rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
rotM = glm::rotate(rotM, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
glm::vec3 translation = position;
if (flipY) {
translation.y *= -1.0f;
}
transM = glm::translate(glm::mat4(1.0f), translation);
if (type == CameraType::firstperson)
{
matrices.view = rotM * transM;
}
else
{
matrices.view = transM * rotM;
}
viewPos = glm::vec4(position, 0.0f) * glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f);
if (matrices.view != currentMatrix) {
updated = true;
}
};
public:
enum CameraType { lookat, firstperson };
CameraType type = CameraType::lookat;
glm::vec3 rotation = glm::vec3();
glm::vec3 position = glm::vec3();
glm::vec4 viewPos = glm::vec4();
float rotationSpeed = 1.0f;
float movementSpeed = 1.0f;
bool updated = true;
bool flipY = false;
struct
{
glm::mat4 perspective;
glm::mat4 view;
} matrices;
struct
{
bool left = false;
bool right = false;
bool up = false;
bool down = false;
} keys;
bool moving() const
{
return keys.left || keys.right || keys.up || keys.down;
}
float getNearClip() const {
return znear;
}
float getFarClip() const {
return zfar;
}
void setPerspective(float fov, float aspect, float znear, float zfar)
{
glm::mat4 currentMatrix = matrices.perspective;
this->fov = fov;
this->znear = znear;
this->zfar = zfar;
matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
if (flipY) {
matrices.perspective[1][1] *= -1.0f;
}
if (matrices.view != currentMatrix) {
updated = true;
}
};
void updateAspectRatio(float aspect)
{
glm::mat4 currentMatrix = matrices.perspective;
matrices.perspective = glm::perspective(glm::radians(fov), aspect, znear, zfar);
if (flipY) {
matrices.perspective[1][1] *= -1.0f;
}
if (matrices.view != currentMatrix) {
updated = true;
}
}
void setPosition(glm::vec3 position)
{
this->position = position;
updateViewMatrix();
}
void setRotation(glm::vec3 rotation)
{
this->rotation = rotation;
updateViewMatrix();
}
void rotate(glm::vec3 delta)
{
this->rotation += delta;
updateViewMatrix();
}
void setTranslation(glm::vec3 translation)
{
this->position = translation;
updateViewMatrix();
};
void translate(glm::vec3 delta)
{
this->position += delta;
updateViewMatrix();
}
void setRotationSpeed(float rotationSpeed)
{
this->rotationSpeed = rotationSpeed;
}
void setMovementSpeed(float movementSpeed)
{
this->movementSpeed = movementSpeed;
}
void update(float deltaTime)
{
updated = false;
if (type == CameraType::firstperson)
{
if (moving())
{
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;
if (keys.up)
position += camFront * moveSpeed;
if (keys.down)
position -= camFront * moveSpeed;
if (keys.left)
position -= glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;
if (keys.right)
position += glm::normalize(glm::cross(camFront, glm::vec3(0.0f, 1.0f, 0.0f))) * moveSpeed;
}
}
updateViewMatrix();
};
// 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 * rotationSpeed * 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;
}
};
}

View file

@ -27,20 +27,20 @@ int main() {
WindowWaylandVulkan window("Crafter.Graphics", 1280, 720);
Asset asset;
asset.LoadFull("gulch.cras");
asset.LoadFull("cannon.cras");
Camera camera;
Mesh<Vertex_xf32_yf32_zf32_wf32_uf32_vf32>* mesh = Mesh<Vertex_xf32_yf32_zf32_wf32_uf32_vf32>::FromAssetUV(asset.entries[0].data.data());
Mesh<VertexUV>* mesh = Mesh<VertexUV>::FromAssetUV(asset.entries[0].data.data());
DescriptorSet descriptors;
Pipeline::GetDescriptorSet(descriptors);
MeshShader<Vertex_xf32_yf32_zf32_wf32_uf32_vf32> meshShader(mesh, &camera);
MeshShader<VertexUV> meshShader(mesh, &camera);
meshShader.WriteDescriptors(descriptors);
meshShader.transform = glm::mat4(1.0f);
meshShader.Update();
Asset asset2;
asset2.LoadFull("gulchtex.cras");
asset2.LoadFull("texture.cras");
VkCommandBuffer cmd = window.StartInit();
VulkanTexture<Pixel_RU8_GU8_BU8_AU8>* txt = VulkanTexture<Pixel_RU8_GU8_BU8_AU8>::FromAsset(asset2.entries[0].data.data(), cmd);

View file

@ -10,7 +10,7 @@
"build_dir": "build",
"output_dir": "bin",
"type":"library",
"libs": ["wayland-client", "vulkan"],
"libs": ["wayland-client", "vulkan", "xkbcommon"],
"flags": ["-Wno-uninitialized"],
"shaders": [
{
@ -39,7 +39,25 @@
"name": "debug",
"extends": ["base"],
"optimization_level": "0",
"debug": true
"debug": true,
"dependencies": [
{
"path":"/home/jorijn/repos/Crafter/Crafter.Event/project.json",
"configuration":"debug"
},
{
"path":"/home/jorijn/repos/Crafter/Crafter.Asset/project.json",
"configuration":"lib-debug"
},
{
"path":"/home/jorijn/repos/Crafter/Crafter.Component/project.json",
"configuration":"debug"
},
{
"path":"/home/jorijn/repos/Crafter/Crafter.Math/project.json",
"configuration":"debug-lib"
}
]
},
{
"name": "test",
@ -58,6 +76,10 @@
{
"path":"/home/jorijn/repos/Crafter/Crafter.Component/project.json",
"configuration":"debug"
},
{
"path":"/home/jorijn/repos/Crafter/Crafter.Math/project.json",
"configuration":"debug-lib"
}
]
},