summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authors-ol <s+removethis@s-ol.nu>2021-03-31 15:51:45 +0000
committers-ol <s+removethis@s-ol.nu>2021-03-31 16:03:44 +0000
commitdd5b4fdcfdfdb20a352032541f65fb401e73afe9 (patch)
tree8ba87d1db5d0d8ae6b306fdaaa19b5a1c7c51f50 /src
parentbetter DiligentEngine GLTF interface (diff)
downloadopenxPriments-dd5b4fdcfdfdb20a352032541f65fb401e73afe9.tar.gz
openxPriments-dd5b4fdcfdfdb20a352032541f65fb401e73afe9.zip
multiple GLTF Models, EXT_MSFT_controller_model support
Diffstat (limited to 'src')
-rw-r--r--src/main.zig57
-rw-r--r--src/scene.zig144
-rw-r--r--src/xrvk.zig3
3 files changed, 166 insertions, 38 deletions
diff --git a/src/main.zig b/src/main.zig
index 7a3a40a..67ce8f0 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -1,5 +1,6 @@
usingnamespace @import("xrvk.zig");
const std = @import("std");
+const glm = @import("glm");
const gfx = @import("graphics.zig");
const scene = @import("scene.zig");
const renderdoc = @import("renderdoc.zig");
@@ -12,6 +13,26 @@ pub fn main() !void {
session.deinit();
}
+const Paths = struct {
+ user_hand_right: xr.Path,
+ user_hand_left: xr.Path,
+ user_hand_head: xr.Path,
+
+ pub fn init(xri: xr.InstanceDispatch, inst: xr.Instance) !Paths {
+ var self: Paths = undefined;
+
+ inline for (@typeInfo(Paths).Struct.fields) |field| {
+ var buffer: [field.name.len + 2:0]u8 = undefined;
+ _ = std.mem.replace(u8, field.name, "_", "/", buffer[1..]);
+ buffer[0] = '/';
+ buffer[buffer.len - 1] = 0;
+ @field(self, field.name) = try xri.stringToPath(inst, buffer[0..]);
+ }
+
+ return self;
+ }
+};
+
const Session = struct {
xrb: xr.BaseDispatch,
xri: xr.InstanceDispatch,
@@ -24,6 +45,7 @@ const Session = struct {
state: xr.SessionState,
views: ?ViewInfo,
+ paths: Paths,
graphics: gfx.Graphics,
layers: []*const xr.CompositionLayerBaseHeader,
scene_space: xr.Space,
@@ -42,6 +64,7 @@ const Session = struct {
const zero = [_:0]u8{};
const extensions = [_][*:0]const u8{
"XR_KHR_vulkan_enable2",
+ "XR_MSFT_controller_model",
};
const xrb = try xr.BaseDispatch.load(xr.getProcAddr);
@@ -63,6 +86,8 @@ const Session = struct {
const xri = try xr.InstanceDispatch.load(instance, xr.getProcAddr);
errdefer xri.destroyInstance(instance) catch unreachable;
+ const paths = try Paths.init(xri, instance);
+
const system = try xri.getSystem(instance, .{ .form_factor = .head_mounted_display });
var system_properties = xr.SystemProperties.empty();
@@ -119,6 +144,7 @@ const Session = struct {
.state = .idle,
.views = null,
+ .paths = paths,
.graphics = graphics,
.scene_space = scene_space,
.layers = &[_]*const xr.CompositionLayerBaseHeader{},
@@ -225,6 +251,31 @@ const Session = struct {
try self.graphics.createSwapchain(self.session, views.configurations);
var gfx_scene = try scene.Scene.init(&self.graphics);
+ var helmet = scene.Model.initFile(&gfx_scene, "assets/DamagedHelmet.gltf");
+ helmet.setTransform(glm.translation(glm.Vec3.init([_]f32{ 0, 1.5, -2 })));
+ try gfx_scene.models.append(helmet);
+
+ for ([_]xr.Path{ self.paths.user_hand_left, self.paths.user_hand_right }) |path, i| {
+ var model_state = xr.ControllerModelKeyStateMSFT.empty();
+ try self.xri.getControllerModelKeyMSFT(self.session, path, &model_state);
+
+ if (model_state.model_key == 0)
+ continue;
+
+ const size = try self.xri.loadControllerModelMSFT(self.session, model_state.model_key, 0, null);
+ const buffer = try self.allocator.alloc(u8, size);
+ defer self.allocator.free(buffer);
+
+ _ = try self.xri.loadControllerModelMSFT(self.session, model_state.model_key, size, buffer.ptr);
+ var model = scene.Model.initMemory(&gfx_scene, buffer);
+
+ var transform = glm.Mat4.IDENTITY;
+ transform = transform.mul(glm.translation(glm.Vec3.init([_]f32{ 0.6 * (@intToFloat(f32, i) - 0.5), 1.5, -0.5 })));
+ transform = transform.mul(glm.rotation(0.9, glm.Vec3.init([_]f32{ 1, 0, 0 })));
+ model.setTransform(transform);
+ try gfx_scene.models.append(model);
+ }
+
const composition_layer = try self.allocator.create(xr.CompositionLayerProjection);
composition_layer.* = .{
.layer_flags = .{ .blend_texture_source_alpha_bit = true },
@@ -256,6 +307,12 @@ const Session = struct {
_ = try self.xri.beginFrame(self.session, null);
self.graphics.unlockQueue();
+ const predicted_seconds = @intToFloat(f32, frame_state.predicted_display_time) / 1_000_000_000;
+
+ var transform = glm.translation(glm.Vec3.init([_]f32{ 0, 1.5, -2 }));
+ transform = transform.mul(glm.rotation(predicted_seconds, glm.Vec3.init([_]f32{ 0, 1, 0 })));
+ gfx_scene.models.items[0].setTransform(transform);
+
var layer_count: u32 = 0;
if (frame_state.should_render > 0) {
diff --git a/src/scene.zig b/src/scene.zig
index d71dc47..e7fbb5c 100644
--- a/src/scene.zig
+++ b/src/scene.zig
@@ -169,6 +169,96 @@ const defaultSampler = dg.SamplerDesc{
.MaxLOD = 3.402823466e+38,
};
+pub const Model = struct {
+ model: dg.IGLTFModel_Wrapper,
+ bindings: dg.GLTF_ModelResourceBindings,
+ params: dg.GLTF_RenderInfo,
+
+ const DEFAULT_PARAMS = dg.GLTF_RenderInfo{
+ .ModelTransform = @bitCast([16]f32, glm.Mat4.IDENTITY),
+ .AlphaModes = dg.ALPHA_MODE_FLAG_ALL,
+ .DebugView = 0,
+ .OcclusionStrength = 1,
+ .EmissionScale = 1,
+ .IBLScale = 1,
+ .AverageLogLum = 0.3,
+ .MiddleGray = 0.18,
+ .WhitePoint = 3,
+ };
+
+ pub fn initMemory(scene: *const Scene, data: []const u8) Model {
+ const model = dg.Diligent_IGLTFModel_Create(
+ @ptrCast(*dg.IRenderDevice, scene.dev.ptr),
+ scene.ctx.ptr,
+ &dg.IGLTFModelCreateInfo{
+ .FileName = null,
+ .Data = data.ptr,
+ .DataSize = data.len,
+ .FileType = ._BINARY,
+ .pTextureCache = null,
+ .pCacheInfo = null,
+ .LoadAnimationAndSkin = true,
+ },
+ );
+
+ return .{
+ .model = dg.IGLTFModel_Wrapper.wrap(model),
+ .bindings = scene.renderer.CreateResourceBindings(
+ model,
+ scene.camera_ubo.ptr,
+ scene.light_ubo.ptr,
+ ),
+ .params = DEFAULT_PARAMS,
+ };
+ }
+
+ pub fn initFile(scene: *const Scene, path: [:0]const u8) Model {
+ const model = dg.Diligent_IGLTFModel_Create(
+ @ptrCast(*dg.IRenderDevice, scene.dev.ptr),
+ scene.ctx.ptr,
+ &dg.IGLTFModelCreateInfo{
+ .FileName = path.ptr,
+ .Data = null,
+ .DataSize = 0,
+ .FileType = ._UNKNOWN,
+ .pTextureCache = null,
+ .pCacheInfo = null,
+ .LoadAnimationAndSkin = true,
+ },
+ );
+
+ return .{
+ .model = dg.IGLTFModel_Wrapper.wrap(model),
+ .bindings = scene.renderer.CreateResourceBindings(
+ model,
+ scene.camera_ubo.ptr,
+ scene.light_ubo.ptr,
+ ),
+ .params = DEFAULT_PARAMS,
+ };
+ }
+
+ pub fn deinit(self: *Model) void {
+ self.bindings.Release();
+ self.model.Release();
+ }
+
+ pub fn setTransform(self: *Model, mat: glm.Mat4) void {
+ self.params.ModelTransform = @bitCast([16]f32, mat);
+ }
+
+ pub fn draw(self: *Model, scene: *Scene) void {
+ scene.renderer.Render(
+ scene.ctx.ptr,
+ self.model.ptr,
+ &self.params,
+ &self.bindings,
+ null,
+ scene.resource_binding.ptr,
+ );
+ }
+};
+
pub const Scene = struct {
viewports: []dg.Viewport,
scissors: []dg.Rect,
@@ -180,9 +270,7 @@ pub const Scene = struct {
views: []ViewUBO,
renderer: dg.IGLTF_PBR_Renderer_Wrapper,
- render_params: dg.GLTF_RenderInfo,
- model: dg.IGLTFModel_Wrapper,
- model_bindings: dg.GLTF_ModelResourceBindings,
+ models: std.ArrayList(Model),
envmap: ?*dg.ITextureView,
ctx: dg.IDeviceContext_Wrapper,
@@ -377,51 +465,27 @@ pub const Scene = struct {
self.renderer.PrecomputeCubemaps(@ptrCast(*dg.IRenderDevice, self.dev.ptr), self.ctx.ptr, self.envmap);
- const model = dg.Diligent_IGLTFModel_Create(
- @ptrCast(*dg.IRenderDevice, self.dev.ptr),
- self.ctx.ptr,
- &dg.IGLTFModelCreateInfo{
- .FileName = "assets/DamagedHelmet.gltf",
- .pTextureCache = null,
- .pCacheInfo = null,
- .LoadAnimationAndSkin = true,
- },
- );
- self.model = dg.IGLTFModel_Wrapper.wrap(model);
-
- self.model_bindings = self.renderer.CreateResourceBindings(
- self.model.ptr,
- self.camera_ubo.ptr,
- self.light_ubo.ptr,
- );
-
- self.render_params = .{
- .ModelTransform = @bitCast([16]f32, glm.translation(glm.Vec3.init([_]f32{ 0, 1.5, -2 }))),
- .AlphaModes = dg.ALPHA_MODE_FLAG_ALL,
- .DebugView = 0,
- .OcclusionStrength = 1,
- .EmissionScale = 1,
- .IBLScale = 1,
- .AverageLogLum = 0.3,
- .MiddleGray = 0.18,
- .WhitePoint = 3,
- };
+ // model
+ self.models = std.ArrayList(Model).init(gfx.allocator);
return self;
}
pub fn deinit(self: *const Scene) void {
- self.resource_binding.Release();
self.views_ubo.Release();
self.light_ubo.Release();
self.camera_ubo.Release();
- self.model.Release();
+ for (self.models.items) |*model| {
+ model.deinit();
+ }
+ self.models.deinit();
self.renderer.Release();
+ self.resource_binding.Release();
- gfx.allocator.free(self.viewports);
- gfx.allocator.free(self.scissors);
- gfx.allocator.free(self.views);
+ self.gfx.allocator.free(self.viewports);
+ self.gfx.allocator.free(self.scissors);
+ self.gfx.allocator.free(self.views);
}
pub fn render(self: *Scene, views: []const xr.View) !void {
@@ -483,7 +547,11 @@ pub const Scene = struct {
// record renderpass
self.renderer.Begin(self.ctx.ptr);
- self.renderer.Render(self.ctx.ptr, self.model.ptr, &self.render_params, &self.model_bindings, null, self.resource_binding.ptr);
+ for (self.models.items) |*model| {
+ model.draw(self);
+ }
+
+ // self.renderer.Render(self.ctx.ptr, self.model.ptr, &self.render_params, &self.model_bindings, null, self.resource_binding.ptr);
}
fn createShader(
diff --git a/src/xrvk.zig b/src/xrvk.zig
index 2a6d8d8..64428bc 100644
--- a/src/xrvk.zig
+++ b/src/xrvk.zig
@@ -52,6 +52,7 @@ pub const xr = struct {
xrDestroyInstance: PfnDestroyInstance,
xrGetSystem: PfnGetSystem,
xrGetSystemProperties: PfnGetSystemProperties,
+ xrStringToPath: PfnStringToPath,
xrCreateSession: PfnCreateSession,
xrDestroySession: PfnDestroySession,
xrBeginSession: PfnBeginSession,
@@ -73,6 +74,8 @@ pub const xr = struct {
xrAcquireSwapchainImage: PfnAcquireSwapchainImage,
xrWaitSwapchainImage: PfnWaitSwapchainImage,
xrReleaseSwapchainImage: PfnReleaseSwapchainImage,
+ xrGetControllerModelKeyMSFT: PfnGetControllerModelKeyMSFT,
+ xrLoadControllerModelMSFT: PfnLoadControllerModelMSFT,
usingnamespace InstanceWrapper(@This());
};