summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/candy_gear.cpp28
-rw-r--r--src/candy_gear.hpp2
-rw-r--r--src/core.cpp3
-rw-r--r--src/main.cpp6
-rw-r--r--src/sprite.cpp17
-rw-r--r--src/sprite.hpp2
-rw-r--r--src/view.cpp94
-rw-r--r--src/view_2d.cpp81
-rw-r--r--src/view_2d.hpp (renamed from src/view.hpp)10
-rw-r--r--src/view_3d.cpp113
-rw-r--r--src/view_3d.hpp27
-rw-r--r--src/vk/graphics_pipeline_2d.cpp24
-rw-r--r--src/vk/graphics_pipeline_2d.hpp5
-rw-r--r--src/vk/graphics_pipeline_3d.cpp2
-rw-r--r--src/vk/graphics_pipeline_3d.hpp4
-rw-r--r--src/vk/renderer.cpp31
-rw-r--r--src/vk/renderer.hpp12
-rw-r--r--src/vk/view_2d.cpp (renamed from src/vk/view.cpp)122
-rw-r--r--src/vk/view_2d.hpp (renamed from src/vk/view.hpp)24
-rw-r--r--src/vk/view_3d.cpp159
-rw-r--r--src/vk/view_3d.hpp47
-rw-r--r--test/src/main.rb10
22 files changed, 537 insertions, 286 deletions
diff --git a/src/candy_gear.cpp b/src/candy_gear.cpp
index 8ba87cc..7ed1d13 100644
--- a/src/candy_gear.cpp
+++ b/src/candy_gear.cpp
@@ -22,9 +22,8 @@
#include <yaml-cpp/yaml.h>
-#include "rotation_3d.hpp"
-#include "vector_3d.hpp"
-#include "view.hpp"
+#include "view_2d.hpp"
+#include "view_3d.hpp"
static mrb_value
parse_node(mrb_state *mrb, const YAML::Node &node)
@@ -75,30 +74,37 @@ cg_mCandyGear_load_yaml(mrb_state *mrb, mrb_value self)
static mrb_value
cg_mCandyGear_set_views(mrb_state *mrb, mrb_value self)
{
- struct RClass *cg_m, *cg_cView;
+ struct RClass *cg_m, *cg_cView2D, *cg_cView3D;
mrb_value *array;
mrb_int array_len;
- std::vector<std::shared_ptr<VK::View>> views;
+ std::vector<std::shared_ptr<VK::View2D>> views_2d;
+ std::vector<std::shared_ptr<VK::View3D>> views_3d;
cg_m = mrb_module_get(mrb, "CandyGear");
- cg_cView = mrb_class_get_under(mrb, cg_m, "View");
+ cg_cView2D = mrb_class_get_under(mrb, cg_m, "View2D");
+ cg_cView3D = mrb_class_get_under(mrb, cg_m, "View3D");
mrb_get_args(mrb, "a", &array, &array_len);
for(mrb_int i{0}; i < array_len; i++)
{
- if(mrb_obj_is_kind_of(mrb, array[i], cg_cView))
+ if(mrb_obj_is_kind_of(mrb, array[i], cg_cView2D))
{
- auto v = (std::shared_ptr<VK::View>*)DATA_PTR(array[i]);
- views.push_back(*v);
+ auto v = (std::shared_ptr<VK::View2D>*)DATA_PTR(array[i]);
+ views_2d.push_back(*v);
+ }
+ else if(mrb_obj_is_kind_of(mrb, array[i], cg_cView3D))
+ {
+ auto v = (std::shared_ptr<VK::View3D>*)DATA_PTR(array[i]);
+ views_3d.push_back(*v);
}
}
// A Renderer need at least one view to work.
- if(views.size() > 0)
+ if(views_2d.size() > 0 || views_3d.size() > 0)
{
delete cg_core.vk_renderer;
- cg_core.vk_renderer = new VK::Renderer({views});
+ cg_core.vk_renderer = new VK::Renderer({views_2d, views_3d});
}
return self;
diff --git a/src/candy_gear.hpp b/src/candy_gear.hpp
index 487ab13..44c6fb5 100644
--- a/src/candy_gear.hpp
+++ b/src/candy_gear.hpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#ifndef CANDY_GEAR_GRAPHIC_H
+#ifndef CANDY_GEAR_CANDY_GEAR_H
#define CANDY_GEAR_CANDY_GEAR_H 1
#include "core.hpp"
diff --git a/src/core.cpp b/src/core.cpp
index 5827ef6..8d828d6 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -539,7 +539,8 @@ load_vk_renderer(void *obj)
static_cast<float>(cg_core.screen_width),
static_cast<float>(cg_core.screen_height));
cg_core.vk_renderer = new VK::Renderer(
- {std::make_shared<VK::View>(region)});
+ {},
+ {std::make_shared<VK::View3D>(region)});
}
catch(const CommandError &e)
{
diff --git a/src/main.cpp b/src/main.cpp
index 21e2c29..d818c8f 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -27,7 +27,8 @@
#include "texture.hpp"
#include "vector_3d.hpp"
#include "vector_4d.hpp"
-#include "view.hpp"
+#include "view_2d.hpp"
+#include "view_3d.hpp"
cg_sCore cg_core;
@@ -70,7 +71,8 @@ int main(int argc, char *argv[])
cg_texture_init(cg_core.mrb);
cg_vector_3d_init(cg_core.mrb);
cg_vector_4d_init(cg_core.mrb);
- cg_view_init(cg_core.mrb);
+ cg_view_2d_init(cg_core.mrb);
+ cg_view_3d_init(cg_core.mrb);
main_obj = mrb_obj_iv_inspect(cg_core.mrb, cg_core.mrb->top_self);
sym_init = mrb_intern_cstr(cg_core.mrb, "init");
diff --git a/src/sprite.cpp b/src/sprite.cpp
index 96a702a..5f815f6 100644
--- a/src/sprite.cpp
+++ b/src/sprite.cpp
@@ -18,7 +18,6 @@
#include "texture.hpp"
#include "vector_4d.hpp"
-#include "view.hpp"
#include "vk/sprite.hpp"
void
@@ -53,21 +52,6 @@ cg_cSprite_initialize(mrb_state *mrb, mrb_value self)
return self;
}
-static mrb_value
-cg_cSprite_draw(mrb_state *mrb, mrb_value self)
-{
- std::shared_ptr<VK::View> *view;
- std::shared_ptr<glm::vec4> *position;
- auto *ptr = (std::shared_ptr<VK::Sprite>*)DATA_PTR(self);
-
- mrb_get_args(mrb, "dd", &view, &cg_view_type, &position, &cg_vector_4d_type);
- auto &positions = (*view)->sprites_to_draw[
- cg_core.vk_swapchain->current_frame][*ptr];
- positions.push_back(*position->get());
-
- return self;
-}
-
void
cg_sprite_init(mrb_state *mrb)
{
@@ -78,5 +62,4 @@ cg_sprite_init(mrb_state *mrb)
MRB_SET_INSTANCE_TT(cg_cSprite, MRB_TT_DATA);
mrb_define_method(
mrb, cg_cSprite, "initialize", cg_cSprite_initialize, MRB_ARGS_REQ(2));
- mrb_define_method(mrb, cg_cSprite, "draw", cg_cSprite_draw, MRB_ARGS_REQ(2));
}
diff --git a/src/sprite.hpp b/src/sprite.hpp
index 6b21023..528f2f7 100644
--- a/src/sprite.hpp
+++ b/src/sprite.hpp
@@ -19,6 +19,8 @@
#include "core.hpp"
+extern const struct mrb_data_type cg_sprite_type;
+
void
cg_sprite_init(mrb_state *mrb);
diff --git a/src/view.cpp b/src/view.cpp
deleted file mode 100644
index 745c4bc..0000000
--- a/src/view.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2022 Frederico de Oliveira Linhares
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "view.hpp"
-
-#include "rotation_3d.hpp"
-#include "vector_3d.hpp"
-#include "vector_4d.hpp"
-#include "vk/view.hpp"
-
-void
-cg_free_view(mrb_state *mrb, void* obj)
-{
- auto ptr = static_cast<std::shared_ptr<VK::View>*>(obj);
-
- ptr->~shared_ptr();
- mrb_free(mrb, ptr);
-}
-
-const struct mrb_data_type cg_view_type = { "CG_View", cg_free_view };
-
-static mrb_value
-cg_cView_initialize(mrb_state *mrb, mrb_value self)
-{
- std::shared_ptr<glm::vec4> *region;
- std::shared_ptr<VK::View> *ptr;
-
- mrb_get_args(mrb, "d", &region, &cg_vector_4d_type);
- ptr = (std::shared_ptr<VK::View>*)DATA_PTR(self);
- if(ptr) mrb_free(mrb, ptr);
- ptr = (std::shared_ptr<VK::View>*)mrb_malloc(
- mrb, sizeof(std::shared_ptr<VK::View>));
-
- new(ptr)std::shared_ptr<VK::View>(
- std::make_shared<VK::View>(*region->get()));
-
- mrb_data_init(self, ptr, &cg_view_type);
- return self;
-}
-
-static mrb_value
-cg_cView_set_camera_position(mrb_state *mrb, mrb_value self)
-{
- std::shared_ptr<glm::vec3> *camera_position;
- auto ptr = (std::shared_ptr<VK::View>*)DATA_PTR(self);
-
- mrb_get_args(mrb, "d", &camera_position, &cg_vector_3d_type);
- (*ptr)->camera_position = (*camera_position);
-
- return self;
-}
-
-static mrb_value
-cg_cView_set_camera_rotation(mrb_state *mrb, mrb_value self)
-{
- std::shared_ptr<glm::vec3> *camera_rotation;
- auto ptr = (std::shared_ptr<VK::View>*)DATA_PTR(self);
-
- mrb_get_args(mrb, "d", &camera_rotation, &cg_rotation_3d_type);
- (*ptr)->camera_rotation = (*camera_rotation);
-
- return self;
-}
-
-void
-cg_view_init(mrb_state *mrb)
-{
- struct RClass *cg_m, *cg_cView;
-
- cg_m = mrb_module_get(mrb, "CandyGear");
- cg_cView = mrb_define_class_under(mrb, cg_m, "View", mrb->object_class);
- MRB_SET_INSTANCE_TT(cg_cView, MRB_TT_DATA);
- mrb_define_method(
- mrb, cg_cView, "initialize", cg_cView_initialize, MRB_ARGS_REQ(1));
- mrb_define_method(
- mrb, cg_cView, "camera_position=", cg_cView_set_camera_position,
- MRB_ARGS_REQ(1));
- mrb_define_method(
- mrb, cg_cView, "camera_rotation=", cg_cView_set_camera_rotation,
- MRB_ARGS_REQ(1));
-}
diff --git a/src/view_2d.cpp b/src/view_2d.cpp
new file mode 100644
index 0000000..c84cbee
--- /dev/null
+++ b/src/view_2d.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2022 Frederico de Oliveira Linhares
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "view_2d.hpp"
+
+#include "sprite.hpp"
+#include "vector_4d.hpp"
+#include "vk/sprite.hpp"
+#include "vk/view_2d.hpp"
+
+void
+cg_free_view_2d(mrb_state *mrb, void* obj)
+{
+ auto ptr = static_cast<std::shared_ptr<VK::View2D>*>(obj);
+
+ ptr->~shared_ptr();
+ mrb_free(mrb, ptr);
+}
+
+const struct mrb_data_type cg_view_2d_type = { "CG_View2D", cg_free_view_2d };
+
+static mrb_value
+cg_cView2D_initialize(mrb_state *mrb, mrb_value self)
+{
+ std::shared_ptr<glm::vec4> *region;
+ std::shared_ptr<VK::View2D> *ptr;
+
+ mrb_get_args(mrb, "d", &region, &cg_vector_4d_type);
+ ptr = (std::shared_ptr<VK::View2D>*)DATA_PTR(self);
+ if(ptr) mrb_free(mrb, ptr);
+ ptr = (std::shared_ptr<VK::View2D>*)mrb_malloc(
+ mrb, sizeof(std::shared_ptr<VK::View2D>));
+
+ new(ptr)std::shared_ptr<VK::View2D>(
+ std::make_shared<VK::View2D>(*region->get()));
+
+ mrb_data_init(self, ptr, &cg_view_2d_type);
+ return self;
+}
+
+static mrb_value
+cg_cView2D_draw(mrb_state *mrb, mrb_value self)
+{
+ std::shared_ptr<VK::Sprite> *sprite;
+ std::shared_ptr<glm::vec4> *position;
+ auto *ptr = (std::shared_ptr<VK::View2D>*)DATA_PTR(self);
+
+ mrb_get_args(mrb, "dd", &sprite, &cg_sprite_type,
+ &position, &cg_vector_4d_type);
+ auto &positions = (*ptr)->sprites_to_draw[
+ cg_core.vk_swapchain->current_frame][*sprite];
+ positions.push_back(*position->get());
+
+ return self;
+}
+
+void
+cg_view_2d_init(mrb_state *mrb)
+{
+ struct RClass *cg_m, *cg_cView2D;
+
+ cg_m = mrb_module_get(mrb, "CandyGear");
+ cg_cView2D = mrb_define_class_under(mrb, cg_m, "View2D", mrb->object_class);
+ MRB_SET_INSTANCE_TT(cg_cView2D, MRB_TT_DATA);
+ mrb_define_method(
+ mrb, cg_cView2D, "initialize", cg_cView2D_initialize, MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, cg_cView2D, "draw", cg_cView2D_draw, MRB_ARGS_REQ(2));
+}
diff --git a/src/view.hpp b/src/view_2d.hpp
index ae22b59..0b33380 100644
--- a/src/view.hpp
+++ b/src/view_2d.hpp
@@ -14,14 +14,14 @@
* limitations under the License.
*/
-#ifndef CANDY_GEAR_VIEW_H
-#define CANDY_GEAR_VIEW_H 1
+#ifndef CANDY_GEAR_VIEW_2D_H
+#define CANDY_GEAR_VIEW_2D_H 1
#include "core.hpp"
-extern const struct mrb_data_type cg_view_type;
+extern const struct mrb_data_type cg_view_2d_type;
void
-cg_view_init(mrb_state *mrb);
+cg_view_2d_init(mrb_state *mrb);
-#endif /* CANDY_GEAR_VIEW_H */
+#endif /* CANDY_GEAR_VIEW_2D_H */
diff --git a/src/view_3d.cpp b/src/view_3d.cpp
new file mode 100644
index 0000000..4e8b254
--- /dev/null
+++ b/src/view_3d.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2022 Frederico de Oliveira Linhares
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "view_3d.hpp"
+
+#include "sprite.hpp"
+#include "rotation_3d.hpp"
+#include "vector_3d.hpp"
+#include "vector_4d.hpp"
+#include "vk/sprite.hpp"
+#include "vk/view_3d.hpp"
+
+void
+cg_free_view_3d(mrb_state *mrb, void* obj)
+{
+ auto ptr = static_cast<std::shared_ptr<VK::View3D>*>(obj);
+
+ ptr->~shared_ptr();
+ mrb_free(mrb, ptr);
+}
+
+const struct mrb_data_type cg_view_3d_type = { "CG_View3D", cg_free_view_3d };
+
+static mrb_value
+cg_cView3D_initialize(mrb_state *mrb, mrb_value self)
+{
+ std::shared_ptr<glm::vec4> *region;
+ std::shared_ptr<VK::View3D> *ptr;
+
+ mrb_get_args(mrb, "d", &region, &cg_vector_4d_type);
+ ptr = (std::shared_ptr<VK::View3D>*)DATA_PTR(self);
+ if(ptr) mrb_free(mrb, ptr);
+ ptr = (std::shared_ptr<VK::View3D>*)mrb_malloc(
+ mrb, sizeof(std::shared_ptr<VK::View3D>));
+
+ new(ptr)std::shared_ptr<VK::View3D>(
+ std::make_shared<VK::View3D>(*region->get()));
+
+ mrb_data_init(self, ptr, &cg_view_3d_type);
+ return self;
+}
+
+static mrb_value
+cg_cView3D_set_camera_position(mrb_state *mrb, mrb_value self)
+{
+ std::shared_ptr<glm::vec3> *camera_position;
+ auto ptr = (std::shared_ptr<VK::View3D>*)DATA_PTR(self);
+
+ mrb_get_args(mrb, "d", &camera_position, &cg_vector_3d_type);
+ (*ptr)->camera_position = (*camera_position);
+
+ return self;
+}
+
+static mrb_value
+cg_cView3D_set_camera_rotation(mrb_state *mrb, mrb_value self)
+{
+ std::shared_ptr<glm::vec3> *camera_rotation;
+ auto ptr = (std::shared_ptr<VK::View3D>*)DATA_PTR(self);
+
+ mrb_get_args(mrb, "d", &camera_rotation, &cg_rotation_3d_type);
+ (*ptr)->camera_rotation = (*camera_rotation);
+
+ return self;
+}
+
+static mrb_value
+cg_cView3D_draw(mrb_state *mrb, mrb_value self)
+{
+ std::shared_ptr<VK::Sprite> *sprite;
+ std::shared_ptr<glm::vec4> *position;
+ auto *ptr = (std::shared_ptr<VK::View3D>*)DATA_PTR(self);
+
+ mrb_get_args(mrb, "dd", &sprite, &cg_sprite_type,
+ &position, &cg_vector_4d_type);
+ auto &positions = (*ptr)->sprites_to_draw[
+ cg_core.vk_swapchain->current_frame][*sprite];
+ positions.push_back(*position->get());
+
+ return self;
+}
+
+void
+cg_view_3d_init(mrb_state *mrb)
+{
+ struct RClass *cg_m, *cg_cView3D;
+
+ cg_m = mrb_module_get(mrb, "CandyGear");
+ cg_cView3D = mrb_define_class_under(mrb, cg_m, "View3D", mrb->object_class);
+ MRB_SET_INSTANCE_TT(cg_cView3D, MRB_TT_DATA);
+ mrb_define_method(
+ mrb, cg_cView3D, "initialize", cg_cView3D_initialize, MRB_ARGS_REQ(1));
+ mrb_define_method(
+ mrb, cg_cView3D, "camera_position=", cg_cView3D_set_camera_position,
+ MRB_ARGS_REQ(1));
+ mrb_define_method(
+ mrb, cg_cView3D, "camera_rotation=", cg_cView3D_set_camera_rotation,
+ MRB_ARGS_REQ(1));
+ mrb_define_method(mrb, cg_cView3D, "draw", cg_cView3D_draw, MRB_ARGS_REQ(2));
+}
diff --git a/src/view_3d.hpp b/src/view_3d.hpp
new file mode 100644
index 0000000..22aa084
--- /dev/null
+++ b/src/view_3d.hpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2022 Frederico de Oliveira Linhares
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CANDY_GEAR_VIEW_3D_H
+#define CANDY_GEAR_VIEW_3D_H 1
+
+#include "core.hpp"
+
+extern const struct mrb_data_type cg_view_3d_type;
+
+void
+cg_view_3d_init(mrb_state *mrb);
+
+#endif /* CANDY_GEAR_VIEW_3D_H */
diff --git a/src/vk/graphics_pipeline_2d.cpp b/src/vk/graphics_pipeline_2d.cpp
index 08bdb6e..1509d2f 100644
--- a/src/vk/graphics_pipeline_2d.cpp
+++ b/src/vk/graphics_pipeline_2d.cpp
@@ -47,8 +47,8 @@ load_framebuffer(void *obj)
framebuffer_info.layers = 1;
if(vkCreateFramebuffer(
- cg_core.vk_device_with_swapchain->device, &framebuffer_info, nullptr,
- &self->swapchain_framebuffers[i])
+ cg_core.vk_device_with_swapchain->device, &framebuffer_info, nullptr,
+ &self->swapchain_framebuffers[i])
!= VK_SUCCESS)
throw CommandError{"Failed to create Vulkan Framebuffer."};
}
@@ -272,7 +272,7 @@ GraphicsPipeline2D::~GraphicsPipeline2D()
void
GraphicsPipeline2D::draw(
- std::shared_ptr<View> view, const VkCommandBuffer draw_command_buffer,
+ std::shared_ptr<View2D> view, const VkCommandBuffer draw_command_buffer,
const size_t current_frame, const size_t next_frame,
const uint32_t image_index)
{
@@ -301,21 +301,21 @@ GraphicsPipeline2D::draw(
// Commands
{
std::array<VkDescriptorSet, 2> vk_descriptor_sets{
- view->descriptor_sets_2d[image_index],
- sprite->descriptor_sets[image_index]};
+ view->descriptor_sets_2d[image_index],
+ sprite->descriptor_sets[image_index]};
VkDeviceSize offsets[]{0};
vkCmdBindDescriptorSets(
- draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
- cg_core.vk_graphics_pipeline_2d_layout->pipeline, 0,
- vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr);
+ draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
+ cg_core.vk_graphics_pipeline_2d_layout->pipeline, 0,
+ vk_descriptor_sets.size(), vk_descriptor_sets.data(), 0, nullptr);
vkCmdBindPipeline(
- draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
- this->graphic_pipeline);
+ draw_command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
+ this->graphic_pipeline);
vkCmdBindVertexBuffers(
- draw_command_buffer, 0, 1, &sprite->vertex_buffer->buffer, offsets);
+ draw_command_buffer, 0, 1, &sprite->vertex_buffer->buffer, offsets);
vkCmdDraw(
- draw_command_buffer, Sprite::vertex_count, positions.size(), 0, 0);
+ draw_command_buffer, Sprite::vertex_count, positions.size(), 0, 0);
}
VK::UBOSpritePositions ubo_sprite_positions;
diff --git a/src/vk/graphics_pipeline_2d.hpp b/src/vk/graphics_pipeline_2d.hpp
index dd4bb29..ffa373a 100644
--- a/src/vk/graphics_pipeline_2d.hpp
+++ b/src/vk/graphics_pipeline_2d.hpp
@@ -23,14 +23,13 @@
#include "core.hpp"
#include "sprite.hpp"
-#include "view.hpp"
+#include "view_2d.hpp"
namespace VK
{
struct GraphicsPipeline2D
{
- VkRenderPass render_pass;
std::vector<VkFramebuffer> swapchain_framebuffers;
VkPipeline graphic_pipeline;
@@ -38,7 +37,7 @@ struct GraphicsPipeline2D
~GraphicsPipeline2D();
void
- draw(std::shared_ptr<View> view, const VkCommandBuffer draw_command_buffer,
+ draw(std::shared_ptr<View2D> view, const VkCommandBuffer draw_command_buffer,
const size_t current_frame, const size_t next_frame,
const uint32_t image_index);
};
diff --git a/src/vk/graphics_pipeline_3d.cpp b/src/vk/graphics_pipeline_3d.cpp
index 02fbfd9..fbf5b80 100644
--- a/src/vk/graphics_pipeline_3d.cpp
+++ b/src/vk/graphics_pipeline_3d.cpp
@@ -534,7 +534,7 @@ GraphicsPipeline3D::~GraphicsPipeline3D()
void
GraphicsPipeline3D::draw(
- std::shared_ptr<View> view, const VkCommandBuffer draw_command_buffer,
+ std::shared_ptr<View3D> view, const VkCommandBuffer draw_command_buffer,
const size_t current_frame, const uint32_t image_index)
{
// Set viewport
diff --git a/src/vk/graphics_pipeline_3d.hpp b/src/vk/graphics_pipeline_3d.hpp
index a7cf117..925df77 100644
--- a/src/vk/graphics_pipeline_3d.hpp
+++ b/src/vk/graphics_pipeline_3d.hpp
@@ -26,7 +26,7 @@
#include "model.hpp"
#include "model_instance.hpp"
#include "uniform_buffer.hpp"
-#include "view.hpp"
+#include "view_3d.hpp"
namespace VK
{
@@ -52,7 +52,7 @@ struct GraphicsPipeline3D
~GraphicsPipeline3D();
void
- draw(std::shared_ptr<View> view, const VkCommandBuffer draw_command_buffer,
+ draw(std::shared_ptr<View3D> view, const VkCommandBuffer draw_command_buffer,
const size_t current_frame, const uint32_t image_index);
};
diff --git a/src/vk/renderer.cpp b/src/vk/renderer.cpp
index 7531e19..5ebc271 100644
--- a/src/vk/renderer.cpp
+++ b/src/vk/renderer.cpp
@@ -29,8 +29,10 @@ load_descriptor_pool(void *obj)
auto self = static_cast<VK::Renderer*>(obj);
uint32_t uniform_buffer_count = 0;
- for(auto &view : self->views)
+ for(auto &view : self->views_3d)
uniform_buffer_count += (view->ub_3d.size() + view->ub_2d.size());
+ for(auto &view : self->views_2d)
+ uniform_buffer_count += (view->ub_2d.size());
VkDescriptorPoolSize descriptor_pool_size{};
descriptor_pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
@@ -49,7 +51,9 @@ load_descriptor_pool(void *obj)
&self->descriptor_pool) != VK_SUCCESS)
throw CommandError{"Failed to create a Vulkan descriptor pool."};
- for(auto &view : self->views)
+ for(auto &view : self->views_3d)
+ view->load_descriptor_sets(self->descriptor_pool);
+ for(auto &view : self->views_2d)
view->load_descriptor_sets(self->descriptor_pool);
}
@@ -58,7 +62,8 @@ unload_descriptor_pool(void *obj)
{
auto self = static_cast<VK::Renderer*>(obj);
- for(auto &view : self->views) view->unload_descriptor_sets();
+ for(auto &view : self->views_3d) view->unload_descriptor_sets();
+ for(auto &view : self->views_2d) view->unload_descriptor_sets();
vkDestroyDescriptorPool(
cg_core.vk_device_with_swapchain->device, self->descriptor_pool,
@@ -136,15 +141,18 @@ const CommandChain loader{
namespace VK
{
-Renderer::Renderer(std::vector<std::shared_ptr<View>> views):
+Renderer::Renderer(std::vector<std::shared_ptr<View2D>> views_2d,
+ std::vector<std::shared_ptr<View3D>> views_3d):
models_to_draw{cg_core.vk_swapchain->images_count},
- views{views}
+ views_2d{views_2d},
+ views_3d{views_3d}
{
loader.execute(this);
}
-Renderer::Renderer(std::initializer_list<std::shared_ptr<View>> views):
- Renderer{std::vector<std::shared_ptr<View>>(views)}
+Renderer::Renderer(std::initializer_list<std::shared_ptr<View2D>> views_2d,
+ std::initializer_list<std::shared_ptr<View3D>> views_3d):
+ Renderer(std::vector(views_2d), std::vector(views_3d))
{
}
@@ -212,7 +220,7 @@ Renderer::draw()
vkCmdBeginRenderPass(
draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
- for(auto &view: this->views)
+ for(auto &view: this->views_3d)
cg_core.vk_graphics_pipeline_3d->draw(
view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
image_index);
@@ -239,7 +247,12 @@ Renderer::draw()
vkCmdBeginRenderPass(
draw_command_buffer, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE);
- for(auto &view: this->views)
+ for(auto &view: this->views_2d)
+ cg_core.vk_graphics_pipeline_2d->draw(
+ view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
+ next_frame, image_index);
+
+ for(auto &view: this->views_3d)
cg_core.vk_graphics_pipeline_2d->draw(
view, draw_command_buffer, cg_core.vk_swapchain->current_frame,
next_frame, image_index);
diff --git a/src/vk/renderer.hpp b/src/vk/renderer.hpp
index 2b913fe..551e4e5 100644
--- a/src/vk/renderer.hpp
+++ b/src/vk/renderer.hpp
@@ -25,7 +25,8 @@
#include "model.hpp"
#include "model_instance.hpp"
#include "queue_family.hpp"
-#include "view.hpp"
+#include "view_2d.hpp"
+#include "view_3d.hpp"
namespace VK
{
@@ -37,13 +38,16 @@ struct Renderer
models_to_draw;
VkDescriptorPool descriptor_pool;
- std::vector<std::shared_ptr<View>> views;
+ std::vector<std::shared_ptr<View2D>> views_2d;
+ std::vector<std::shared_ptr<View3D>> views_3d;
QueueFamily *queue_family;
VkCommandPool command_pool;
std::vector<VkCommandBuffer> draw_command_buffers;
- Renderer(std::vector<std::shared_ptr<View>> views);
- Renderer(std::initializer_list<std::shared_ptr<View>> views);
+ Renderer(std::vector<std::shared_ptr<View2D>> views_2d,
+ std::vector<std::shared_ptr<View3D>> views_3d);
+ Renderer(std::initializer_list<std::shared_ptr<View2D>> views_2d,
+ std::initializer_list<std::shared_ptr<View3D>> views_3d);
~Renderer();
void
diff --git a/src/vk/view.cpp b/src/vk/view_2d.cpp
index b4ef722..623aa63 100644
--- a/src/vk/view.cpp
+++ b/src/vk/view_2d.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "view.hpp"
+#include "view_2d.hpp"
#include <array>
@@ -24,35 +24,9 @@ namespace
{
void
-load_3d_uniform_buffer(void *obj)
-{
- auto self = static_cast<VK::View*>(obj);
-
- try
- {
- self->ub_3d.reserve(cg_core.vk_swapchain->images_count);
- for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
- self->ub_3d.emplace_back(
- cg_core.vk_device_with_swapchain, sizeof(VK::UBOView3D));
- }
- catch(const std::exception& e)
- {
- throw CommandError{e.what()};
- }
-}
-
-void
-unload_3d_uniform_buffer(void *obj)
-{
- auto self = static_cast<VK::View*>(obj);
-
- self->ub_3d.clear();
-}
-
-void
load_2d_uniform_buffer(void *obj)
{
- auto self = static_cast<VK::View*>(obj);
+ auto self = static_cast<VK::View2D*>(obj);
try
{
@@ -70,37 +44,15 @@ load_2d_uniform_buffer(void *obj)
void
unload_2d_uniform_buffer(void *obj)
{
- auto self = static_cast<VK::View*>(obj);
+ auto self = static_cast<VK::View2D*>(obj);
self->ub_2d.clear();
}
void
-load_descriptor_sets_3d(void *obj)
-{
- auto self = static_cast<VK::View*>(obj);
-
- std::vector<VkDescriptorSetLayout> layouts(
- cg_core.vk_swapchain->images_count,
- cg_core.vk_graphics_pipeline_3d_layout->descriptor_set_view);
-
- VkDescriptorSetAllocateInfo alloc_info{};
- alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
- alloc_info.descriptorPool = self->descriptor_pool;
- alloc_info.descriptorSetCount = layouts.size();
- alloc_info.pSetLayouts = layouts.data();
-
- self->descriptor_sets_3d.resize(layouts.size());
- if(vkAllocateDescriptorSets(
- cg_core.vk_device_with_swapchain->device, &alloc_info,
- self->descriptor_sets_3d.data()) != VK_SUCCESS)
- throw CommandError{"Failed to create Vulkan descriptor sets for view."};
-}
-
-void
load_descriptor_sets_2d(void *obj)
{
- auto self = static_cast<VK::View*>(obj);
+ auto self = static_cast<VK::View2D*>(obj);
std::vector<VkDescriptorSetLayout> layouts(
cg_core.vk_swapchain->images_count,
@@ -120,45 +72,9 @@ load_descriptor_sets_2d(void *obj)
}
void
-load_resources_to_descriptor_sets_3d(void *obj)
-{
- auto self = static_cast<VK::View*>(obj);
-
- for(auto i{0}; i < self->ub_3d.size(); i++)
- {
- VkDescriptorBufferInfo view_3d_info{};
- view_3d_info.buffer = self->ub_3d[i].buffer;
- view_3d_info.offset = 0;
- view_3d_info.range = sizeof(VK::UBOView3D);
-
- std::array<VkWriteDescriptorSet, 1> write_descriptors{};
- write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
- write_descriptors[0].dstSet = self->descriptor_sets_3d[i];
- write_descriptors[0].dstBinding = 0;
- write_descriptors[0].dstArrayElement = 0;
- write_descriptors[0].descriptorCount = 1;
- write_descriptors[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
- write_descriptors[0].pBufferInfo = &view_3d_info;
- write_descriptors[0].pImageInfo = nullptr;
- write_descriptors[0].pTexelBufferView = nullptr;
-
- vkUpdateDescriptorSets(
- cg_core.vk_device_with_swapchain->device, write_descriptors.size(),
- write_descriptors.data(), 0, nullptr);
-
- VK::UBOView3D ubo_view_3d;
- ubo_view_3d.proj = glm::ortho(
- 0.0f, self->region.z,
- 0.0f, self->region.w,
- 0.0f, 100.0f);
- self->ub_3d[i].copy_data(&ubo_view_3d);
- }
-}
-
-void
load_resources_to_descriptor_sets_2d(void *obj)
{
- auto self = static_cast<VK::View*>(obj);
+ auto self = static_cast<VK::View2D*>(obj);
for(auto i{0}; i < self->ub_2d.size(); i++)
{
@@ -191,41 +107,35 @@ load_resources_to_descriptor_sets_2d(void *obj)
}
}
-const CommandChain loader{
- {&load_3d_uniform_buffer, &unload_3d_uniform_buffer},
+}
+
+namespace VK
+{
+
+const CommandChain View2D::loader{
{&load_2d_uniform_buffer, &unload_2d_uniform_buffer}
- // By destroying the pool the sets are also destroyed.
};
-const CommandChain descriptor_sets_loader{
- {&load_descriptor_sets_3d, nullptr},
+const CommandChain View2D::descriptor_sets_loader{
{&load_descriptor_sets_2d, nullptr},
- {&load_resources_to_descriptor_sets_3d, nullptr},
{&load_resources_to_descriptor_sets_2d, nullptr}
};
-}
-
-namespace VK
-{
-
-View::View(glm::vec4 region):
+View2D::View2D(glm::vec4 region):
region{region},
descriptor_pool{VK_NULL_HANDLE},
- camera_position{std::make_shared<glm::vec3>(0.0f, 0.0f, 0.0f)},
- camera_rotation{std::make_shared<glm::vec3>(0.0f, 0.0f, 0.0f)},
sprites_to_draw{cg_core.vk_swapchain->images_count}
{
loader.execute(this);
}
-View::~View()
+View2D::~View2D()
{
loader.revert(this);
}
void
-View::load_descriptor_sets(VkDescriptorPool descriptor_pool)
+View2D::load_descriptor_sets(VkDescriptorPool descriptor_pool)
{
if(this->descriptor_pool != VK_NULL_HANDLE) return;
@@ -234,7 +144,7 @@ View::load_descriptor_sets(VkDescriptorPool descriptor_pool)
}
void
-View::unload_descriptor_sets()
+View2D::unload_descriptor_sets()
{
if(this->descriptor_pool == VK_NULL_HANDLE) return;
diff --git a/src/vk/view.hpp b/src/vk/view_2d.hpp
index 5d133a9..f6741cc 100644
--- a/src/vk/view.hpp
+++ b/src/vk/view_2d.hpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#ifndef CANDY_GEAR_VK_VIEW_H
-#define CANDY_GEAR_VK_VIEW_H 1
+#ifndef CANDY_GEAR_VK_VIEW_2D_H
+#define CANDY_GEAR_VK_VIEW_2D_H 1
#include <memory>
#include <unordered_map>
@@ -27,35 +27,33 @@
namespace VK
{
-struct View
+struct View2D
{
glm::vec4 region;
// FIXME: if these vectors get resized, they can cause a segmentation fault!
- std::vector<UniformBuffer> ub_3d;
std::vector<UniformBuffer> ub_2d;
VkDescriptorPool descriptor_pool;
- std::vector<VkDescriptorSet> descriptor_sets_3d;
std::vector<VkDescriptorSet> descriptor_sets_2d;
- std::shared_ptr<glm::vec3> camera_position;
- std::shared_ptr<glm::vec3> camera_rotation;
-
std::vector<
std::unordered_map<std::shared_ptr<Sprite>, std::vector<glm::vec4>>>
sprites_to_draw;
- View(glm::vec4 region);
- ~View();
+ View2D(glm::vec4 region);
+ virtual ~View2D();
void
- load_descriptor_sets(VkDescriptorPool descriptor_pool);
+ virtual load_descriptor_sets(VkDescriptorPool descriptor_pool);
void
- unload_descriptor_sets();
+ virtual unload_descriptor_sets();
+
+protected:
+ static const CommandChain loader, descriptor_sets_loader;
};
}
-#endif /* CANDY_GEAR_VK_VIEW_H */
+#endif /* CANDY_GEAR_VK_VIEW_2D_H */
diff --git a/src/vk/view_3d.cpp b/src/vk/view_3d.cpp
new file mode 100644
index 0000000..9d124d9
--- /dev/null
+++ b/src/vk/view_3d.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2022 Frederico de Oliveira Linhares
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "view_3d.hpp"
+
+#include <array>
+
+#include "../core.hpp"
+
+namespace
+{
+
+void
+load_3d_uniform_buffer(void *obj)
+{
+ auto self = static_cast<VK::View3D*>(obj);
+
+ try
+ {
+ self->ub_3d.reserve(cg_core.vk_swapchain->images_count);
+ for(auto i{0}; i < cg_core.vk_swapchain->images_count; i++)
+ self->ub_3d.emplace_back(
+ cg_core.vk_device_with_swapchain, sizeof(VK::UBOView3D));
+ }
+ catch(const std::exception& e)
+ {
+ throw CommandError{e.what()};
+ }
+}
+
+void
+unload_3d_uniform_buffer(void *obj)
+{
+ auto self = static_cast<VK::View3D*>(obj);
+
+ self->ub_3d.clear();
+}
+
+void
+load_descriptor_sets_3d(void *obj)
+{
+ auto self = static_cast<VK::View3D*>(obj);
+
+ std::vector<VkDescriptorSetLayout> layouts(
+ cg_core.vk_swapchain->images_count,
+ cg_core.vk_graphics_pipeline_3d_layout->descriptor_set_view);
+
+ VkDescriptorSetAllocateInfo alloc_info{};
+ alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
+ alloc_info.descriptorPool = self->descriptor_pool;
+ alloc_info.descriptorSetCount = layouts.size();
+ alloc_info.pSetLayouts = layouts.data();
+
+ self->descriptor_sets_3d.resize(layouts.size());
+ if(vkAllocateDescriptorSets(
+ cg_core.vk_device_with_swapchain->device, &alloc_info,
+ self->descriptor_sets_3d.data()) != VK_SUCCESS)
+ throw CommandError{"Failed to create Vulkan descriptor sets for view."};
+}
+
+void
+load_resources_to_descriptor_sets_3d(void *obj)
+{
+ auto self = static_cast<VK::View3D*>(obj);
+
+ for(auto i{0}; i < self->ub_3d.size(); i++)
+ {
+ VkDescriptorBufferInfo view_3d_info{};
+ view_3d_info.buffer = self->ub_3d[i].buffer;
+ view_3d_info.offset = 0;
+ view_3d_info.range = sizeof(VK::UBOView3D);
+
+ std::array<VkWriteDescriptorSet, 1> write_descriptors{};
+ write_descriptors[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ write_descriptors[0].dstSet = self->descriptor_sets_3d[i];
+ write_descriptors[0].dstBinding = 0;
+ write_descriptors[0].dstArrayElement = 0;
+ write_descriptors[0].descriptorCount = 1;
+ write_descriptors[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ write_descriptors[0].pBufferInfo = &view_3d_info;
+ write_descriptors[0].pImageInfo = nullptr;
+ write_descriptors[0].pTexelBufferView = nullptr;
+
+ vkUpdateDescriptorSets(
+ cg_core.vk_device_with_swapchain->device, write_descriptors.size(),
+ write_descriptors.data(), 0, nullptr);
+
+ VK::UBOView3D ubo_view_3d;
+ ubo_view_3d.proj = glm::ortho(
+ 0.0f, self->region.z,
+ 0.0f, self->region.w,
+ 0.0f, 100.0f);
+ self->ub_3d[i].copy_data(&ubo_view_3d);
+ }
+}
+
+const CommandChain loader{
+ {&load_3d_uniform_buffer, &unload_3d_uniform_buffer}
+};
+
+const CommandChain descriptor_sets_loader{
+ {&load_descriptor_sets_3d, nullptr},
+ {&load_resources_to_descriptor_sets_3d, nullptr}
+};
+
+}
+
+namespace VK
+{
+
+View3D::View3D(glm::vec4 region):
+ View2D{region},
+ camera_position{std::make_shared<glm::vec3>(0.0f, 0.0f, 0.0f)},
+ camera_rotation{std::make_shared<glm::vec3>(0.0f, 0.0f, 0.0f)}
+{
+ ::loader.execute(this);
+}
+
+View3D::~View3D()
+{
+ ::loader.revert(this);
+}
+
+void
+View3D::load_descriptor_sets(VkDescriptorPool descriptor_pool)
+{
+ if(this->descriptor_pool != VK_NULL_HANDLE) return;
+
+ auto parent = dynamic_cast<VK::View2D*>(this);
+ this->descriptor_pool = descriptor_pool;
+ View2D::descriptor_sets_loader.execute(parent);
+ ::descriptor_sets_loader.execute(this);
+}
+
+void
+View3D::unload_descriptor_sets()
+{
+ if(this->descriptor_pool == VK_NULL_HANDLE) return;
+
+ auto parent = dynamic_cast<VK::View2D*>(this);
+ this->descriptor_pool = VK_NULL_HANDLE;
+ ::descriptor_sets_loader.revert(this);
+ View2D::descriptor_sets_loader.revert(parent);
+}
+
+}
diff --git a/src/vk/view_3d.hpp b/src/vk/view_3d.hpp
new file mode 100644
index 0000000..ba08957
--- /dev/null
+++ b/src/vk/view_3d.hpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2022 Frederico de Oliveira Linhares
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef CANDY_GEAR_VK_VIEW_3D_H
+#define CANDY_GEAR_VK_VIEW_3D_H 1
+
+#include "view_2d.hpp"
+
+namespace VK
+{
+
+struct View3D: public View2D
+{
+ // FIXME: if this vector get resized, it can cause a segmentation fault!
+ std::vector<UniformBuffer> ub_3d;
+
+ std::vector<VkDescriptorSet> descriptor_sets_3d;
+
+ std::shared_ptr<glm::vec3> camera_position;
+ std::shared_ptr<glm::vec3> camera_rotation;
+
+ View3D(glm::vec4 region);
+ ~View3D();
+
+ void
+ load_descriptor_sets(VkDescriptorPool descriptor_pool);
+
+ void
+ unload_descriptor_sets();
+};
+
+}
+
+#endif /* CANDY_GEAR_VK_VIEW_3D_H */
diff --git a/test/src/main.rb b/test/src/main.rb
index 67ef80c..40a7c79 100644
--- a/test/src/main.rb
+++ b/test/src/main.rb
@@ -37,12 +37,12 @@ def init()
$camera_rotation = CandyGear::Rotation3D.new(0.0, 0.0, 0.0);
color = CandyGear::Vector3D.new(0.12, 0.12, 0.18);
- $view1 = CandyGear::View.new(CandyGear::Vector4D.new(0, 0, 1280, 360));
- $view2 = CandyGear::View.new(CandyGear::Vector4D.new(0, 360, 1280, 360));
+ $view1 = CandyGear::View2D.new(CandyGear::Vector4D.new(0, 0, 1280, 360));
+ $view2 = CandyGear::View3D.new(CandyGear::Vector4D.new(0, 360, 1280, 360));
CandyGear.views = [$view1, $view2];
- $view1.camera_position = $camera_position;
- $view1.camera_rotation = $camera_rotation;
+ $view2.camera_position = $camera_position;
+ $view2.camera_rotation = $camera_rotation;
end
def key_down(key)
@@ -76,7 +76,7 @@ end
def quit() = CandyGear.quit();
def tick()
- $sprite.draw($view2, $sprite_position);
+ $view1.draw($sprite, $sprite_position);
$instances_rotation.rotate(0.0, BOX_ROTATION_SPEED);
$instances.each do |i|
$model.draw(i, $instances_rotation);