source: opengl-game/vulkan-game.hpp@ 6bac215

feature/imgui-sdl
Last change on this file since 6bac215 was 6bac215, checked in by Dmitry Portnoy <dportnoy@…>, 3 years ago

Rewrite a large portion of the VulkanBuffer class, start using it more
to resize buffers, and simplify resizeBufferSet() since the additions to
VulkanBuffer can now do some of what that function used to do

  • Property mode set to 100644
File size: 22.7 KB
Line 
1#ifndef _VULKAN_GAME_H
2#define _VULKAN_GAME_H
3
4#include <algorithm>
5#include <chrono>
6#include <map>
7#include <vector>
8
9#include <vulkan/vulkan.h>
10
11#include <SDL2/SDL.h>
12#include <SDL2/SDL_ttf.h>
13
14#define GLM_FORCE_RADIANS
15#define GLM_FORCE_DEPTH_ZERO_TO_ONE // Since, in Vulkan, the depth range is 0 to 1 instead of -1 to 1
16#define GLM_FORCE_RIGHT_HANDED
17
18#include <glm/glm.hpp>
19#include <glm/gtc/matrix_transform.hpp>
20
21#include "IMGUI/imgui_impl_vulkan.h"
22
23#include "consts.hpp"
24#include "utils.hpp"
25#include "game-gui-sdl.hpp"
26#include "vulkan-utils.hpp"
27#include "graphics-pipeline_vulkan.hpp"
28#include "vulkan-buffer.hpp"
29
30using namespace glm;
31using namespace std::chrono;
32
33#ifdef NDEBUG
34 const bool ENABLE_VALIDATION_LAYERS = false;
35#else
36 const bool ENABLE_VALIDATION_LAYERS = true;
37#endif
38
39// TODO: Consider if there is a better way of dealing with all the vertex types and ssbo types, maybe
40// by consolidating some and trying to keep new ones to a minimum
41
42struct ModelVertex {
43 vec3 pos;
44 vec3 color;
45 vec2 texCoord;
46 vec3 normal;
47 unsigned int objIndex;
48};
49
50struct LaserVertex {
51 vec3 pos;
52 vec2 texCoord;
53 unsigned int objIndex;
54};
55
56struct ExplosionVertex {
57 vec3 particleStartVelocity;
58 float particleStartTime;
59 unsigned int objIndex;
60};
61
62struct SSBO_ModelObject {
63 alignas(16) mat4 model;
64};
65
66struct SSBO_Asteroid {
67 alignas(16) mat4 model;
68 alignas(4) float hp;
69 alignas(4) unsigned int deleted;
70};
71
72struct SSBO_Laser {
73 alignas(16) mat4 model;
74 alignas(4) vec3 color;
75 alignas(4) unsigned int deleted;
76};
77
78struct SSBO_Explosion {
79 alignas(16) mat4 model;
80 alignas(4) float explosionStartTime;
81 alignas(4) float explosionDuration;
82 alignas(4) unsigned int deleted;
83};
84
85struct UBO_VP_mats {
86 alignas(16) mat4 view;
87 alignas(16) mat4 proj;
88};
89
90struct UBO_Explosion {
91 alignas(16) mat4 view;
92 alignas(16) mat4 proj;
93 alignas(4) float cur_time;
94};
95
96// TODO: Use this struct for uniform buffers as well and probably combine it with the VulkanBuffer class
97// Also, probably better to make this a vector of structs where each struct
98// has a VkBuffer, VkDeviceMemory, and VkDescriptorBufferInfo
99// TODO: Maybe change the structure here since VkDescriptorBufferInfo already stores a reference to the VkBuffer
100struct BufferSet {
101 vector<VkBuffer> buffers;
102 vector<VkDeviceMemory> memory;
103 vector<VkDescriptorBufferInfo> infoSet;
104 VkBufferUsageFlags usages;
105 VkMemoryPropertyFlags properties;
106};
107
108// TODO: Change the index type to uint32_t and check the Vulkan Tutorial loading model section as a reference
109// TODO: Create a typedef for index type so I can easily change uin16_t to something else later
110// TODO: Maybe create a typedef for each of the templated SceneObject types
111template<class VertexType, class SSBOType>
112struct SceneObject {
113 vector<VertexType> vertices;
114 vector<uint16_t> indices;
115 SSBOType ssbo;
116
117 mat4 model_base;
118 mat4 model_transform;
119
120 bool modified;
121
122 // TODO: Figure out if I should make child classes that have these fields instead of putting them in the
123 // parent class
124 vec3 center; // currently only matters for asteroids
125 float radius; // currently only matters for asteroids
126 SceneObject<ModelVertex, SSBO_Asteroid>* targetAsteroid; // currently only used for lasers
127};
128
129// TODO: Have to figure out how to include an optional ssbo parameter for each object
130// Could probably use the same approach to make indices optional
131// Figure out if there are sufficient use cases to make either of these optional or is it fine to make
132// them mamdatory
133
134
135// TODO: Look into using dynamic_cast to check types of SceneObject and EffectOverTime
136
137struct BaseEffectOverTime {
138 bool deleted;
139
140 virtual void applyEffect(float curTime) = 0;
141
142 BaseEffectOverTime() :
143 deleted(false) {
144 }
145
146 virtual ~BaseEffectOverTime() {
147 }
148};
149
150template<class VertexType, class SSBOType>
151struct EffectOverTime : public BaseEffectOverTime {
152 GraphicsPipeline_Vulkan<VertexType>& pipeline;
153 vector<SceneObject<VertexType, SSBOType>>& objects;
154 unsigned int objectIndex;
155 size_t effectedFieldOffset;
156 float startValue;
157 float startTime;
158 float changePerSecond;
159
160 EffectOverTime(GraphicsPipeline_Vulkan<VertexType>& pipeline, vector<SceneObject<VertexType, SSBOType>>& objects,
161 unsigned int objectIndex, size_t effectedFieldOffset, float startTime, float changePerSecond)
162 : pipeline(pipeline)
163 , objects(objects)
164 , objectIndex(objectIndex)
165 , effectedFieldOffset(effectedFieldOffset)
166 , startTime(startTime)
167 , changePerSecond(changePerSecond) {
168 size_t ssboOffset = offset_of(&SceneObject<VertexType, SSBOType>::ssbo);
169
170 unsigned char* effectedFieldPtr = reinterpret_cast<unsigned char*>(&objects[objectIndex]) +
171 ssboOffset + effectedFieldOffset;
172
173 startValue = *reinterpret_cast<float*>(effectedFieldPtr);
174 }
175
176 void applyEffect(float curTime) {
177 if (objects[objectIndex].ssbo.deleted) {
178 this->deleted = true;
179 return;
180 }
181
182 size_t ssboOffset = offset_of(&SceneObject<VertexType, SSBOType>::ssbo);
183
184 unsigned char* effectedFieldPtr = reinterpret_cast<unsigned char*>(&objects[objectIndex]) +
185 ssboOffset + effectedFieldOffset;
186
187 *reinterpret_cast<float*>(effectedFieldPtr) = startValue + (curTime - startTime) * changePerSecond;
188
189 objects[objectIndex].modified = true;
190 }
191};
192
193// TODO: Maybe move this to a different header
194
195enum UIValueType {
196 UIVALUE_INT,
197 UIVALUE_DOUBLE,
198};
199
200struct UIValue {
201 UIValueType type;
202 string label;
203 void* value;
204
205 UIValue(UIValueType _type, string _label, void* _value) : type(_type), label(_label), value(_value) {}
206};
207
208/* TODO: The following syntax (note the const keyword) means the function will not modify
209 * its params. I should use this where appropriate
210 *
211 * [return-type] [func-name](params...) const { ... }
212 */
213
214class VulkanGame {
215
216 public:
217
218 VulkanGame();
219 ~VulkanGame();
220
221 void run(int width, int height, unsigned char guiFlags);
222
223 private:
224
225 static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(
226 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
227 VkDebugUtilsMessageTypeFlagsEXT messageType,
228 const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
229 void* pUserData);
230
231 // TODO: Maybe pass these in as parameters to some Camera class
232 const float NEAR_CLIP = 0.1f;
233 const float FAR_CLIP = 100.0f;
234 const float FOV_ANGLE = 67.0f; // means the camera lens goes from -33 deg to 33 deg
235
236 const int EXPLOSION_PARTICLE_COUNT = 300;
237 const vec3 LASER_COLOR = vec3(0.2f, 1.0f, 0.2f);
238
239 bool done;
240
241 vec3 cam_pos;
242
243 // TODO: Good place to start using smart pointers
244 GameGui* gui;
245
246 SDL_version sdlVersion;
247 SDL_Window* window = nullptr;
248
249 int drawableWidth, drawableHeight;
250
251 VkInstance instance;
252 VkDebugUtilsMessengerEXT debugMessenger;
253 VkSurfaceKHR vulkanSurface;
254 VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
255 VkDevice device;
256
257 VkQueue graphicsQueue;
258 VkQueue presentQueue;
259
260 // TODO: Maybe make a swapchain struct for convenience
261 VkSurfaceFormatKHR swapChainSurfaceFormat;
262 VkPresentModeKHR swapChainPresentMode;
263 VkExtent2D swapChainExtent;
264 uint32_t swapChainMinImageCount;
265 uint32_t swapChainImageCount;
266 VkSwapchainKHR swapChain;
267 vector<VkImage> swapChainImages;
268 vector<VkImageView> swapChainImageViews;
269 vector<VkFramebuffer> swapChainFramebuffers;
270
271 VkRenderPass renderPass;
272
273 VkCommandPool resourceCommandPool;
274
275 vector<VkCommandPool> commandPools;
276 vector<VkCommandBuffer> commandBuffers;
277
278 VulkanImage depthImage;
279
280 // These are per frame
281 vector<VkSemaphore> imageAcquiredSemaphores;
282 vector<VkSemaphore> renderCompleteSemaphores;
283
284 // These are per swap chain image
285 vector<VkFence> inFlightFences;
286
287 uint32_t imageIndex;
288 uint32_t currentFrame;
289
290 bool shouldRecreateSwapChain;
291
292 VkSampler textureSampler;
293
294 VulkanImage floorTextureImage;
295 VkDescriptorImageInfo floorTextureImageDescriptor;
296
297 VulkanImage laserTextureImage;
298 VkDescriptorImageInfo laserTextureImageDescriptor;
299
300 mat4 viewMat, projMat;
301
302 // Maybe at some point create an imgui pipeline class, but I don't think it makes sense right now
303 VkDescriptorPool imguiDescriptorPool;
304
305 // TODO: Probably restructure the GraphicsPipeline_Vulkan class based on what I learned about descriptors and textures
306 // while working on graphics-library. Double-check exactly what this was and note it down here.
307 // Basically, I think the point was that if I have several modesl that all use the same shaders and, therefore,
308 // the same pipeline, but use different textures, the approach I took when initially creating GraphicsPipeline_Vulkan
309 // wouldn't work since the whole pipeline couldn't have a common set of descriptors for the textures
310 GraphicsPipeline_Vulkan<ModelVertex> modelPipeline;
311 GraphicsPipeline_Vulkan<ModelVertex> shipPipeline;
312 GraphicsPipeline_Vulkan<ModelVertex> asteroidPipeline;
313 GraphicsPipeline_Vulkan<LaserVertex> laserPipeline;
314 GraphicsPipeline_Vulkan<ExplosionVertex> explosionPipeline;
315
316 BufferSet storageBuffers_modelPipeline;
317 VulkanBuffer<SSBO_ModelObject> objects_modelPipeline;
318 BufferSet uniformBuffers_modelPipeline;
319
320 BufferSet storageBuffers_shipPipeline;
321 VulkanBuffer<SSBO_ModelObject> objects_shipPipeline;
322 BufferSet uniformBuffers_shipPipeline;
323
324 BufferSet storageBuffers_asteroidPipeline;
325 VulkanBuffer<SSBO_Asteroid> objects_asteroidPipeline;
326 BufferSet uniformBuffers_asteroidPipeline;
327
328 BufferSet storageBuffers_laserPipeline;
329 VulkanBuffer<SSBO_Laser> objects_laserPipeline;
330 BufferSet uniformBuffers_laserPipeline;
331
332 BufferSet storageBuffers_explosionPipeline;
333 VulkanBuffer<SSBO_Explosion> objects_explosionPipeline;
334 BufferSet uniformBuffers_explosionPipeline;
335
336 // TODO: Maybe make the ubo objects part of the pipeline class since there's only one ubo
337 // per pipeline.
338 // Or maybe create a higher level wrapper around GraphicsPipeline_Vulkan to hold things like
339 // the objects vector, the ubo, and the ssbo
340
341 // TODO: Rename *_VP_mats to *_uniforms and possibly use different types for each one
342 // if there is a need to add other uniform variables to one or more of the shaders
343
344 vector<SceneObject<ModelVertex, SSBO_ModelObject>> modelObjects;
345
346 UBO_VP_mats object_VP_mats;
347
348 vector<SceneObject<ModelVertex, SSBO_ModelObject>> shipObjects;
349
350 UBO_VP_mats ship_VP_mats;
351
352 vector<SceneObject<ModelVertex, SSBO_Asteroid>> asteroidObjects;
353
354 UBO_VP_mats asteroid_VP_mats;
355
356 vector<SceneObject<LaserVertex, SSBO_Laser>> laserObjects;
357
358 UBO_VP_mats laser_VP_mats;
359
360 vector<SceneObject<ExplosionVertex, SSBO_Explosion>> explosionObjects;
361
362 UBO_Explosion explosion_UBO;
363
364 vector<BaseEffectOverTime*> effects;
365
366 float shipSpeed = 0.5f;
367 float asteroidSpeed = 2.0f;
368
369 float spawnRate_asteroid = 0.5;
370 float lastSpawn_asteroid;
371
372 unsigned int leftLaserIdx = -1;
373 EffectOverTime<ModelVertex, SSBO_Asteroid>* leftLaserEffect = nullptr;
374
375 unsigned int rightLaserIdx = -1;
376 EffectOverTime<ModelVertex, SSBO_Asteroid>* rightLaserEffect = nullptr;
377
378 /*** High-level vars ***/
379
380 // TODO: Just typedef the type of this function to RenderScreenFn or something since it's used in a few places
381 void (VulkanGame::* currentRenderScreenFn)(int width, int height);
382
383 map<string, vector<UIValue>> valueLists;
384
385 int score;
386 float fps;
387
388 // TODO: Make a separate TImer class
389 time_point<steady_clock> startTime;
390 float fpsStartTime, curTime, prevTime, elapsedTime;
391
392 int frameCount;
393
394 /*** Functions ***/
395
396 bool initUI(int width, int height, unsigned char guiFlags);
397 void initVulkan();
398 void initGraphicsPipelines();
399 void initMatrices();
400 void renderLoop();
401 void updateScene();
402 void cleanup();
403
404 void createVulkanInstance(const vector<const char*>& validationLayers);
405 void setupDebugMessenger();
406 void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo);
407 void createVulkanSurface();
408 void pickPhysicalDevice(const vector<const char*>& deviceExtensions);
409 bool isDeviceSuitable(VkPhysicalDevice physicalDevice, const vector<const char*>& deviceExtensions);
410 void createLogicalDevice(const vector<const char*>& validationLayers,
411 const vector<const char*>& deviceExtensions);
412 void chooseSwapChainProperties();
413 void createSwapChain();
414 void createImageViews();
415 void createResourceCommandPool();
416 void createImageResources();
417 VkFormat findDepthFormat(); // TODO: Declare/define (in the cpp file) this function in some util functions section
418 void createRenderPass();
419 void createCommandPools();
420 void createFramebuffers();
421 void createCommandBuffers();
422 void createSyncObjects();
423
424 void createTextureSampler();
425
426 void initImGuiOverlay();
427 void cleanupImGuiOverlay();
428
429 // TODO: Maybe move these to a different class, possibly VulkanBuffer or some new related class
430
431 void createBufferSet(VkDeviceSize bufferSize, VkBufferUsageFlags usages, VkMemoryPropertyFlags properties,
432 BufferSet& set);
433
434 template<class VertexType, class SSBOType>
435 void resizeBufferSet(BufferSet& set, VulkanBuffer<SSBOType>& buffer,
436 GraphicsPipeline_Vulkan<VertexType>& pipeline, VkCommandPool commandPool,
437 VkQueue graphicsQueue);
438
439 template<class SSBOType>
440 void updateBufferSet(BufferSet& set, size_t objIndex, SSBOType& ssbo);
441
442 // TODO: Since addObject() returns a reference to the new object now,
443 // stop using objects.back() to access the object that was just created
444 template<class VertexType, class SSBOType>
445 SceneObject<VertexType, SSBOType>& addObject(vector<SceneObject<VertexType, SSBOType>>& objects,
446 GraphicsPipeline_Vulkan<VertexType>& pipeline,
447 const vector<VertexType>& vertices, vector<uint16_t> indices,
448 VulkanBuffer<SSBOType>& objectBuffer, SSBOType ssbo);
449
450 template<class VertexType>
451 vector<VertexType> addObjectIndex(unsigned int objIndex, vector<VertexType> vertices);
452
453 template<class VertexType>
454 vector<VertexType> addVertexNormals(vector<VertexType> vertices);
455
456 template<class VertexType, class SSBOType>
457 void centerObject(SceneObject<VertexType, SSBOType>& object);
458
459 template<class VertexType, class SSBOType>
460 void updateObject(SceneObject<VertexType, SSBOType>& obj);
461
462 template<class VertexType, class SSBOType>
463 void updateObjectVertices(GraphicsPipeline_Vulkan<VertexType>& pipeline,
464 SceneObject<VertexType, SSBOType>& obj, size_t index);
465
466 void addLaser(vec3 start, vec3 end, vec3 color, float width);
467 void translateLaser(size_t index, const vec3& translation);
468 void updateLaserTarget(size_t index);
469 bool getLaserAndAsteroidIntersection(SceneObject<ModelVertex, SSBO_Asteroid>& asteroid,
470 vec3& start, vec3& end, vec3& intersection);
471
472 void addExplosion(mat4 model_mat, float duration, float cur_time);
473
474 void renderFrame(ImDrawData* draw_data);
475 void presentFrame();
476
477 void recreateSwapChain();
478
479 void cleanupSwapChain();
480
481 /*** High-level functions ***/
482
483 void renderMainScreen(int width, int height);
484 void renderGameScreen(int width, int height);
485
486 void initGuiValueLists(map<string, vector<UIValue>>& valueLists);
487 void renderGuiValueList(vector<UIValue>& values);
488
489 void goToScreen(void (VulkanGame::* renderScreenFn)(int width, int height));
490 void quitGame();
491};
492
493// Start of specialized no-op functions
494
495template<>
496inline void VulkanGame::centerObject(SceneObject<ExplosionVertex, SSBO_Explosion>& object) {
497}
498
499// End of specialized no-op functions
500
501template<class VertexType, class SSBOType>
502void VulkanGame::resizeBufferSet(BufferSet& set, VulkanBuffer<SSBOType>& buffer,
503 GraphicsPipeline_Vulkan<VertexType>& pipeline, VkCommandPool commandPool,
504 VkQueue graphicsQueue) {
505 VkDeviceSize newSize = buffer.capacity * sizeof(SSBOType);
506
507 for (size_t i = 0; i < set.buffers.size(); i++) {
508 VkBuffer newBuffer;
509 VkDeviceMemory newMemory;
510
511 VulkanUtils::createBuffer(device, physicalDevice, newSize, set.usages, set.properties, newBuffer, newMemory);
512
513 VulkanUtils::copyBuffer(device, commandPool, set.buffers[i], newBuffer, 0, 0, set.infoSet[i].range,
514 graphicsQueue);
515
516 vkDestroyBuffer(device, set.buffers[i], nullptr);
517 vkFreeMemory(device, set.memory[i], nullptr);
518
519 set.buffers[i] = newBuffer;
520 set.memory[i] = newMemory;
521
522 set.infoSet[i].buffer = set.buffers[i];
523 set.infoSet[i].offset = 0; // This is the offset from the start of the buffer, so always 0 for now
524 set.infoSet[i].range = newSize; // Size of the update starting from offset, or VK_WHOLE_SIZE
525 }
526
527 // Assume the SSBO is always the 2nd binding
528 // TODO: Figure out a way to make this more flexible
529 pipeline.updateDescriptorInfo(1, &set.infoSet, swapChainImages.size());
530}
531
532// TODO: See if it makes sense to pass in the current swapchain index instead of updating all of them
533template<class SSBOType>
534void VulkanGame::updateBufferSet(BufferSet& set, size_t objIndex, SSBOType& ssbo) {
535 for (size_t i = 0; i < set.memory.size(); i++) {
536 VulkanUtils::copyDataToMemory(device, &ssbo, set.memory[i], objIndex * sizeof(SSBOType), sizeof(ssbo), false);
537 }
538}
539
540// TODO: Right now, it's basically necessary to pass the identity matrix in for ssbo.model
541// and to change the model matrix later by setting model_transform and then calling updateObject()
542// Figure out a better way to allow the model matrix to be set during object creation
543template<class VertexType, class SSBOType>
544SceneObject<VertexType, SSBOType>& VulkanGame::addObject(vector<SceneObject<VertexType, SSBOType>>& objects,
545 GraphicsPipeline_Vulkan<VertexType>& pipeline,
546 const vector<VertexType>& vertices, vector<uint16_t> indices,
547 VulkanBuffer<SSBOType>& objectBuffer, SSBOType ssbo) {
548 // TODO: Use the model field of ssbo to set the object's model_base
549 // currently, the passed in model is useless since it gets overridden in updateObject() anyway
550 size_t numVertices = pipeline.getNumVertices();
551
552 for (uint16_t& idx : indices) {
553 idx += numVertices;
554 }
555
556 objects.push_back({ vertices, indices, ssbo, mat4(1.0f), mat4(1.0f), false });
557 objectBuffer.add(ssbo);
558
559 SceneObject<VertexType, SSBOType>& obj = objects.back();
560
561 // TODO: Specify whether to center the object outside of this function or, worst case, maybe
562 // with a boolean being passed in here, so that I don't have to rely on checking the specific object
563 // type
564 // TODO: Actually, I've already defined a no-op centerObject method for explosions
565 // Maybe I should do the same for lasers and remove this conditional altogether
566 if (!is_same_v<VertexType, LaserVertex> && !is_same_v<VertexType, ExplosionVertex>) {
567 centerObject(obj);
568 }
569
570 pipeline.addObject(obj.vertices, obj.indices, resourceCommandPool, graphicsQueue);
571
572 return obj;
573}
574
575template<class VertexType>
576vector<VertexType> VulkanGame::addObjectIndex(unsigned int objIndex, vector<VertexType> vertices) {
577 for (VertexType& vertex : vertices) {
578 vertex.objIndex = objIndex;
579 }
580
581 return vertices;
582}
583
584// This function sets all the normals for a face to be parallel
585// This is good for models that should have distinct faces, but bad for models that should appear smooth
586// Maybe add an option to set all copies of a point to have the same normal and have the direction of
587// that normal be the weighted average of all the faces it is a part of, where the weight from each face
588// is its surface area.
589
590// TODO: Since the current approach to normal calculation basicaly makes indexed drawing useless, see if it's
591// feasible to automatically enable/disable indexed drawing based on which approach is used
592template<class VertexType>
593vector<VertexType> VulkanGame::addVertexNormals(vector<VertexType> vertices) {
594 for (unsigned int i = 0; i < vertices.size(); i += 3) {
595 vec3 p1 = vertices[i].pos;
596 vec3 p2 = vertices[i + 1].pos;
597 vec3 p3 = vertices[i + 2].pos;
598
599 vec3 normal = normalize(cross(p2 - p1, p3 - p1));
600
601 // Add the same normal for all 3 vertices
602 vertices[i].normal = normal;
603 vertices[i + 1].normal = normal;
604 vertices[i + 2].normal = normal;
605 }
606
607 return vertices;
608}
609
610template<class VertexType, class SSBOType>
611void VulkanGame::centerObject(SceneObject<VertexType, SSBOType>& object) {
612 vector<VertexType>& vertices = object.vertices;
613
614 float min_x = vertices[0].pos.x;
615 float max_x = vertices[0].pos.x;
616 float min_y = vertices[0].pos.y;
617 float max_y = vertices[0].pos.y;
618 float min_z = vertices[0].pos.z;
619 float max_z = vertices[0].pos.z;
620
621 // start from the second point
622 for (unsigned int i = 1; i < vertices.size(); i++) {
623 vec3& pos = vertices[i].pos;
624
625 if (min_x > pos.x) {
626 min_x = pos.x;
627 } else if (max_x < pos.x) {
628 max_x = pos.x;
629 }
630
631 if (min_y > pos.y) {
632 min_y = pos.y;
633 } else if (max_y < pos.y) {
634 max_y = pos.y;
635 }
636
637 if (min_z > pos.z) {
638 min_z = pos.z;
639 } else if (max_z < pos.z) {
640 max_z = pos.z;
641 }
642 }
643
644 vec3 center = vec3(min_x + max_x, min_y + max_y, min_z + max_z) / 2.0f;
645
646 for (unsigned int i = 0; i < vertices.size(); i++) {
647 vertices[i].pos -= center;
648 }
649
650 object.radius = std::max(max_x - center.x, max_y - center.y);
651 object.radius = std::max(object.radius, max_z - center.z);
652
653 object.center = vec3(0.0f, 0.0f, 0.0f);
654}
655
656// TODO: Just pass in the single object instead of a list of all of them
657template<class VertexType, class SSBOType>
658void VulkanGame::updateObject(SceneObject<VertexType, SSBOType>& obj) {
659 obj.ssbo.model = obj.model_transform * obj.model_base;
660 obj.center = vec3(obj.ssbo.model * vec4(0.0f, 0.0f, 0.0f, 1.0f));
661
662 obj.modified = false;
663}
664
665template<class VertexType, class SSBOType>
666void VulkanGame::updateObjectVertices(GraphicsPipeline_Vulkan<VertexType>& pipeline,
667 SceneObject<VertexType, SSBOType>& obj, size_t index) {
668 pipeline.updateObjectVertices(index, obj.vertices, resourceCommandPool, graphicsQueue);
669}
670
671#endif // _VULKAN_GAME_H
Note: See TracBrowser for help on using the repository browser.