| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534 |
- /*
- * Copyright 2016 Dario Manesku. All rights reserved.
- * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
- */
- #include "common.h"
- #include "bgfx_utils.h"
- #include "imgui/imgui.h"
- namespace
- {
- struct DrawMode
- {
- enum
- {
- WireframeShaded,
- Wireframe,
- Shaded,
- };
- };
- struct Camera
- {
- Camera()
- {
- reset();
- }
- void reset()
- {
- m_target.curr[0] = 0.0f;
- m_target.curr[1] = 0.0f;
- m_target.curr[2] = 0.0f;
- m_target.dest[0] = 0.0f;
- m_target.dest[1] = 0.0f;
- m_target.dest[2] = 0.0f;
- m_pos.curr[0] = 0.0f;
- m_pos.curr[1] = 0.0f;
- m_pos.curr[2] = -2.0f;
- m_pos.dest[0] = 0.0f;
- m_pos.dest[1] = 0.0f;
- m_pos.dest[2] = -2.0f;
- m_orbit[0] = 0.0f;
- m_orbit[1] = 0.0f;
- }
- void mtxLookAt(float* _outViewMtx)
- {
- bx::mtxLookAt(_outViewMtx, m_pos.curr, m_target.curr);
- }
- void orbit(float _dx, float _dy)
- {
- m_orbit[0] += _dx;
- m_orbit[1] += _dy;
- }
- void dolly(float _dz)
- {
- const float cnear = 0.01f;
- const float cfar = 10.0f;
- const float toTarget[3] =
- {
- m_target.dest[0] - m_pos.dest[0],
- m_target.dest[1] - m_pos.dest[1],
- m_target.dest[2] - m_pos.dest[2],
- };
- const float toTargetLen = bx::vec3Length(toTarget);
- const float invToTargetLen = 1.0f/(toTargetLen+FLT_MIN);
- const float toTargetNorm[3] =
- {
- toTarget[0]*invToTargetLen,
- toTarget[1]*invToTargetLen,
- toTarget[2]*invToTargetLen,
- };
- float delta = toTargetLen*_dz;
- float newLen = toTargetLen + delta;
- if ( (cnear < newLen || _dz < 0.0f)
- && (newLen < cfar || _dz > 0.0f) )
- {
- m_pos.dest[0] += toTargetNorm[0]*delta;
- m_pos.dest[1] += toTargetNorm[1]*delta;
- m_pos.dest[2] += toTargetNorm[2]*delta;
- }
- }
- void consumeOrbit(float _amount)
- {
- float consume[2];
- consume[0] = m_orbit[0]*_amount;
- consume[1] = m_orbit[1]*_amount;
- m_orbit[0] -= consume[0];
- m_orbit[1] -= consume[1];
- const float toPos[3] =
- {
- m_pos.curr[0] - m_target.curr[0],
- m_pos.curr[1] - m_target.curr[1],
- m_pos.curr[2] - m_target.curr[2],
- };
- const float toPosLen = bx::vec3Length(toPos);
- const float invToPosLen = 1.0f/(toPosLen+FLT_MIN);
- const float toPosNorm[3] =
- {
- toPos[0]*invToPosLen,
- toPos[1]*invToPosLen,
- toPos[2]*invToPosLen,
- };
- float ll[2];
- bx::vec3ToLatLong(&ll[0], &ll[1], toPosNorm);
- ll[0] += consume[0];
- ll[1] -= consume[1];
- ll[1] = bx::fclamp(ll[1], 0.02f, 0.98f);
- float tmp[3];
- bx::vec3FromLatLong(tmp, ll[0], ll[1]);
- float diff[3];
- diff[0] = (tmp[0]-toPosNorm[0])*toPosLen;
- diff[1] = (tmp[1]-toPosNorm[1])*toPosLen;
- diff[2] = (tmp[2]-toPosNorm[2])*toPosLen;
- m_pos.curr[0] += diff[0];
- m_pos.curr[1] += diff[1];
- m_pos.curr[2] += diff[2];
- m_pos.dest[0] += diff[0];
- m_pos.dest[1] += diff[1];
- m_pos.dest[2] += diff[2];
- }
- void update(float _dt)
- {
- const float amount = bx::fmin(_dt/0.12f, 1.0f);
- consumeOrbit(amount);
- m_target.curr[0] = bx::flerp(m_target.curr[0], m_target.dest[0], amount);
- m_target.curr[1] = bx::flerp(m_target.curr[1], m_target.dest[1], amount);
- m_target.curr[2] = bx::flerp(m_target.curr[2], m_target.dest[2], amount);
- m_pos.curr[0] = bx::flerp(m_pos.curr[0], m_pos.dest[0], amount);
- m_pos.curr[1] = bx::flerp(m_pos.curr[1], m_pos.dest[1], amount);
- m_pos.curr[2] = bx::flerp(m_pos.curr[2], m_pos.dest[2], amount);
- }
- struct Interp3f
- {
- float curr[3];
- float dest[3];
- };
- Interp3f m_target;
- Interp3f m_pos;
- float m_orbit[2];
- };
- struct Mouse
- {
- Mouse()
- {
- m_dx = 0.0f;
- m_dy = 0.0f;
- m_prevMx = 0.0f;
- m_prevMx = 0.0f;
- m_scroll = 0;
- m_scrollPrev = 0;
- }
- void update(float _mx, float _my, int32_t _mz, uint32_t _width, uint32_t _height)
- {
- const float widthf = float(int32_t(_width));
- const float heightf = float(int32_t(_height));
- // Delta movement.
- m_dx = float(_mx - m_prevMx)/widthf;
- m_dy = float(_my - m_prevMy)/heightf;
- m_prevMx = _mx;
- m_prevMy = _my;
- // Scroll.
- m_scroll = _mz - m_scrollPrev;
- m_scrollPrev = _mz;
- }
- float m_dx; // Screen space.
- float m_dy;
- float m_prevMx;
- float m_prevMy;
- int32_t m_scroll;
- int32_t m_scrollPrev;
- };
- struct MeshMtx
- {
- MeshMtx()
- {
- m_mesh = NULL;
- }
- void init(const char* _path
- , float _scale = 1.0f
- , float _rotX = 0.0f
- , float _rotY = 0.0f
- , float _rotZ = 0.0f
- , float _transX = 0.0f
- , float _transY = 0.0f
- , float _transZ = 0.0f
- )
- {
- m_mesh = meshLoad(_path);
- bx::mtxSRT(m_mtx
- , _scale
- , _scale
- , _scale
- , _rotX
- , _rotY
- , _rotZ
- , _transX
- , _transY
- , _transZ
- );
- }
- void destroy()
- {
- if (NULL != m_mesh)
- {
- meshUnload(m_mesh);
- }
- }
- Mesh* m_mesh;
- float m_mtx[16];
- };
- struct Uniforms
- {
- enum { NumVec4 = 3 };
- void init()
- {
- m_camPos[0] = 0.0f;
- m_camPos[1] = 1.0f;
- m_camPos[2] = -2.5f;
- m_wfColor[0] = 1.0f;
- m_wfColor[1] = 0.0f;
- m_wfColor[2] = 0.0f;
- m_wfColor[3] = 1.0f;
- m_drawEdges = 0.0f;
- m_wfThickness = 1.5f;
- u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, NumVec4);
- }
- void submit()
- {
- bgfx::setUniform(u_params, m_params, NumVec4);
- }
- void destroy()
- {
- bgfx::destroy(u_params);
- }
- union
- {
- struct
- {
- /*0*/struct { float m_camPos[3], m_unused0; };
- /*1*/struct { float m_wfColor[4]; };
- /*2*/struct { float m_drawEdges, m_wfThickness, m_unused2[2]; };
- };
- float m_params[NumVec4*4];
- };
- bgfx::UniformHandle u_params;
- };
- class ExampleWireframe : public entry::AppI
- {
- public:
- ExampleWireframe(const char* _name, const char* _description)
- : entry::AppI(_name, _description)
- {
- }
- void init(int32_t _argc, const char* const* _argv, uint32_t _width, uint32_t _height) override
- {
- Args args(_argc, _argv);
- m_width = _width;
- m_height = _height;
- m_debug = BGFX_DEBUG_NONE;
- m_reset = 0
- | BGFX_RESET_VSYNC
- | BGFX_RESET_MSAA_X16
- ;
- bgfx::init(args.m_type, args.m_pciId);
- bgfx::reset(m_width, m_height, m_reset);
- // Enable m_debug text.
- bgfx::setDebug(m_debug);
- // Set view 0 clear state.
- bgfx::setViewClear(0
- , BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
- , 0x303030ff
- , 1.0f
- , 0
- );
- m_wfProgram = loadProgram("vs_wf_wireframe", "fs_wf_wireframe");
- m_meshProgram = loadProgram("vs_wf_mesh", "fs_wf_mesh");
- m_uniforms.init();
- m_meshes[0].init("meshes/bunny.bin", 1.0f, 0.0f, bx::kPi, 0.0f, 0.0f, -0.8f, 0.0f);
- m_meshes[1].init("meshes/hollowcube.bin", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
- m_meshes[2].init("meshes/orb.bin", 1.2f, 0.0f, 0.0f, 0.0f, 0.0f, -0.65f, 0.0f);
- // Imgui.
- imguiCreate();
- m_oldWidth = 0;
- m_oldHeight = 0;
- m_oldReset = m_reset;
- m_meshSelection = 1;
- m_drawMode = DrawMode::WireframeShaded;
- }
- virtual int shutdown() override
- {
- // Cleanup.
- imguiDestroy();
- m_meshes[0].destroy();
- m_meshes[1].destroy();
- m_meshes[2].destroy();
- bgfx::destroy(m_wfProgram);
- bgfx::destroy(m_meshProgram);
- m_uniforms.destroy();
- // Shutdown bgfx.
- bgfx::shutdown();
- return 0;
- }
- bool update() override
- {
- if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
- {
- if (m_oldWidth != m_width
- || m_oldHeight != m_height
- || m_oldReset != m_reset)
- {
- // Recreate variable size render targets when resolution changes.
- m_oldWidth = m_width;
- m_oldHeight = m_height;
- m_oldReset = m_reset;
- }
- imguiBeginFrame(m_mouseState.m_mx
- , m_mouseState.m_my
- , (m_mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0)
- | (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0)
- | (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
- , m_mouseState.m_mz
- , uint16_t(m_width)
- , uint16_t(m_height)
- );
- showExampleDialog(this);
- ImGui::SetNextWindowPos(
- ImVec2(m_width - m_width / 5.0f - 10.0f, 10.0f)
- , ImGuiCond_FirstUseEver
- );
- ImGui::SetNextWindowSize(
- ImVec2(m_width / 5.0f, m_height * 0.75f)
- , ImGuiCond_FirstUseEver
- );
- ImGui::Begin("Settings"
- , NULL
- , 0
- );
- ImGui::Separator();
- ImGui::Text("Draw mode:");
- ImGui::RadioButton("Wireframe + Shaded", &m_drawMode, 0);
- ImGui::RadioButton("Wireframe", &m_drawMode, 1);
- ImGui::RadioButton("Shaded", &m_drawMode, 2);
- const bool wfEnabled = (DrawMode::Shaded != m_drawMode);
- if ( wfEnabled )
- {
- ImGui::Separator();
- ImGui::ColorWheel("Color", m_uniforms.m_wfColor, 0.6f);
- ImGui::SliderFloat("Thickness", &m_uniforms.m_wfThickness, 0.6f, 2.2f);
- }
- ImGui::Separator();
- ImGui::Text("Mesh:");
- {
- bool meshChanged = false;
- meshChanged |= ImGui::RadioButton("Bunny", &m_meshSelection, 0);
- meshChanged |= ImGui::RadioButton("Hollowcubes", &m_meshSelection, 1);
- meshChanged |= ImGui::RadioButton("Orb", &m_meshSelection, 2);
- if (meshChanged)
- {
- m_camera.reset();
- }
- }
- ImGui::End();
- imguiEndFrame();
- // This dummy draw call is here to make sure that view 0 is cleared
- // if no other draw calls are submitted to view 0.
- bgfx::touch(0);
- int64_t now = bx::getHPCounter();
- static int64_t last = now;
- const int64_t frameTime = now - last;
- last = now;
- const double freq = double(bx::getHPFrequency() );
- const float deltaTimeSec = float(double(frameTime)/freq);
- // Setup view.
- bgfx::setViewRect(0, 0, 0, bgfx::BackbufferRatio::Equal);
- bgfx::setViewClear(0, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH, 0x303030ff, 1.0f, 0);
- const bool mouseOverGui = ImGui::MouseOverArea();
- m_mouse.update(float(m_mouseState.m_mx), float(m_mouseState.m_my), m_mouseState.m_mz, m_width, m_height);
- if (!mouseOverGui)
- {
- if (m_mouseState.m_buttons[entry::MouseButton::Left])
- {
- m_camera.orbit(m_mouse.m_dx, m_mouse.m_dy);
- }
- else if (m_mouseState.m_buttons[entry::MouseButton::Right])
- {
- m_camera.dolly(m_mouse.m_dx + m_mouse.m_dy);
- }
- else if (0 != m_mouse.m_scroll)
- {
- m_camera.dolly(float(m_mouse.m_scroll)*0.1f);
- }
- }
- float view[16];
- float proj[16];
- m_camera.update(deltaTimeSec);
- bx::memCopy(m_uniforms.m_camPos, m_camera.m_pos.curr, 3*sizeof(float));
- m_camera.mtxLookAt(view);
- bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, bgfx::getCaps()->homogeneousDepth);
- bgfx::setViewTransform(0, view, proj);
- m_uniforms.m_drawEdges = (DrawMode::WireframeShaded == m_drawMode) ? 1.0f : 0.0f;
- m_uniforms.submit();
- if (DrawMode::Wireframe == m_drawMode)
- {
- uint64_t state = 0
- | BGFX_STATE_RGB_WRITE
- | BGFX_STATE_ALPHA_WRITE
- | BGFX_STATE_DEPTH_WRITE
- | BGFX_STATE_CULL_CCW
- | BGFX_STATE_MSAA
- | BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
- ;
- meshSubmit(m_meshes[m_meshSelection].m_mesh, 0, m_wfProgram, m_meshes[m_meshSelection].m_mtx, state);
- }
- else
- {
- uint64_t state = 0
- | BGFX_STATE_RGB_WRITE
- | BGFX_STATE_ALPHA_WRITE
- | BGFX_STATE_DEPTH_TEST_LESS
- | BGFX_STATE_DEPTH_WRITE
- | BGFX_STATE_CULL_CCW
- | BGFX_STATE_MSAA
- ;
- meshSubmit(m_meshes[m_meshSelection].m_mesh, 0, m_meshProgram, m_meshes[m_meshSelection].m_mtx, state);
- }
- // Advance to next frame. Rendering thread will be kicked to
- // process submitted rendering primitives.
- bgfx::frame();
- return true;
- }
- return false;
- }
- entry::MouseState m_mouseState;
- bgfx::ProgramHandle m_wfProgram;
- bgfx::ProgramHandle m_meshProgram;
- uint32_t m_width;
- uint32_t m_height;
- uint32_t m_debug;
- uint32_t m_reset;
- uint32_t m_oldWidth;
- uint32_t m_oldHeight;
- uint32_t m_oldReset;
- Camera m_camera;
- Mouse m_mouse;
- Uniforms m_uniforms;
- MeshMtx m_meshes[3];
- int32_t m_meshSelection;
- int32_t m_drawMode; // Holds data for 'DrawMode'.
- };
- } // namespace
- ENTRY_IMPLEMENT_MAIN(ExampleWireframe, "28-wirefame", "Drawing wireframe mesh.");
|