Model preview - closes #775

This commit is contained in:
Mikulas Florek 2016-05-12 07:48:51 +02:00
parent 1b4577970b
commit 1102f8a007
3 changed files with 147 additions and 12 deletions

View file

@ -3,6 +3,7 @@
#include "engine/fs/disk_file_device.h"
#include "engine/fs/file_system.h"
#include "engine/fs/os_file.h"
#include "engine/input_system.h"
#include "engine/json_serializer.h"
#include "engine/log.h"
#include "engine/lua_wrapper.h"
@ -23,6 +24,7 @@
#include "game_view.h"
#include "editor/render_interface.h"
#include "import_asset_dialog.h"
#include "renderer/frame_buffer.h"
#include "renderer/material.h"
#include "renderer/model.h"
#include "renderer/model_manager.h"
@ -334,6 +336,7 @@ struct ModelPlugin : public AssetBrowser::IPlugin
Entity m_entity;
WorldEditor& m_editor;
Entity getEntity() const { return m_entity; }
explicit InsertMeshCommand(WorldEditor& editor)
: m_editor(editor)
@ -435,7 +438,22 @@ struct ModelPlugin : public AssetBrowser::IPlugin
explicit ModelPlugin(StudioApp& app)
: m_app(app)
{
m_camera_cmp = INVALID_COMPONENT;
m_camera_entity = INVALID_ENTITY;
m_mesh = INVALID_COMPONENT;
m_pipeline = nullptr;
m_universe = nullptr;
m_app.getWorldEditor()->registerEditorCommandCreator("insert_mesh", createInsertMeshCommand);
createPreviewUniverse();
}
~ModelPlugin()
{
auto& engine = m_app.getWorldEditor()->getEngine();
engine.destroyUniverse(*m_universe);
Pipeline::destroy(m_pipeline);
}
@ -447,18 +465,120 @@ struct ModelPlugin : public AssetBrowser::IPlugin
static void insertInScene(WorldEditor& editor, Model* model)
{
auto* command = LUMIX_NEW(editor.getAllocator(), InsertMeshCommand)(
editor, editor.getCameraRaycastHit(), model->getPath());
auto* command =
LUMIX_NEW(editor.getAllocator(), InsertMeshCommand)(editor, editor.getCameraRaycastHit(), model->getPath());
editor.executeCommand(command);
}
void createPreviewUniverse()
{
auto& engine = m_app.getWorldEditor()->getEngine();
m_universe = &engine.createUniverse();
auto* renderer = static_cast<Renderer*>(engine.getPluginManager().getPlugin("renderer"));
m_pipeline = Pipeline::create(*renderer, Path("pipelines/main.lua"), engine.getAllocator());
m_pipeline->load();
auto mesh_entity = m_universe->createEntity({ 0, 0, 0 }, { 0, 0, 0, 1 });
auto* render_scene = static_cast<RenderScene*>(m_universe->getScene(crc32("renderer")));
m_mesh = render_scene->createComponent(crc32("renderable"), mesh_entity);
auto light_entity = m_universe->createEntity({ 0, 0, 0 }, { 0, 0, 0, 1 });
auto light_cmp = render_scene->createComponent(crc32("global_light"), light_entity);
render_scene->setGlobalLightIntensity(light_cmp, 0);
render_scene->setLightAmbientIntensity(light_cmp, 1);
m_camera_entity = m_universe->createEntity({ 0, 0, 0 }, { 0, 0, 0, 1 });
m_camera_cmp = render_scene->createComponent(crc32("camera"), m_camera_entity);
render_scene->setCameraSlot(m_camera_cmp, "editor");
m_pipeline->setScene(render_scene);
}
void showPreview(Model& model)
{
auto& engine = m_app.getWorldEditor()->getEngine();
auto* render_scene = static_cast<RenderScene*>(m_universe->getScene(crc32("renderer")));
if (!render_scene) return;
if (!model.isReady()) return;
if (render_scene->getRenderableModel(m_mesh) != &model)
{
render_scene->setRenderablePath(m_mesh, model.getPath());
AABB aabb = model.getAABB();
m_universe->setRotation(m_camera_entity, {0, 0, 0, 1});
m_universe->setPosition(m_camera_entity,
{(aabb.max.x + aabb.min.x) * 0.5f,
(aabb.max.y + aabb.min.y) * 0.5f,
aabb.max.z + aabb.max.x - aabb.min.x});
}
ImVec2 image_size(ImGui::GetContentRegionAvailWidth(), ImGui::GetContentRegionAvailWidth());
m_pipeline->setViewport(0, 0, (int)image_size.x, (int)image_size.y);
m_pipeline->render();
auto content_min = ImGui::GetCursorScreenPos();
ImVec2 content_max(content_min.x + image_size.x, content_min.y + image_size.y);
ImGui::Image(&m_pipeline->getFramebuffer("default")->getRenderbuffer(0).m_handle, image_size);
bool mouse_down = ImGui::IsMouseDown(0) || ImGui::IsMouseDown(1);
if (m_is_mouse_captured && !mouse_down)
{
m_is_mouse_captured = false;
PlatformInterface::showCursor(true);
PlatformInterface::unclipCursor();
}
if (ImGui::IsItemHovered() && mouse_down)
{
auto& input = engine.getInputSystem();
auto delta = Lumix::Vec2(input.getMouseXMove(), input.getMouseYMove());
if (!m_is_mouse_captured)
{
m_is_mouse_captured = true;
PlatformInterface::showCursor(false);
}
PlatformInterface::clipCursor(content_min.x, content_min.y, content_max.x, content_max.y);
if (delta.x != 0 || delta.y != 0)
{
const Vec2 MOUSE_SENSITIVITY(50, 50);
Vec3 pos = m_universe->getPosition(m_camera_entity);
Quat rot = m_universe->getRotation(m_camera_entity);
Quat old_rot = rot;
float yaw = -Math::signum(delta.x) * (Math::pow(Math::abs((float)delta.x / MOUSE_SENSITIVITY.x), 1.2f));
Quat yaw_rot(Vec3(0, 1, 0), yaw);
rot = rot * yaw_rot;
rot.normalize();
Vec3 pitch_axis = rot * Vec3(1, 0, 0);
float pitch =
-Math::signum(delta.y) * (Math::pow(Math::abs((float)delta.y / MOUSE_SENSITIVITY.y), 1.2f));
Quat pitch_rot(pitch_axis, pitch);
rot = rot * pitch_rot;
rot.normalize();
Vec3 dir = rot * Vec3(0, 0, 1);
Vec3 origin = (model.getAABB().max + model.getAABB().min) * 0.5f;
float dist = (origin - pos).length();
pos = origin + dir * dist;
m_universe->setRotation(m_camera_entity, rot);
m_universe->setPosition(m_camera_entity, pos);
}
}
}
bool onGUI(Resource* resource, uint32 type) override
{
if (type != MODEL_HASH) return false;
auto* model = static_cast<Model*>(resource);
if (ImGui::Button("Insert in scene"))
{
insertInScene(*m_app.getWorldEditor(), model);
@ -535,6 +655,9 @@ struct ModelPlugin : public AssetBrowser::IPlugin
ImGui::TreePop();
}
}
showPreview(*model);
return true;
}
@ -564,6 +687,12 @@ struct ModelPlugin : public AssetBrowser::IPlugin
StudioApp& m_app;
Universe* m_universe;
Pipeline* m_pipeline;
ComponentIndex m_mesh;
Entity m_camera_entity;
ComponentIndex m_camera_cmp;
bool m_is_mouse_captured;
};
@ -1513,12 +1642,12 @@ LUMIX_STUDIO_ENTRY(renderer)
{
auto& allocator = app.getWorldEditor()->getAllocator();
auto* material_plugin = LUMIX_NEW(allocator, MaterialPlugin)(app);
app.getAssetBrowser()->addPlugin(*material_plugin);
auto* model_plugin = LUMIX_NEW(allocator, ModelPlugin)(app);
app.getAssetBrowser()->addPlugin(*model_plugin);
auto* material_plugin = LUMIX_NEW(allocator, MaterialPlugin)(app);
app.getAssetBrowser()->addPlugin(*material_plugin);
auto* texture_plugin = LUMIX_NEW(allocator, TexturePlugin)(app);
app.getAssetBrowser()->addPlugin(*texture_plugin);

View file

@ -226,8 +226,7 @@ void SceneView::onGUI()
}
if(m_is_mouse_captured)
{
PlatformInterface::clipCursor(
content_min.x, content_min.y, content_max.x, content_max.y);
PlatformInterface::clipCursor(content_min.x, content_min.y, content_max.x, content_max.y);
for (int i = 0; i < 3; ++i)
{
auto rel_mp = ImGui::GetMousePos();

View file

@ -3476,19 +3476,19 @@ public:
}
ModelLoadedCallback* getModelLoadedCallback(Model* model)
int getModelLoadedCallback(Model* model)
{
for (int i = 0; i < m_model_loaded_callbacks.size(); ++i)
{
if (m_model_loaded_callbacks[i]->m_model == model)
{
return m_model_loaded_callbacks[i];
return i;
}
}
ModelLoadedCallback* new_callback =
LUMIX_NEW(m_allocator, ModelLoadedCallback)(*this, model);
m_model_loaded_callbacks.push(new_callback);
return new_callback;
return m_model_loaded_callbacks.size() - 1;
}
@ -3576,8 +3576,15 @@ public:
auto& rm = old_model->getResourceManager();
auto* material_manager = static_cast<MaterialManager*>(rm.get(ResourceManager::MATERIAL));
freeCustomMeshes(m_renderables[component], material_manager);
ModelLoadedCallback* callback = getModelLoadedCallback(old_model);
int callback_idx = getModelLoadedCallback(old_model);
ModelLoadedCallback* callback = m_model_loaded_callbacks[callback_idx];
--callback->m_ref_count;
if (callback->m_ref_count == 0)
{
LUMIX_DELETE(m_allocator, callback);
m_model_loaded_callbacks.eraseFast(callback_idx);
}
if (old_model->isReady())
{
m_culling_system->removeStatic(component);
@ -3591,7 +3598,7 @@ public:
m_renderables[component].pose = nullptr;
if (model)
{
ModelLoadedCallback* callback = getModelLoadedCallback(model);
ModelLoadedCallback* callback = m_model_loaded_callbacks[getModelLoadedCallback(model)];
++callback->m_ref_count;
if (model->isReady())