use pixels in setBackgroundImagePosition and add argument for clamp

This commit is contained in:
Nick Fisher
2022-09-07 17:40:18 +10:00
parent 9e20c2e0b2
commit f956d46dfc
6 changed files with 68 additions and 47 deletions

View File

@@ -389,13 +389,11 @@ void FilamentViewer::setBackgroundImage(const char *resourcePath) {
_imageTexture->setImage(*_engine, 0, std::move(buffer)); _imageTexture->setImage(*_engine, 0, std::move(buffer));
_imageTexture->generateMipmaps(*_engine); _imageTexture->generateMipmaps(*_engine);
// This currently just centers the image in the viewport at its original size // This currently just acnhors 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);
_imageScale = mat4f { float(vp.width) / float(_imageWidth) , 0.0f, 0.0f, 1.0f, 0.0f, float(vp.height) / float(_imageHeight), 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,1.0f, 0.0f, 0.0f, 0.0f, 1.0f }; _imageScale = mat4f { float(vp.width) / float(_imageWidth) , 0.0f, 0.0f, 0.0f, 0.0f, float(vp.height) / float(_imageHeight), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f };
// _imageScale = mat4f { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,1.0f, 0.0f, 0.0f, 0.0f, 1.0f };
_imageMaterial->setDefaultParameter("transform", _imageScale); _imageMaterial->setDefaultParameter("transform", _imageScale);
_imageMaterial->setDefaultParameter("image", _imageTexture, _imageSampler); _imageMaterial->setDefaultParameter("image", _imageTexture, _imageSampler);
@@ -408,52 +406,75 @@ void FilamentViewer::setBackgroundImage(const char *resourcePath) {
/// ///
/// Translates the background image by the specified x/y NDC units (i.e. between -1 and 1). /// Translates the background image by (x,y) pixels.
/// Clamps both values so that the left/top and right/bottom sides of the background image are /// If clamp is true, x/y are both clamped so that the left/top and right/bottom sides of the background image
/// positioned at a max/min of -1/1 respectively (i.e. you cannot set a position where the left/top or right/bottom sides would be "inside" the screen coordinate space. /// are positioned at a max/min of -1/1 respectively
/// (i.e. you cannot set a position where the left/top or right/bottom sides would be "inside" the screen coordinate space).
/// ///
void FilamentViewer::setBackgroundImagePosition(float x, float y) { void FilamentViewer::setBackgroundImagePosition(float x, float y, bool clamp=false) {
// first, clamp x/y // to translate the background image, we apply a transform to the UV coordinates of the quad texture, not the quad itself (see image.mat).
auto xScale = float(_imageWidth) / _view->getViewport().width; // this allows us to set a background colour for the quad when the texture has been translated outside the quad's bounds.
auto yScale = float(_imageHeight) / _view->getViewport().height; // so we need to munge the coordinates appropriately (and take into consideration the scale transform applied when the image was loaded).
float xMin = 0; // first, convert x/y to a percentage of the original image size
float xMax = 0; x /= _imageWidth;
float yMin = 0; y /= _imageHeight;
float yMax = 0;
// we need to clamp x so that it can only be translated between (left side touching viewport left) and (right side touching viewport right) // now scale these by the viewport dimensions so they can be incorporated directly into the UV transform matrix.
// if width is less than viewport, these values are 0/1-xScale respectively // x *= _imageScale[0][0];
if(xScale < 1) { // y *= _imageScale[1][1];
xMin = 0;
xMax = 1-xScale; // TODO - I haven't updated the clamp calculations to work with scaled image width/height percentages so the below code is probably wrong, don't use it until it's fixed.
// otherwise, these value are (xScale-1 and 1-xScale) if(clamp) {
} else { Log("Clamping background image translation");
xMin = 1-xScale; // first, clamp x/y
xMax = 0; auto xScale = float(_imageWidth) / _view->getViewport().width;
auto yScale = float(_imageHeight) / _view->getViewport().height;
float xMin = 0;
float xMax = 0;
float yMin = 0;
float yMax = 0;
// we need to clamp x so that it can only be translated between (left side touching viewport left) and (right side touching viewport right)
// if width is less than viewport, these values are 0/1-xScale respectively
if(xScale < 1) {
xMin = 0;
xMax = 1-xScale;
// otherwise, these value are (xScale-1 and 1-xScale)
} else {
xMin = 1-xScale;
xMax = 0;
}
// do the same for y
if(yScale < 1) {
yMin = 0;
yMax = 1-yScale;
} else {
yMin = 1-yScale;
yMax = 0;
}
x = std::max(xMin, std::min(x,xMax));
y = std::max(yMin, std::min(y,yMax));
} }
// do the same for y
if(yScale < 1) {
yMin = 0;
yMax = 1-yScale;
} else {
yMin = 1-yScale;
yMax = 0;
}
x = std::max(xMin, std::min(x,xMax));
y = std::max(yMin, std::min(y,yMax));
// these values are then negated to account for the fact that the transform is applied to the UV coordinates, not the vertices (see image.mat). // these values are then negated to account for the fact that the transform is applied to the UV coordinates, not the vertices (see image.mat).
// i.e. translating the image right by 0.5 units means translating the UV coordinates left by 0.5 units. // i.e. translating the image right by 0.5 units means translating the UV coordinates left by 0.5 units.
x = -x; x = -x;
y = -y; y = -y;
Log("x %f y %f", x, y); Log("x %f y %f", x, y);
auto transform = _imageScale * math::mat4f::translation(math::float3(x, y, 0.0f)); Log("imageScale %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ", _imageScale[0][0],_imageScale[0][1],_imageScale[0][2], _imageScale[0][3], \
_imageScale[1][0],_imageScale[1][1],_imageScale[1][2], _imageScale[1][3],\
_imageScale[2][0],_imageScale[2][1],_imageScale[2][2], _imageScale[2][3], \
_imageScale[3][0],_imageScale[3][1],_imageScale[3][2], _imageScale[3][3]);
auto transform = math::mat4f::translation(math::float3(x, y, 0.0f)) * _imageScale;
Log("transform %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ", transform[0][0],transform[0][1],transform[0][2], transform[0][3], \ Log("transform %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f ", transform[0][0],transform[0][1],transform[0][2], transform[0][3], \
transform[1][0],transform[1][1],transform[1][2], transform[1][3],\ transform[1][0],transform[1][1],transform[1][2], transform[1][3],\
transform[2][0],transform[2][1],transform[2][2], transform[2][3], \ transform[2][0],transform[2][1],transform[2][2], transform[2][3], \

View File

@@ -73,7 +73,7 @@ namespace polyvox {
Renderer* getRenderer(); Renderer* getRenderer();
void setBackgroundImage(const char* resourcePath); void setBackgroundImage(const char* resourcePath);
void setBackgroundImagePosition(float x, float y); void setBackgroundImagePosition(float x, float y, bool clamp);
void setCameraPosition(float x, float y, float z); void setCameraPosition(float x, float y, float z);
void setCameraRotation(float rads, float x, float y, float z); void setCameraRotation(float rads, float x, float y, float z);

View File

@@ -28,8 +28,8 @@ extern "C" {
((FilamentViewer*)viewer)->setBackgroundImage(path); ((FilamentViewer*)viewer)->setBackgroundImage(path);
} }
void set_background_image_position(void* viewer, float x, float y) { void set_background_image_position(void* viewer, float x, float y, bool clamp) {
((FilamentViewer*)viewer)->setBackgroundImagePosition(x, y); ((FilamentViewer*)viewer)->setBackgroundImagePosition(x, y, clamp);
} }
void load_skybox(void* viewer, const char* skyboxPath) { void load_skybox(void* viewer, const char* skyboxPath) {

View File

@@ -10,7 +10,7 @@ typedef struct ResourceBuffer ResourceBuffer;
void* filament_viewer_new(void* texture, void* loadResource, void* freeResource); void* filament_viewer_new(void* texture, void* loadResource, void* freeResource);
void* filament_viewer_delete(void* viewer); void* filament_viewer_delete(void* viewer);
void set_background_image(void* viewer, const char* path); void set_background_image(void* viewer, const char* path);
void set_background_image_position(void* viewer, float x, float y); void set_background_image_position(void* viewer, float x, float y, bool clamp);
void load_skybox(void* viewer, const char* skyboxPath); void load_skybox(void* viewer, const char* skyboxPath);
void load_ibl(void* viewer, const char* iblPath); void load_ibl(void* viewer, const char* iblPath);
void remove_skybox(void* viewer); void remove_skybox(void* viewer);

View File

@@ -19,7 +19,7 @@ abstract class FilamentController {
Future resize(int width, int height, { double devicePixelRatio = 1, double contentScaleFactor=1}); Future resize(int width, int height, { double devicePixelRatio = 1, double contentScaleFactor=1});
Future setBackgroundImage(String path); Future setBackgroundImage(String path);
Future setBackgroundImagePosition(double x, double y); Future setBackgroundImagePosition(double x, double y, {bool clamp=false});
Future loadSkybox(String skyboxPath); Future loadSkybox(String skyboxPath);
Future removeSkybox(); Future removeSkybox();
Future loadIbl(String path); Future loadIbl(String path);
@@ -137,8 +137,8 @@ class PolyvoxFilamentController extends FilamentController {
} }
@override @override
Future setBackgroundImagePosition(double x, double y) async { Future setBackgroundImagePosition(double x, double y, { bool clamp = false}) async {
await _channel.invokeMethod("setBackgroundImagePosition", [x,y]); await _channel.invokeMethod("setBackgroundImagePosition", [x,y, clamp]);
} }
@override @override

View File

@@ -63,10 +63,10 @@ class _FilamentWidgetState extends State<FilamentWidget> {
} }
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
var size = ((context.findRenderObject()) as RenderBox).size; var size = ((context.findRenderObject()) as RenderBox).size;
print("Requesting texture creation for Filament of size $size"); print("Requesting creation of Filament back-end texture/viewer for viewport size $size");
await widget.controller await widget.controller
.createTextureViewer(size.width.toInt(), size.height.toInt()); .createTextureViewer(size.width.toInt(), size.height.toInt());
print("Filament texture available"); print("Filament texture/viewer created.");
setState(() { setState(() {
_ready = true; _ready = true;
}); });