feat: ignore grid overlay and gizmo center when picking, implement highlighting

This commit is contained in:
Nick Fisher
2024-08-24 16:17:34 +08:00
parent 2e1f2cd56d
commit 11756fcedd

View File

@@ -88,6 +88,7 @@
#include <filesystem> #include <filesystem>
#include <mutex> #include <mutex>
#include <iomanip> #include <iomanip>
#include <unordered_set>
#include "Log.hpp" #include "Log.hpp"
@@ -115,10 +116,6 @@ namespace thermion_filament
using std::string; using std::string;
// const float kAperture = 1.0f;
// const float kShutterSpeed = 1.0f;
// const float kSensitivity = 50.0f;
static constexpr float4 sFullScreenTriangleVertices[3] = { static constexpr float4 sFullScreenTriangleVertices[3] = {
{-1.0f, -1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f, 1.0f},
{3.0f, -1.0f, 1.0f, 1.0f}, {3.0f, -1.0f, 1.0f, 1.0f},
@@ -129,7 +126,7 @@ namespace thermion_filament
FilamentViewer::FilamentViewer(const void *sharedContext, const ResourceLoaderWrapperImpl *const resourceLoader, void *const platform, const char *uberArchivePath) FilamentViewer::FilamentViewer(const void *sharedContext, const ResourceLoaderWrapperImpl *const resourceLoader, void *const platform, const char *uberArchivePath)
: _resourceLoaderWrapper(resourceLoader) : _resourceLoaderWrapper(resourceLoader)
{ {
_context = (void*) sharedContext; _context = (void *)sharedContext;
ASSERT_POSTCONDITION(_resourceLoaderWrapper != nullptr, "Resource loader must be non-null"); ASSERT_POSTCONDITION(_resourceLoaderWrapper != nullptr, "Resource loader must be non-null");
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
@@ -147,14 +144,11 @@ namespace thermion_filament
#else #else
_engine = Engine::create(Engine::Backend::OPENGL, (backend::Platform *)platform, (void *)sharedContext, nullptr); _engine = Engine::create(Engine::Backend::OPENGL, (backend::Platform *)platform, (void *)sharedContext, nullptr);
#endif #endif
Log("Created engine");
_engine->setAutomaticInstancingEnabled(true); _engine->setAutomaticInstancingEnabled(true);
_renderer = _engine->createRenderer(); _renderer = _engine->createRenderer();
Log("Created renderer");
_frameInterval = 1000.0f / 60.0f; _frameInterval = 1000.0f / 60.0f;
setFrameInterval(_frameInterval); setFrameInterval(_frameInterval);
@@ -180,9 +174,9 @@ namespace thermion_filament
_view->setAmbientOcclusionOptions({.enabled = false}); _view->setAmbientOcclusionOptions({.enabled = false});
_view->setDynamicResolutionOptions({.enabled = false}); _view->setDynamicResolutionOptions({.enabled = false});
#if defined(_WIN32) #if defined(_WIN32)
_view->setStereoscopicOptions({.enabled = true}); _view->setStereoscopicOptions({.enabled = true});
#endif #endif
_view->setDithering(filament::Dithering::NONE); _view->setDithering(filament::Dithering::NONE);
setAntiAliasing(false, false, false); setAntiAliasing(false, false, false);
@@ -196,8 +190,7 @@ namespace thermion_filament
_cameraFocalLength = 28.0f; _cameraFocalLength = 28.0f;
_mainCamera->setLensProjection(_cameraFocalLength, 1.0f, _near, _mainCamera->setLensProjection(_cameraFocalLength, 1.0f, _near,
_far); _far);
// _mainCamera->setExposure(kAperture, kShutterSpeed, kSensitivity);
Log("View created");
const float aperture = _mainCamera->getAperture(); const float aperture = _mainCamera->getAperture();
const float shutterSpeed = _mainCamera->getShutterSpeed(); const float shutterSpeed = _mainCamera->getShutterSpeed();
const float sens = _mainCamera->getSensitivity(); const float sens = _mainCamera->getSensitivity();
@@ -207,13 +200,11 @@ namespace thermion_filament
EntityManager &em = EntityManager::get(); EntityManager &em = EntityManager::get();
_sceneManager = new SceneManager( _sceneManager = new SceneManager(
_view,
_resourceLoaderWrapper, _resourceLoaderWrapper,
_engine, _engine,
_scene, _scene,
uberArchivePath); uberArchivePath);
Log("Created scene maager");
} }
void FilamentViewer::setAntiAliasing(bool msaa, bool fxaa, bool taa) void FilamentViewer::setAntiAliasing(bool msaa, bool fxaa, bool taa)
@@ -243,22 +234,22 @@ namespace thermion_filament
_view->setShadowType(shadowType); _view->setShadowType(shadowType);
} }
void FilamentViewer::setSoftShadowOptions(float penumbraScale, float penumbraRatioScale) { void FilamentViewer::setSoftShadowOptions(float penumbraScale, float penumbraRatioScale)
{
SoftShadowOptions opts; SoftShadowOptions opts;
opts.penumbraRatioScale = penumbraRatioScale; opts.penumbraRatioScale = penumbraRatioScale;
opts.penumbraScale = penumbraScale; opts.penumbraScale = penumbraScale;
_view->setSoftShadowOptions(opts); _view->setSoftShadowOptions(opts);
} }
void FilamentViewer::setBloom(float strength) void FilamentViewer::setBloom(float strength)
{ {
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
decltype(_view->getBloomOptions()) opts; decltype(_view->getBloomOptions()) opts;
opts.enabled = true; opts.enabled = true;
opts.strength = strength; opts.strength = strength;
_view->setBloomOptions(opts); _view->setBloomOptions(opts);
#endif #endif
} }
void FilamentViewer::setToneMapping(ToneMapping toneMapping) void FilamentViewer::setToneMapping(ToneMapping toneMapping)
@@ -335,9 +326,12 @@ namespace thermion_filament
.direction(math::float3(dirX, dirY, dirZ)) .direction(math::float3(dirX, dirY, dirZ))
.castShadows(shadows) .castShadows(shadows)
.build(*_engine, light); .build(*_engine, light);
if(result != LightManager::Builder::Result::Success) { if (result != LightManager::Builder::Result::Success)
{
Log("ERROR : failed to create light"); Log("ERROR : failed to create light");
} else { }
else
{
_scene->addEntity(light); _scene->addEntity(light);
_lights.push_back(light); _lights.push_back(light);
} }
@@ -507,7 +501,8 @@ namespace thermion_filament
{ {
std::lock_guard lock(_imageMutex); std::lock_guard lock(_imageMutex);
if(_imageEntity.isNull()) { if (_imageEntity.isNull())
{
createBackgroundImage(); createBackgroundImage();
} }
_imageMaterial->setDefaultParameter("showImage", 0); _imageMaterial->setDefaultParameter("showImage", 0);
@@ -515,7 +510,8 @@ namespace thermion_filament
_imageMaterial->setDefaultParameter("transform", _imageScale); _imageMaterial->setDefaultParameter("transform", _imageScale);
} }
void FilamentViewer::createBackgroundImage() { void FilamentViewer::createBackgroundImage()
{
_dummyImageTexture = Texture::Builder() _dummyImageTexture = Texture::Builder()
.width(1) .width(1)
@@ -561,7 +557,7 @@ namespace thermion_filament
_imageIb->setBuffer(*_engine, {sFullScreenTriangleIndices, _imageIb->setBuffer(*_engine, {sFullScreenTriangleIndices,
sizeof(sFullScreenTriangleIndices)}); sizeof(sFullScreenTriangleIndices)});
auto & em = EntityManager::get(); auto &em = EntityManager::get();
_imageEntity = em.create(); _imageEntity = em.create();
RenderableManager::Builder(1) RenderableManager::Builder(1)
.boundingBox({{}, {1.0f, 1.0f, 1.0f}}) .boundingBox({{}, {1.0f, 1.0f, 1.0f}})
@@ -577,7 +573,8 @@ namespace thermion_filament
{ {
std::lock_guard lock(_imageMutex); std::lock_guard lock(_imageMutex);
if(_imageEntity.isNull()) { if (_imageEntity.isNull())
{
createBackgroundImage(); createBackgroundImage();
} }
_imageMaterial->setDefaultParameter("image", _dummyImageTexture, _imageSampler); _imageMaterial->setDefaultParameter("image", _dummyImageTexture, _imageSampler);
@@ -595,7 +592,8 @@ namespace thermion_filament
std::lock_guard lock(_imageMutex); std::lock_guard lock(_imageMutex);
if(_imageEntity.isNull()) { if (_imageEntity.isNull())
{
createBackgroundImage(); createBackgroundImage();
} }
@@ -610,7 +608,7 @@ namespace thermion_filament
// This currently just anchors the image at the bottom left of the viewport at its original size // This currently just anchors the image at the bottom left of the viewport at its original size
// TODO - implement stretch/etc // TODO - implement stretch/etc
const Viewport &vp = _view->getViewport(); const Viewport &vp = _view->getViewport();
Log("Image width %d height %d vp width %d height %d", _imageWidth, _imageHeight, vp.width, vp.height); // Log("Image width %d height %d vp width %d height %d", _imageWidth, _imageHeight, vp.width, vp.height);
float xScale = float(vp.width) / float(_imageWidth); float xScale = float(vp.width) / float(_imageWidth);
@@ -641,7 +639,8 @@ namespace thermion_filament
{ {
std::lock_guard lock(_imageMutex); std::lock_guard lock(_imageMutex);
if(_imageEntity.isNull()) { if (_imageEntity.isNull())
{
createBackgroundImage(); createBackgroundImage();
} }
@@ -724,7 +723,8 @@ namespace thermion_filament
{ {
clearLights(); clearLights();
destroySwapChain(); destroySwapChain();
if(!_imageEntity.isNull()) { if (!_imageEntity.isNull())
{
_engine->destroy(_imageEntity); _engine->destroy(_imageEntity);
_engine->destroy(_imageTexture); _engine->destroy(_imageTexture);
_engine->destroy(_imageVb); _engine->destroy(_imageVb);
@@ -735,6 +735,7 @@ namespace thermion_filament
_engine->destroyCameraComponent(_mainCamera->getEntity()); _engine->destroyCameraComponent(_mainCamera->getEntity());
_mainCamera = nullptr; _mainCamera = nullptr;
_engine->destroy(_view); _engine->destroy(_view);
_engine->destroy(_scene); _engine->destroy(_scene);
_engine->destroy(_renderer); _engine->destroy(_renderer);
Engine::destroy(&_engine); Engine::destroy(&_engine);
@@ -806,11 +807,11 @@ namespace thermion_filament
_swapChain = nullptr; _swapChain = nullptr;
Log("Swapchain destroyed."); Log("Swapchain destroyed.");
} }
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
_engine->execute(); _engine->execute();
#else #else
_engine->flushAndWait(); _engine->flushAndWait();
#endif #endif
} }
void FilamentViewer::clearEntities() void FilamentViewer::clearEntities()
@@ -821,8 +822,6 @@ namespace thermion_filament
void FilamentViewer::removeEntity(EntityId asset) void FilamentViewer::removeEntity(EntityId asset)
{ {
Log("Removing asset from scene");
mtx.lock(); mtx.lock();
// todo - what if we are using a camera from this asset? // todo - what if we are using a camera from this asset?
_sceneManager->remove(asset); _sceneManager->remove(asset);
@@ -835,7 +834,6 @@ namespace thermion_filament
void FilamentViewer::setCameraExposure(float aperture, float shutterSpeed, float sensitivity) void FilamentViewer::setCameraExposure(float aperture, float shutterSpeed, float sensitivity)
{ {
Camera &cam = _view->getCamera(); Camera &cam = _view->getCamera();
Log("Setting aperture (%03f) shutterSpeed (%03f) and sensitivity (%03f)", aperture, shutterSpeed, sensitivity);
cam.setExposure(aperture, shutterSpeed, sensitivity); cam.setExposure(aperture, shutterSpeed, sensitivity);
} }
@@ -846,7 +844,15 @@ namespace thermion_filament
{ {
Camera &cam = _view->getCamera(); Camera &cam = _view->getCamera();
_cameraFocalLength = focalLength; _cameraFocalLength = focalLength;
cam.setLensProjection(_cameraFocalLength, 1.0f, _near, const auto &vp = _view->getViewport();
if (vp.height == 0)
{
Log("Viewport height has not yet been set, returning");
return;
}
auto aspect = vp.width / vp.height;
cam.setLensProjection(_cameraFocalLength, aspect, _near,
_far); _far);
} }
@@ -858,8 +864,9 @@ namespace thermion_filament
Camera &cam = _view->getCamera(); Camera &cam = _view->getCamera();
_near = near; _near = near;
_far = far; _far = far;
cam.setLensProjection(_cameraFocalLength, 1.0f, _near, _far); const auto &vp = _view->getViewport();
Log("Set lens projection to focal length %f, near %f and far %f", _cameraFocalLength, _near, _far); auto aspect = vp.width / vp.height;
cam.setLensProjection(_cameraFocalLength, aspect, _near, _far);
} }
double FilamentViewer::getCameraCullingNear() double FilamentViewer::getCameraCullingNear()
@@ -1005,8 +1012,7 @@ namespace thermion_filament
ResourceBuffer* rb = (ResourceBuffer*) vec->at(1); ResourceBuffer* rb = (ResourceBuffer*) vec->at(1);
loader->free(*rb); loader->free(*rb);
delete rb; delete rb;
delete vec; delete vec; },
},
callbackData); callbackData);
_skybox = _skybox =
filament::Skybox::Builder().environment(_skyboxTexture).build(*_engine); filament::Skybox::Builder().environment(_skyboxTexture).build(*_engine);
@@ -1148,12 +1154,11 @@ namespace thermion_filament
_skippedFrames++; _skippedFrames++;
} }
// beginFrame = true;
if (beginFrame) if (beginFrame)
{ {
_renderer->render(_view); _renderer->render(_view);
_frameCount++; _frameCount++;
if (_recording) if (_recording)
@@ -1185,22 +1190,22 @@ namespace thermion_filament
} }
_renderer->endFrame(); _renderer->endFrame();
} }
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
_engine->execute(); _engine->execute();
#endif #endif
} }
void FilamentViewer::capture(uint8_t *out, void (*onComplete)()) { void FilamentViewer::capture(uint8_t *out, void (*onComplete)())
{
Viewport const &vp = _view->getViewport(); Viewport const &vp = _view->getViewport();
size_t pixelBufferSize = vp.width * vp.height * 4; size_t pixelBufferSize = vp.width * vp.height * 4;
auto *pixelBuffer = new uint8_t[pixelBufferSize]; auto *pixelBuffer = new uint8_t[pixelBufferSize];
auto callback = [](void *buf, size_t size, void *data) auto callback = [](void *buf, size_t size, void *data)
{ {
auto frameCallbackData = (std::vector<void *> *)data;
auto frameCallbackData = (std::vector<void*>*)data;
uint8_t *out = (uint8_t *)(frameCallbackData->at(0)); uint8_t *out = (uint8_t *)(frameCallbackData->at(0));
void* callbackPtr = frameCallbackData->at(1); void *callbackPtr = frameCallbackData->at(1);
void (*callback)(void) = (void (*)(void))callbackPtr; void (*callback)(void) = (void (*)(void))callbackPtr;
memcpy(out, buf, size); memcpy(out, buf, size);
@@ -1208,7 +1213,7 @@ namespace thermion_filament
callback(); callback();
}; };
auto userData = new std::vector<void*> { out, (void*)onComplete } ; auto userData = new std::vector<void *>{out, (void *)onComplete};
auto pbd = Texture::PixelBufferDescriptor( auto pbd = Texture::PixelBufferDescriptor(
pixelBuffer, pixelBufferSize, pixelBuffer, pixelBufferSize,
@@ -1218,21 +1223,22 @@ namespace thermion_filament
_renderer->render(_view); _renderer->render(_view);
if(_rt) { if (_rt)
{
_renderer->readPixels(_rt, 0, 0, vp.width, vp.height, std::move(pbd)); _renderer->readPixels(_rt, 0, 0, vp.width, vp.height, std::move(pbd));
} else { }
else
{
_renderer->readPixels(0, 0, vp.width, vp.height, std::move(pbd)); _renderer->readPixels(0, 0, vp.width, vp.height, std::move(pbd));
} }
_renderer->endFrame(); _renderer->endFrame();
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
_engine->execute(); _engine->execute();
emscripten_webgl_commit_frame(); emscripten_webgl_commit_frame();
#endif #endif
} }
void FilamentViewer::savePng(void *buf, size_t size, int frameNumber) void FilamentViewer::savePng(void *buf, size_t size, int frameNumber)
{ {
// std::lock_guard lock(_recordingMutex); // std::lock_guard lock(_recordingMutex);
@@ -1319,10 +1325,14 @@ namespace thermion_filament
const double aspect = (double)width / height; const double aspect = (double)width / height;
Camera &cam = _view->getCamera(); Camera &cam = _view->getCamera();
cam.setLensProjection(_cameraFocalLength, 1.0f, _near,
cam.setLensProjection(_cameraFocalLength, aspect, _near,
_far); _far);
cam.setScaling({1.0 / aspect, 1.0}); // cam.setScaling({1.0 / aspect, 1.0});
// Camera &gizmoCam = _gizmoView->getCamera();
// gizmoCam.setScaling({1.0 / aspect, 1.0});
Log("Set viewport to width: %d height: %d aspect %f scaleFactor : %f", width, height, aspect, Log("Set viewport to width: %d height: %d aspect %f scaleFactor : %f", width, height, aspect,
contentScaleFactor); contentScaleFactor);
@@ -1333,11 +1343,18 @@ namespace thermion_filament
_view->setFrustumCullingEnabled(enabled); _view->setFrustumCullingEnabled(enabled);
} }
void FilamentViewer::setCameraFov(double fovInDegrees, double aspect) float FilamentViewer::getCameraFov(bool horizontal)
{ {
Camera &cam = _view->getCamera(); Camera &cam = _view->getCamera();
cam.setProjection(fovInDegrees, aspect, _near, _far, Camera::Fov::HORIZONTAL); return cam.getFieldOfViewInDegrees(horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL);
Log("Set camera projection fov to %f", fovInDegrees); }
void FilamentViewer::setCameraFov(double fovInDegrees, bool horizontal)
{
Camera &cam = _view->getCamera();
const auto &vp = _view->getViewport();
auto aspect = vp.width / vp.height;
cam.setProjection(fovInDegrees, aspect, _near, _far, horizontal ? Camera::Fov::HORIZONTAL : Camera::Fov::VERTICAL);
} }
void FilamentViewer::setCameraPosition(float x, float y, float z) void FilamentViewer::setCameraPosition(float x, float y, float z)
@@ -1494,14 +1511,14 @@ namespace thermion_filament
{ {
_createManipulator(); _createManipulator();
} }
if (pan) // if (pan)
{ // {
Log("Beginning pan at %f %f", x, y); // Log("Beginning pan at %f %f", x, y);
} // }
else // else
{ // {
Log("Beginning rotate at %f %f", x, y); // Log("Beginning rotate at %f %f", x, y);
} // }
_manipulator->grabBegin(x, y, pan); _manipulator->grabBegin(x, y, pan);
} }
@@ -1574,8 +1591,25 @@ namespace thermion_filament
_view->pick(x, y, [=](filament::View::PickingQueryResult const &result) _view->pick(x, y, [=](filament::View::PickingQueryResult const &result)
{ {
if(result.renderable != _imageEntity) {
Log("Picked entity %d at screen space (%f,%f,(%f))", result.renderable, result.fragCoords.x, result.fragCoords.y, result.fragCoords.z);
auto* gizmo = _sceneManager->gizmo;
std::unordered_set<Entity, Entity::Hasher> nonPickableEntities = {
_imageEntity,
gizmo->center(),
_sceneManager->_gridOverlay->sphere(),
_sceneManager->_gridOverlay->grid(),
};
if(result.renderable == gizmo->x() || result.renderable == gizmo->y() || result.renderable == gizmo->z()) {
gizmo->highlight(result.renderable);
} else {
gizmo->unhighlight();
}
if (nonPickableEntities.find(result.renderable) == nonPickableEntities.end()) {
callback(Entity::smuggle(result.renderable), x, y); callback(Entity::smuggle(result.renderable), x, y);
} else {
Log("Ignored");
} }); } });
} }