From d93b3f6aa81a5cfb05595ac1873af16e65f56792 Mon Sep 17 00:00:00 2001 From: Nick Fisher Date: Mon, 25 Sep 2023 21:52:28 +1000 Subject: [PATCH] windows working (SLOW) with pixel buffer copy --- windows/CMakeLists.txt | 22 +- windows/polyvox_filament_plugin.cpp | 851 +++++++++++++++++++++++----- windows/polyvox_filament_plugin.h | 153 ++++- 3 files changed, 857 insertions(+), 169 deletions(-) diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index b4e26927..ae7887e4 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -26,7 +26,7 @@ add_library(${PLUGIN_NAME} SHARED "polyvox_filament_plugin_c_api.cpp" ${PLUGIN_SOURCES} "${CMAKE_CURRENT_SOURCE_DIR}/../ios/include/material/image.c" - "${CMAKE_CURRENT_SOURCE_DIR}/../ios/include/material/unlit_opaque.c" + # "${CMAKE_CURRENT_SOURCE_DIR}/../ios/include/material/uberarchive.c" ) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) @@ -40,9 +40,6 @@ target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) target_include_directories(${PLUGIN_NAME} INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/include") -add_library(glfw SHARED IMPORTED) -set_property(TARGET glfw PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/glfw-3.3.8.bin.WIN64/lib-vc2022/glfw3.lib") - add_library(bluegl SHARED IMPORTED) set_property(TARGET bluegl PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/bluegl.lib") add_library(geometry SHARED IMPORTED) @@ -61,6 +58,8 @@ add_library(utils SHARED IMPORTED) set_property(TARGET utils PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/utils.lib") add_library(filabridge SHARED IMPORTED) set_property(TARGET filabridge PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/filabridge.lib") +add_library(gltfio SHARED IMPORTED) +set_property(TARGET gltfio PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/gltfio.lib") add_library(gltfio_core SHARED IMPORTED) set_property(TARGET gltfio_core PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/gltfio_core.lib") add_library(filament-iblprefilter SHARED IMPORTED) @@ -91,8 +90,8 @@ add_library(uberzlib SHARED IMPORTED) set_property(TARGET uberzlib PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/uberzlib.lib") add_library(smol-v SHARED IMPORTED) set_property(TARGET smol-v PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/smol-v.lib") -add_library(uberarchive SHARED IMPORTED) -set_property(TARGET uberarchive PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/uberarchive.lib") +# add_library(uberarchive SHARED IMPORTED) +# set_property(TARGET uberarchive PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/uberarchive.lib") add_library(meshoptimizer SHARED IMPORTED) set_property(TARGET meshoptimizer PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/meshoptimizer.lib") add_library(basis_transcoder SHARED IMPORTED) @@ -104,7 +103,6 @@ set_property(TARGET zstd PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/l add_library(png SHARED IMPORTED) set_property(TARGET png PROPERTY IMPORTED_IMPLIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/png.lib") -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/lib/glfw-3.3.8.bin.WIN64/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../ios/include) get_cmake_property(_variableNames VARIABLES) @@ -116,15 +114,14 @@ endforeach() target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin -glfw bluegl opengl32 + gltfio gltfio_core filament backend geometry - filameshio - filament_viewer +# filameshio filamat filabridge filament-iblprefilter @@ -137,11 +134,9 @@ opengl32 imageio utils stb - bluevk - vkshaders uberzlib smol-v - uberarchive +# uberarchive meshoptimizer geometry basis_transcoder @@ -156,4 +151,5 @@ opengl32 set(polyvox_filament_bundled_libraries "" PARENT_SCOPE + windows/lib/*.lib ) diff --git a/windows/polyvox_filament_plugin.cpp b/windows/polyvox_filament_plugin.cpp index 6916430e..9c5ab30b 100644 --- a/windows/polyvox_filament_plugin.cpp +++ b/windows/polyvox_filament_plugin.cpp @@ -10,13 +10,22 @@ #include #include +#include +#include +#include +#include +#include +#include #include +#include #include #include +#include +#include -#include #include "GL/GL.h" #include "GL/GLu.h" +#include "GL/wglext.h" #include "PolyvoxFilamentApi.h" @@ -31,9 +40,7 @@ void PolyvoxFilamentPlugin::RegisterWithRegistrar( &flutter::StandardMethodCodec::GetInstance()); auto plugin = std::make_unique( - registrar->texture_registrar(), - registrar - ); + registrar->texture_registrar(), registrar); channel->SetMethodCallHandler( [plugin_pointer = plugin.get()](const auto &call, auto result) { @@ -44,85 +51,212 @@ void PolyvoxFilamentPlugin::RegisterWithRegistrar( } PolyvoxFilamentPlugin::PolyvoxFilamentPlugin( - flutter::TextureRegistrar* textureRegistrar, - flutter::PluginRegistrarWindows *pluginRegistrar) : _textureRegistrar(textureRegistrar), _pluginRegistrar(pluginRegistrar) { - -} + flutter::TextureRegistrar *textureRegistrar, + flutter::PluginRegistrarWindows *pluginRegistrar) + : _textureRegistrar(textureRegistrar), _pluginRegistrar(pluginRegistrar) {} PolyvoxFilamentPlugin::~PolyvoxFilamentPlugin() {} +ResourceBuffer PolyvoxFilamentPlugin::loadResource(const char *name) { + TCHAR pBuf[256]; + size_t len = sizeof(pBuf); + int bytes = GetModuleFileName(NULL, pBuf, len); + std::wstring_convert> converter; + std::wstring assetPath = converter.from_bytes(name); -static ResourceBuffer _loadResource(const char* name) { - auto rb = ResourceBuffer(nullptr, 0, 0); + std::wstring exePathBuf(pBuf); + std::filesystem::path exePath(exePathBuf); + auto exeDir = exePath.remove_filename(); + std::filesystem::path p(exeDir.wstring() + L"data/flutter_assets/" + + assetPath); + std::wcout << "Loading from " << p << std::endl; + std::streampos length; + std::ifstream is(p.c_str(), std::ios::binary); + if (!is) { + std::cout << "Failed to find resource at file path " << p << std::endl; + return ResourceBuffer(nullptr, 0, -1); + } + is.seekg(0, std::ios::end); + length = is.tellg(); + char *buffer; + buffer = new char[length]; + is.seekg(0, std::ios::beg); + is.read(buffer, length); + is.close(); + auto id = _resources.size(); + auto rb = ResourceBuffer(buffer, length, id); + _resources.emplace(id, rb); return rb; } -static void _freeResource(ResourceBuffer rbuf) { - +void PolyvoxFilamentPlugin::freeResource(ResourceBuffer rbuf) { + free((void *)rbuf.data); +} + +static ResourceBuffer _loadResource(const char *path, void *const plugin) { + return ((PolyvoxFilamentPlugin *)plugin)->loadResource(path); +} + +static void _freeResource(ResourceBuffer rbf, void *const plugin) { + ((PolyvoxFilamentPlugin *)plugin)->freeResource(rbf); } void PolyvoxFilamentPlugin::CreateFilamentViewer( - const flutter::MethodCall &methodCall, - std::unique_ptr> result) { - auto window = glfwGetCurrentContext(); - const ResourceLoaderWrapper* const resourceLoader = new ResourceLoaderWrapper(_loadResource, _freeResource); - _viewer = (void*) create_filament_viewer(window, resourceLoader); - create_swap_chain(_viewer, window, 1024, 768); - // result->Success(flutter::EncodableValue((long)_viewer)); - result->Success(flutter::EncodableValue(0)); + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + const ResourceLoaderWrapper *const resourceLoader = + new ResourceLoaderWrapper(_loadResource, _freeResource, this); + + wglMakeCurrent(NULL, NULL); + + _viewer = (void *)create_filament_viewer(_context, resourceLoader); + + std::cout << "Created filament viewer " << std::endl; + + // auto hwnd = _pluginRegistrar->GetView()->GetNativeWindow(); + + create_swap_chain(_viewer, nullptr, 1024, 768); + + // create_render_target(_viewer, _glTextureId, 1024, 768); + + // Update the texture @ 10 Hz + // Setting this to 60 Hz might cause epileptic shocks :D + _frameInterval = std::chrono::milliseconds(1000 / 60); + // std::thread([&]() { + // while (true) { + // if (_rendering) { + // auto callback = [](void *buf, size_t size, void *data) { + // auto plugin = (PolyvoxFilamentPlugin*)data; + // plugin->_textureRegistrar->MarkTextureFrameAvailable( + // plugin->_flutterTextureId); + // }; + // render(_viewer, 0, _pixelData.get(), callback, this); + // } + // std::this_thread::sleep_for(std::chrono::milliseconds(_frameInterval)); + // } + // }).detach(); + + result->Success(flutter::EncodableValue((int64_t)_viewer)); } void PolyvoxFilamentPlugin::Render( - const flutter::MethodCall &methodCall, - std::unique_ptr> result) { - render(_viewer, 0); - _textureRegistrar->MarkTextureFrameAvailable(_flutterTextureId); - result->Success(flutter::EncodableValue(true)); + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + auto callback = [](void *buf, size_t size, void *data) { + auto plugin = (PolyvoxFilamentPlugin *)data; + plugin->_textureRegistrar->MarkTextureFrameAvailable( + plugin->_flutterTextureId); + }; + render(_viewer, 0, _pixelData.get(), callback, this); + result->Success(flutter::EncodableValue(true)); +} + +void PolyvoxFilamentPlugin::SetRendering( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + _rendering = *(std::get_if(methodCall.arguments())); } void PolyvoxFilamentPlugin::CreateTexture( - const flutter::MethodCall &methodCall, - std::unique_ptr> result) { - - // HWND m_hWnd = _pluginRegistrar->GetView()->GetNativeWindow(); - glfwInit(); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - - glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { - GLFWwindow* window = glfwCreateWindow(1024, 768, "", nullptr, nullptr); - if (!window) { - std::cout << "Failed to create GLFW window" << std::endl; - glfwTerminate(); - return; + HWND hwnd = _pluginRegistrar->GetView() + ->GetNativeWindow(); // CreateWindowA("STATIC", "dummy", 0, 0, + // 0, 1, 1, NULL, NULL, NULL, NULL); + + HDC whdc = GetDC(hwnd); + if (whdc == NULL) { + result->Error("ERROR", "No device context for temporary window", nullptr); + return; } - glfwMakeContextCurrent(window); + PIXELFORMATDESCRIPTOR pfd = { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags + PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. + 32, // Colordepth of the framebuffer. + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 24, // Number of bits for the depthbuffer + 0, // Number of bits for the stencilbuffer + 0, // Number of Aux buffers in the framebuffer. + PFD_MAIN_PLANE, + 0, + 0, + 0, + 0}; - glClearColor(0.1f, 0.2f, 0.3f, 1.0f); - glClear(GL_COLOR_BUFFER_BIT); + int pixelFormat = ChoosePixelFormat(whdc, &pfd); + SetPixelFormat(whdc, pixelFormat, &pfd); - auto data = new uint8_t[1024*768*4]; - glReadPixels(0,0, 1024, 768, GL_RGBA, GL_UNSIGNED_BYTE, data); - _pixelData.reset(data); + // We need a tmp context to retrieve and call wglCreateContextAttribsARB. + HGLRC tempContext = wglCreateContext(whdc); + if (!wglMakeCurrent(whdc, tempContext)) { + result->Error("ERROR", "Failed to acquire temporary context", nullptr); + return; + } - GLuint glTextureId = 0; + PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr; - auto textureData = new uint8_t[1024*768*4]; - for(int y = 0; y < 768; y++) { - for(int x=0; x < 1024; x++) { - textureData[y*768 + (x*4)] = 0; - textureData[y*768 + (x*4+1)] = 255; - textureData[y*768 + (x*4+2)] = 0; - textureData[y*768 + (x*4+3)] = 255; + wglCreateContextAttribs = + (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress( + "wglCreateContextAttribsARB"); + + if (!wglCreateContextAttribs) { + result->Error("ERROR", "Failed to resolve wglCreateContextAttribsARB", + nullptr); + return; + } + + for (int minor = 5; minor >= 1; minor--) { + std::vector mAttribs = {WGL_CONTEXT_MAJOR_VERSION_ARB, 4, + WGL_CONTEXT_MINOR_VERSION_ARB, minor, 0}; + _context = wglCreateContextAttribs(whdc, nullptr, mAttribs.data()); + if (_context) { + break; } } - glGenTextures(1, &glTextureId); + wglMakeCurrent(NULL, NULL); + wglDeleteContext(tempContext); - glBindTexture(GL_TEXTURE_2D, glTextureId); + hwnd = _pluginRegistrar->GetView()->GetNativeWindow(); + whdc = GetDC(hwnd); + if (whdc == NULL) { + result->Error("ERROR", "No device context for actual window", nullptr); + return; + } + + if (!_context || !wglMakeCurrent(whdc, _context)) { + result->Error("ERROR", "Failed to create OpenGL context."); + return; + } + + _pixelData.reset(new uint8_t[1024 * 768 * 4]); + + glGenTextures(1, &_glTextureId); + + GLenum err = glGetError(); + + if (err != GL_NO_ERROR) { + result->Error("ERROR", "Failed to generate texture, GL error was %d", err); + return; + } + + glBindTexture(GL_TEXTURE_2D, _glTextureId); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -130,46 +264,467 @@ void PolyvoxFilamentPlugin::CreateTexture( glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1024, 768, 0, GL_RGBA, - GL_UNSIGNED_BYTE, textureData); - + GL_UNSIGNED_BYTE, 0); + _pixelBuffer = std::make_unique(); _pixelBuffer->buffer = _pixelData.get(); _pixelBuffer->width = 1024; _pixelBuffer->height = 768; - _texture = std::make_unique(flutter::PixelBufferTexture( - [=](size_t width, size_t height) -> const FlutterDesktopPixelBuffer* { - std::cout << "Copying pixel buffer for " << width << "x" << height << std::endl; - uint8_t* data = _pixelData.get(); - glReadPixels(0,0, (GLsizei)width, (GLsizei)height, GL_RGBA, GL_UNSIGNED_BYTE, data); - return _pixelBuffer.get(); - })); - - std::cout << "Registering texture" << std::endl; + _texture = + std::make_unique(flutter::PixelBufferTexture( + [=](size_t width, + size_t height) -> const FlutterDesktopPixelBuffer * { + // if(!_context || !wglMakeCurrent(whdc, _context)) { + // std::cout << "Failed to switch OpenGL context." << std::endl; + // } else { + // uint8_t* data = new uint8_t[1024*768*4]; + // auto buf = _pixelData.get(); + // for(int y = 0; y < 768; y++) { + // for(int x=0; x < 1024; x++) { + // data[y*768 + (x*4)] = uint8_t(buf[y*768 + (x*4)] * 255); + // data[y*768 + (x*4+1)] = uint8_t(buf[y*768 + (x*4)] * 255); + // data[y*768 + (x*4+2)] = uint8_t(buf[y*768 + (x*4)] * 255); + // data[y*768 + (x*4+3)] = 255; + // } + // } + // glClearColor(0.1f, 0.2f, 0.3f, 1.0f); + // glClear(GL_COLOR_BUFFER_BIT); + // glReadPixels(0,0, (GLsizei)1024, (GLsizei)768, GL_RGBA, + // GL_UNSIGNED_BYTE, data); + // _pixelData.reset(data); + _pixelBuffer->buffer = _pixelData.get(); + // wglMakeCurrent(NULL, NULL); + // } + _pixelBuffer->buffer = _pixelData.get(); + + return _pixelBuffer.get(); + })); _flutterTextureId = _textureRegistrar->RegisterTexture(_texture.get()); - _textureRegistrar->MarkTextureFrameAvailable(_flutterTextureId); - std::cout << "Registered " << _flutterTextureId << std::endl; - + std::cout << "Registered flutter texture " << _flutterTextureId << std::endl; result->Success(flutter::EncodableValue(_flutterTextureId)); } +void PolyvoxFilamentPlugin::SetBackgroundImage( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + const auto *args = + std::get_if(methodCall.arguments()); + const auto path = std::get_if(&(args->at(0))); + const auto fillHeight = std::get_if(&(args->at(1))); + set_background_image(_viewer, path->c_str(), *fillHeight); + result->Success(flutter::EncodableValue(true)); +} + +void PolyvoxFilamentPlugin::SetBackgroundColor( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + const auto *args = + std::get_if(methodCall.arguments()); + const auto r = std::get_if(&(args->at(0))); + const auto g = std::get_if(&(args->at(1))); + const auto b = std::get_if(&(args->at(2))); + const auto a = std::get_if(&(args->at(3))); + set_background_color(_viewer, static_cast(*r), static_cast(*g), + static_cast(*b), static_cast(*a)); + result->Success(flutter::EncodableValue(true)); +} + +void PolyvoxFilamentPlugin::GetAssetManager( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + auto assetManager = get_asset_manager(_viewer); + result->Success(flutter::EncodableValue((int64_t)assetManager)); +} + +void PolyvoxFilamentPlugin::UpdateViewportAndCameraProjection( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + const auto *args = + std::get_if(methodCall.arguments()); + + const auto width = std::get_if(&(args->at(0))); + const auto height = std::get_if(&(args->at(1))); + const auto scaleFactor = std::get_if(&(args->at(2))); + + update_viewport_and_camera_projection(_viewer, (uint32_t)*width, + (uint32_t)*height, + static_cast(*scaleFactor)); + result->Success(flutter::EncodableValue(true)); +} + +void PolyvoxFilamentPlugin::LoadSkybox( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + const auto *args = std::get_if(methodCall.arguments()); + load_skybox(_viewer, (*args).c_str()); + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::RemoveIbl( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + remove_ibl(_viewer); + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::LoadIbl( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + const auto *args = + std::get_if(methodCall.arguments()); + const auto path = std::get_if(&(args->at(0))); + const auto intensity = std::get_if(&(args->at(1))); + load_ibl(_viewer, (*path).c_str(), static_cast(*intensity)); + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::RemoveSkybox( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + remove_skybox(_viewer); + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::AddLight( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + const auto *args = + std::get_if(methodCall.arguments()); + const auto type = *std::get_if(&(args->at(0))); + const auto color = *std::get_if(&(args->at(1))); + const auto intensity = *std::get_if(&(args->at(2))); + const auto posX = *std::get_if(&(args->at(3))); + const auto posY = *std::get_if(&(args->at(4))); + const auto posZ = *std::get_if(&(args->at(5))); + const auto dirX = *std::get_if(&(args->at(6))); + const auto dirY = *std::get_if(&(args->at(7))); + const auto dirZ = *std::get_if(&(args->at(8))); + const auto shadows = *std::get_if(&(args->at(9))); + auto entityId = add_light(_viewer, type, color, intensity, posX, posY, posZ, + dirX, dirY, dirZ, shadows); + result->Success(flutter::EncodableValue(entityId)); +} + +void PolyvoxFilamentPlugin::LoadGlb( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + + const auto assetManager = *std::get_if(&(args->at(0))); + const auto path = *std::get_if(&(args->at(1))); + const auto unlit = *std::get_if(&(args->at(2))); + auto entityId = load_glb((void *)assetManager, path.c_str(), unlit); + result->Success(flutter::EncodableValue(entityId)); +} + +void PolyvoxFilamentPlugin::GetAnimationNames( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + + const auto assetManager = *std::get_if(&(args->at(0))); + const auto asset = *std::get_if(&(args->at(1))); + + std::vector names; + + auto numNames = get_animation_count((void *)assetManager, asset); + + for (int i = 0; i < numNames; i++) { + char out[255]; + get_animation_name((void *)assetManager, asset, out, i); + names.push_back(flutter::EncodableValue(out)); + } + + result->Success(names); +} + +void PolyvoxFilamentPlugin::RemoveAsset( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + const auto asset = *std::get_if(&(args->at(1))); + remove_asset(_viewer, asset); + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::TransformToUnitCube( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + + const auto assetManager = *std::get_if(&(args->at(0))); + const auto asset = *std::get_if(&(args->at(1))); + transform_to_unit_cube((void *)assetManager, asset); + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::RotateStart( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + + const auto x = *std::get_if(&(args->at(0))); + const auto y = *std::get_if(&(args->at(1))); + + grab_begin(_viewer, static_cast(x), static_cast(y), false); + + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::RotateEnd( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + grab_end(_viewer); + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::RotateUpdate( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + const auto *args = + std::get_if(methodCall.arguments()); + const auto x = *std::get_if(&(args->at(0))); + const auto y = *std::get_if(&(args->at(1))); + grab_update(_viewer, static_cast(x), static_cast(y)); + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::PanStart( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + + const auto x = *std::get_if(&(args->at(0))); + const auto y = *std::get_if(&(args->at(1))); + + grab_begin(_viewer, static_cast(x), static_cast(y), true); + + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::PanUpdate( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + + const auto x = *std::get_if(&(args->at(0))); + const auto y = *std::get_if(&(args->at(1))); + + grab_update(_viewer, static_cast(x), static_cast(y)); + + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::PanEnd( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + grab_end(_viewer); + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::SetPosition( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + const auto assetManager = *std::get_if(&(args->at(0))); + const auto asset = *std::get_if(&(args->at(1))); + const auto x = *std::get_if(&(args->at(2))); + const auto y = *std::get_if(&(args->at(3))); + const auto z = *std::get_if(&(args->at(4))); + + set_position((void *)assetManager, asset, static_cast(x), + static_cast(y), static_cast(z)); + + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::SetRotation( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + const auto assetManager = *std::get_if(&(args->at(0))); + const auto asset = *std::get_if(&(args->at(1))); + const auto rads = *std::get_if(&(args->at(2))); + const auto x = *std::get_if(&(args->at(3))); + const auto y = *std::get_if(&(args->at(4))); + const auto z = *std::get_if(&(args->at(5))); + + set_rotation((void *)assetManager, asset, static_cast(rads), + static_cast(x), static_cast(y), + static_cast(z)); + + result->Success(flutter::EncodableValue("OK")); +} + +void PolyvoxFilamentPlugin::GrabBegin( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + + const auto x = static_cast(*std::get_if(&(args->at(0)))); + const auto y = static_cast(*std::get_if(&(args->at(1)))); + auto pan = std::get_if(&(args->at(2))); + + grab_begin(_viewer, x, y, pan); + + flutter::EncodableValue response("OK"); + + result->Success(response); +} + +void PolyvoxFilamentPlugin::GrabEnd( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + grab_end(_viewer); + flutter::EncodableValue response("OK"); + result->Success(response); +} + +void PolyvoxFilamentPlugin::GrabUpdate( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = + std::get_if(methodCall.arguments()); + + const auto x = static_cast(*std::get_if(&(args->at(0)))); + const auto y = static_cast(*std::get_if(&(args->at(1)))); + + grab_update(_viewer, x, y); + + flutter::EncodableValue response("OK"); + + result->Success(response); +} + +void PolyvoxFilamentPlugin::ScrollBegin( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + scroll_begin(_viewer); + flutter::EncodableValue response("OK"); + result->Success(response); +} + +void PolyvoxFilamentPlugin::ScrollEnd( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + scroll_end(_viewer); + flutter::EncodableValue response("OK"); + result->Success(response); +} + +void PolyvoxFilamentPlugin::ScrollUpdate( + const flutter::MethodCall &methodCall, + std::unique_ptr> result) { + + const auto *args = std::get_if(methodCall.arguments()); + const float x = static_cast(*std::get_if(&(args->at(0)))); + const float y = static_cast(*std::get_if(&(args->at(1)))); + const float z = static_cast(*std::get_if(&(args->at(2)))); + + scroll_update(_viewer, x, y, z); + + flutter::EncodableValue response("OK"); + + result->Success(response); +} + void PolyvoxFilamentPlugin::HandleMethodCall( const flutter::MethodCall &methodCall, std::unique_ptr> result) { - std::cout << methodCall.method_name() << std::endl; + // std::cout << methodCall.method_name() << std::endl; - if(methodCall.method_name() == "createFilamentViewer") { + if (methodCall.method_name() == "createFilamentViewer") { CreateFilamentViewer(methodCall, std::move(result)); - } else if(methodCall.method_name() == "createTexture") { - CreateTexture(methodCall, std::move(result)); - } //else if(strcmp(method, "updateViewportAndCameraProjection")==0){ - // response = _update_viewport_and_camera_projection(methodCall); - // } - // else if(strcmp(method, "getAssetManager") ==0){ - // response = _get_asset_manager(self, methodCall); + } else if (methodCall.method_name() == "createTexture") { + CreateTexture(methodCall, std::move(result)); + } else if (methodCall.method_name() == "setBackgroundImage") { + SetBackgroundImage(methodCall, std::move(result)); + } else if (methodCall.method_name() == "setBackgroundColor") { + SetBackgroundColor(methodCall, std::move(result)); + } else if (methodCall.method_name() == "render") { + Render(methodCall, std::move(result)); + } else if (methodCall.method_name() == "setRendering") { + SetRendering(methodCall, std::move(result)); + } else if (methodCall.method_name() == "updateViewportAndCameraProjection") { + UpdateViewportAndCameraProjection(methodCall, std::move(result)); + } else if (methodCall.method_name() == "getAssetManager") { + GetAssetManager(methodCall, std::move(result)); + } else if (methodCall.method_name() == "addLight") { + AddLight(methodCall, std::move(result)); + } else if (methodCall.method_name() == "loadGlb") { + LoadGlb(methodCall, std::move(result)); + } else if (methodCall.method_name() == "loadSkybox") { + LoadSkybox(methodCall, std::move(result)); + } else if (methodCall.method_name() == "loadIbl") { + LoadIbl(methodCall, std::move(result)); + } else if (methodCall.method_name() == "removeIbl") { + RemoveIbl(methodCall, std::move(result)); + } else if (methodCall.method_name() == "removeSkybox") { + RemoveSkybox(methodCall, std::move(result)); + } else if (methodCall.method_name() == "addLight") { + AddLight(methodCall, std::move(result)); + } else if (methodCall.method_name() == "getAnimationNames") { + GetAnimationNames(methodCall, std::move(result)); + } else if (methodCall.method_name() == "removeAsset") { + RemoveAsset(methodCall, std::move(result)); + } else if (methodCall.method_name() == "transformToUnitCube") { + TransformToUnitCube(methodCall, std::move(result)); + } else if (methodCall.method_name() == "rotateStart") { + RotateStart(methodCall, std::move(result)); + } else if (methodCall.method_name() == "rotateEnd") { + RotateEnd(methodCall, std::move(result)); + } else if (methodCall.method_name() == "rotateUpdate") { + RotateUpdate(methodCall, std::move(result)); + } else if (methodCall.method_name() == "panStart") { + PanStart(methodCall, std::move(result)); + } else if (methodCall.method_name() == "panUpdate") { + PanUpdate(methodCall, std::move(result)); + } else if (methodCall.method_name() == "panEnd") { + PanEnd(methodCall, std::move(result)); + } else if (methodCall.method_name() == "setPosition") { + SetPosition(methodCall, std::move(result)); + } else if (methodCall.method_name() == "setRotation") { + SetRotation(methodCall, std::move(result)); + } else if (methodCall.method_name() == "grabBegin") { + GrabBegin(methodCall, std::move(result)); + } else if (methodCall.method_name() == "grabEnd") { + GrabEnd(methodCall, std::move(result)); + } else if (methodCall.method_name() == "grabUpdate") { + GrabUpdate(methodCall, std::move(result)); + } else if (methodCall.method_name() == "scrollBegin") { + ScrollBegin(methodCall, std::move(result)); + } else if (methodCall.method_name() == "scrollEnd") { + ScrollEnd(methodCall, std::move(result)); + } else if (methodCall.method_name() == "scrollUpdate") { + ScrollUpdate(methodCall, std::move(result)); + } else { + result->NotImplemented(); + } // } else if(strcmp(method, "setToneMapping") == 0) { // response = _set_tone_mapping(self, methodCall); // } else if(strcmp(method, "setBloom") == 0) { @@ -177,69 +732,25 @@ void PolyvoxFilamentPlugin::HandleMethodCall( // } else if(strcmp(method, "resize") == 0) { // response = _resize(self, methodCall); // } else if(strcmp(method, "getContext") == 0) { - // g_autoptr(FlValue) result = - // fl_value_new_int(reinterpret_cast(glXGetCurrentContext())); + // g_autoptr(FlValue) result = + // fl_value_new_int(reinterpret_cast(glXGetCurrentContext())); // response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); // } else if(strcmp(method, "getGlTextureId") == 0) { - // g_autoptr(FlValue) result = - // fl_value_new_int(reinterpret_cast(((FilamentTextureGL*)self->texture)->texture_id)); + // g_autoptr(FlValue) result = + // fl_value_new_int(reinterpret_cast(((FilamentTextureGL*)self->texture)->texture_id)); // response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); // } else if(strcmp(method, "getResourceLoader") == 0) { - // ResourceLoaderWrapper* resourceLoader = new ResourceLoaderWrapper(loadResource, freeResource); - // g_autoptr(FlValue) result = - // fl_value_new_int(reinterpret_cast(resourceLoader)); + // ResourceLoaderWrapper* resourceLoader = new + // ResourceLoaderWrapper(loadResource, freeResource); g_autoptr(FlValue) + // result = + // fl_value_new_int(reinterpret_cast(resourceLoader)); // response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); // } else if(strcmp(method, "setRendering") == 0) { // self->rendering = fl_value_get_bool(fl_methodCall_get_args(methodCall)); - // response = FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_string("OK"))); - // } else if(strcmp(method, "loadSkybox") == 0) { - // response = _loadSkybox(self, method_call); - // } else if(strcmp(method, "loadIbl") == 0) { - // response = _loadIbl(self, method_call); - // } else if(strcmp(method, "removeIbl") ==0) { - // response = _remove_ibl(self, method_call); - // } else if(strcmp(method, "removeSkybox") == 0) { - // response = _removeSkybox(self, method_call); - // } else if(strcmp(method, "render") == 0) { - // render(self->viewer, 0); - // g_autoptr(FlValue) result = fl_value_new_string("OK"); - // response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); - // } else if(strcmp(method, "setBackgroundColor") == 0) { - // response = _set_background_color(self, method_call); - // } else if(strcmp(method, "setBackgroundImage") == 0) { - // response = _set_background_image(self, method_call); - // } else if(strcmp(method, "addLight") == 0) { - // response = _add_light(self, method_call); - // } else if(strcmp(method, "loadGlb") == 0) { - // response = _load_glb(self, method_call); - // } else if(strcmp(method, "getAnimationNames") == 0) { - // response = _get_animation_names(self, method_call); - // } else if(strcmp(method, "clearAssets") == 0) { - // clear_assets(self->viewer); - // g_autoptr(FlValue) result = fl_value_new_string("OK"); - // response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); - // } else if(strcmp(method, "removeAsset") == 0) { - // response = _remove_asset(self, method_call); - // } else if(strcmp(method, "transformToUnitCube") == 0) { - // response = _transform_to_unit_cube(self, method_call); - // } else if(strcmp(method, "clearLights") == 0) { - // clear_lights(self->viewer); - // g_autoptr(FlValue) result = fl_value_new_string("OK"); - // response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); - // } else if(strcmp(method, "panStart") == 0) { - // response = _pan_start(self, method_call); - // } else if(strcmp(method, "panEnd") == 0) { - // response = _pan_end(self, method_call); - // } else if(strcmp(method, "panUpdate") == 0) { - // response = _pan_update(self, method_call); - // } else if(strcmp(method, "rotateStart") == 0) { - // response = _rotate_start(self, method_call); - // } else if(strcmp(method, "rotateEnd") == 0) { - // response = _rotate_end(self, method_call); - // } else if(strcmp(method, "rotateUpdate") == 0) { - // response = _rotate_update(self, method_call); - // } else if(strcmp(method, "setRotation") == 0) { - // response = _set_rotation(self, method_call); + // response = + // FL_METHOD_RESPONSE(fl_method_success_response_new(fl_value_new_string("OK"))); + // } else if(strcmp(method, "setCamera") == 0) { // response = _set_camera(self, method_call); // } else if(strcmp(method, "setCameraModelMatrix") == 0) { @@ -285,6 +796,74 @@ void PolyvoxFilamentPlugin::HandleMethodCall( // fl_method_call_respond(method_call, response, nullptr); } -} // namespace +} // namespace polyvox_filament +// glfwInit(); +// glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); +// glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); +// glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); +// glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); + +// GLFWwindow* window = glfwCreateWindow(1024, 768, "", nullptr, nullptr); +// if (!window) { +// std::cout << "Failed to create GLFW window" << std::endl; +// glfwTerminate(); +// return; +// } + +// glfwMakeContextCurrent(window); + +// glClearColor(0.1f, 0.2f, 0.3f, 1.0f); +// glClear(GL_COLOR_BUFFER_BIT); + +// auto data = new uint8_t[1024*768*4]; +// glReadPixels(0,0, 1024, 768, GL_RGBA, GL_UNSIGNED_BYTE, data); +// _pixelData.reset(data); + +// GLuint glTextureId = 0; + +// auto textureData = new uint8_t[1024*768*4]; +// for(int y = 0; y < 768; y++) { +// for(int x=0; x < 1024; x++) { +// textureData[y*768 + (x*4)] = 0; +// textureData[y*768 + (x*4+1)] = 255; +// textureData[y*768 + (x*4+2)] = 0; +// textureData[y*768 + (x*4+3)] = 255; +// } +// } + +// glGenTextures(1, &glTextureId); + +// glBindTexture(GL_TEXTURE_2D, glTextureId); + +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); +// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + +// glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 1024, 768, 0, GL_RGBA, +// GL_UNSIGNED_BYTE, textureData); + +// _pixelBuffer = std::make_unique(); +// _pixelBuffer->buffer = _pixelData.get(); + +// _pixelBuffer->width = 1024; +// _pixelBuffer->height = 768; + +// _texture = +// std::make_unique(flutter::PixelBufferTexture( +// [=](size_t width, size_t height) -> const FlutterDesktopPixelBuffer* { +// std::cout << "Copying pixel buffer for " << width << "x" << height << +// std::endl; +// // uint8_t* data = _pixelData.get(); +// uint8_t* data = new uint8_t[height*width*4]; +// glReadPixels(0,0, (GLsizei)width, (GLsizei)height, GL_RGB, +// GL_UNSIGNED_BYTE, data); return _pixelBuffer.get(); +// })); + +// std::cout << "Registering texture" << std::endl; + +// _flutterTextureId = _textureRegistrar->RegisterTexture(_texture.get()); +// _textureRegistrar->MarkTextureFrameAvailable(_flutterTextureId); +// std::cout << "Registered " << _flutterTextureId << std::endl; \ No newline at end of file diff --git a/windows/polyvox_filament_plugin.h b/windows/polyvox_filament_plugin.h index 3b5fc250..1eedfbba 100644 --- a/windows/polyvox_filament_plugin.h +++ b/windows/polyvox_filament_plugin.h @@ -4,55 +4,168 @@ #include #include +#include #include + +#include "GL/GL.h" +#include "GL/GLu.h" + #include "PolyvoxFilamentApi.h" namespace polyvox_filament { class PolyvoxFilamentPlugin : public flutter::Plugin { - public: +public: static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar); - PolyvoxFilamentPlugin( - flutter::TextureRegistrar* textureRegistrar, - flutter::PluginRegistrarWindows *registrar - ); + PolyvoxFilamentPlugin(flutter::TextureRegistrar *textureRegistrar, + flutter::PluginRegistrarWindows *registrar); virtual ~PolyvoxFilamentPlugin(); // Disallow copy and assign. - PolyvoxFilamentPlugin(const PolyvoxFilamentPlugin&) = delete; - PolyvoxFilamentPlugin& operator=(const PolyvoxFilamentPlugin&) = delete; + PolyvoxFilamentPlugin(const PolyvoxFilamentPlugin &) = delete; + PolyvoxFilamentPlugin &operator=(const PolyvoxFilamentPlugin &) = delete; // Called when a method is called on this plugin's channel from Dart. void HandleMethodCall( const flutter::MethodCall &method_call, std::unique_ptr> result); - flutter::PluginRegistrarWindows* _pluginRegistrar; - flutter::TextureRegistrar* _textureRegistrar; + flutter::PluginRegistrarWindows *_pluginRegistrar; + flutter::TextureRegistrar *_textureRegistrar; std::unique_ptr _texture = nullptr; std::unique_ptr _pixelBuffer = nullptr; std::unique_ptr _pixelData = nullptr; + std::chrono::milliseconds _frameInterval; + bool _rendering = false; int64_t _flutterTextureId; - int _glTextureId; + GLuint _glTextureId = 0; + HGLRC _context = NULL; - void* _viewer = nullptr; + void *_viewer = nullptr; + + std::map _resources; void CreateFilamentViewer( - const flutter::MethodCall &methodCall, - std::unique_ptr> result); + const flutter::MethodCall &methodCall, + std::unique_ptr> result); void CreateTexture( - const flutter::MethodCall &methodCall, - std::unique_ptr> result); - + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + void Render( - const flutter::MethodCall &methodCall, - std::unique_ptr> result); + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void SetRendering( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void SetBackgroundImage( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void SetBackgroundColor( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void UpdateViewportAndCameraProjection( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void GetAssetManager( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void LoadSkybox( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void LoadIbl( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void RemoveSkybox( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void RemoveIbl( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void AddLight( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void LoadGlb( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void RotateStart( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + void RotateEnd( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + void RotateUpdate( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + void PanStart( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + void PanUpdate( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void PanEnd( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void SetPosition( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void SetRotation( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void GetAnimationNames( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void RemoveAsset( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void TransformToUnitCube( + const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void GrabBegin(const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void GrabEnd(const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void GrabUpdate(const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void ScrollBegin(const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void ScrollEnd(const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + void ScrollUpdate(const flutter::MethodCall &methodCall, + std::unique_ptr> result); + + ResourceBuffer loadResource(const char *path); + void freeResource(ResourceBuffer rbuf); }; -} // namespace polyvox_filament +} // namespace polyvox_filament -#endif // FLUTTER_PLUGIN_POLYVOX_FILAMENT_PLUGIN_H_ +#endif // FLUTTER_PLUGIN_POLYVOX_FILAMENT_PLUGIN_H_