~sircmpwn/xrgears

ref: f162555056b018a3805f96df49158518ec63f94c xrgears/vitamin-k/scene/vikNode.hpp -rw-r--r-- 3.8 KiB
f1625550 — Lubosz Sarnecki vik: Use struct and array initializers. 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
 /*
 * vitamin-k
 *
 * Copyright 2016 Sascha Willems - www.saschawillems.de
 * Copyright 2017-2018 Collabora Ltd.
 *
 * Authors: Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
 * SPDX-License-Identifier: MIT
 */

#pragma once

#include <vector>
#include <glm/gtc/matrix_inverse.hpp>

#include "../render/vikModel.hpp"

#include "vikMaterial.hpp"
#include "../system/vikAssets.hpp"
#include "vikSkyBox.hpp"
#include "vikCamera.hpp"

namespace vik {
class Node {
 public:
  struct UBO {
    glm::mat4 normal[2];
    glm::mat4 model;
  } ubo;

  VkDescriptorSet descriptor_set;

  struct NodeInfo {
    glm::vec3 position;
    float rotation_speed;
    float rotation_offset;
    Material material;
  } info;

  Buffer uniformBuffer;

  Node() {
  }

  virtual ~Node() {
    uniformBuffer.destroy();
  }

  void setMateral(const Material& m) {
    info.material = m;
  }

  void setPosition(const glm::vec3& p) {
    info.position = p;
  }

  void setInfo(NodeInfo *nodeinfo) {
    info.position = nodeinfo->position;
    info.rotation_offset = nodeinfo->rotation_offset;
    info.rotation_speed = nodeinfo->rotation_speed;
    info.material = nodeinfo->material;
  }

  void create_descriptor_set(const VkDevice& device,
                           const VkDescriptorPool& descriptorPool,
                           const VkDescriptorSetLayout& descriptorSetLayout,
                           VkDescriptorBufferInfo* lightsDescriptor,
                           VkDescriptorBufferInfo* cameraDescriptor,
                           vik::SkyBox *skyDome) {
    VkDescriptorSetAllocateInfo allocInfo = {
      .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
      .descriptorPool = descriptorPool,
      .descriptorSetCount = 1,
      .pSetLayouts = &descriptorSetLayout
    };
    vik_log_check(vkAllocateDescriptorSets(device, &allocInfo, &descriptor_set));

    std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
      (VkWriteDescriptorSet) {
        .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
        .dstSet = descriptor_set,
        .dstBinding = 0,
        .descriptorCount = 1,
        .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
        .pBufferInfo = &uniformBuffer.descriptor
      },
      (VkWriteDescriptorSet) {
        .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
        .dstSet = descriptor_set,
        .dstBinding = 1,
        .descriptorCount = 1,
        .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
        .pBufferInfo = lightsDescriptor
      },
      (VkWriteDescriptorSet) {
        .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
        .dstSet = descriptor_set,
        .dstBinding = 2,
        .descriptorCount = 1,
        .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
        .pBufferInfo = cameraDescriptor
      }
    };

    if (skyDome != nullptr)
      writeDescriptorSets.push_back(skyDome->get_cube_map_write_descriptor_set(3, descriptor_set));

    vkUpdateDescriptorSets(device,
                           static_cast<uint32_t>(writeDescriptorSets.size()),
                           writeDescriptorSets.data(),
                           0,
                           nullptr);
  }

  void update_uniform_buffer(Camera::StereoView sv, float timer) {
    ubo.model = glm::mat4();

    ubo.model = glm::translate(ubo.model, info.position);
    float rotation_z = (info.rotation_speed * timer * 360.0f) + info.rotation_offset;
    ubo.model = glm::rotate(ubo.model, glm::radians(rotation_z), glm::vec3(0.0f, 0.0f, 1.0f));

    ubo.normal[0] = glm::inverseTranspose(sv.view[0] * ubo.model);
    ubo.normal[1] = glm::inverseTranspose(sv.view[1] * ubo.model);
    memcpy(uniformBuffer.mapped, &ubo, sizeof(ubo));
  }

  void init_uniform_buffer(Device *vulkanDevice) {
    vulkanDevice->create_and_map(&uniformBuffer, sizeof(ubo));
  }

  virtual void draw(VkCommandBuffer cmdbuffer, VkPipelineLayout pipelineLayout) {}
};
}  // namespace vik