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