Skip to content

Commit d7026d6

Browse files
authored
feat: add <BackgroundImage /> component (#200)
1 parent 66fa0ce commit d7026d6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+593
-118
lines changed

package/.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ module.exports = {
1616
'react-hooks/exhaustive-deps': [
1717
'error',
1818
{
19-
additionalHooks: '(useDerivedValue|useAnimatedStyle|useAnimatedProps|useWorkletEffect|useRenderCallback|useDisposableResource)',
19+
additionalHooks: '(useDerivedValue|useAnimatedStyle|useAnimatedProps|useWorkletEffect|useDisposableResource|useWorkletMemo)',
2020
},
2121
],
2222
},

package/cpp/RNFReferences.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,13 @@ template <typename T> struct References {
4646
static std::shared_ptr<T> adoptEngineRef(std::shared_ptr<filament::Engine> engine, T* value, CleanupEngineRefFunction&& cleanup) {
4747
return adoptRef(value, [engine = engine, cleanup = std::move(cleanup)](T* ref) { cleanup(engine, ref); });
4848
}
49+
50+
/**
51+
* Same as `adoptEngineRef` but with an automatic cleanup function that calls `Engine::destroy` on the reference.
52+
*/
53+
static std::shared_ptr<T> adoptEngineRefAuto(std::shared_ptr<filament::Engine> engine, T* value) {
54+
return adoptEngineRef(engine, value, [](std::shared_ptr<filament::Engine> engine, T* ref) { engine->destroy(ref); });
55+
}
4956
};
5057

5158
} // namespace margelo

package/cpp/core/RNFEngineImpl.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ std::shared_ptr<MaterialWrapper> EngineImpl::createMaterial(std::shared_ptr<Fila
366366
for (auto& materialInstanceWrapper : pMaterialImpl->getInstances()) {
367367
std::unique_lock lock(sharedThis->_mutex);
368368
MaterialInstance* materialInstance = materialInstanceWrapper->getMaterialInstance();
369+
// Note: we should only destroy a material instance when no-one is using it anymore
369370
engine->destroy(materialInstance);
370371
}
371372

package/cpp/core/RNFMaterialImpl.cpp

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "RNFMaterialImpl.h"
33
#include <filament/Engine.h>
44
#include <filament/TextureSampler.h>
5+
#include <math/mat3.h>
56

67
namespace margelo {
78

@@ -18,9 +19,11 @@ std::shared_ptr<MaterialInstanceWrapper> MaterialImpl::getDefaultInstance() {
1819
std::unique_lock lock(_mutex);
1920

2021
MaterialInstance* materialInstance = _material->getDefaultInstance();
21-
auto instance = std::make_shared<MaterialInstanceWrapper>(materialInstance);
22-
_instances.push_back(instance);
23-
return instance;
22+
// Note: the default material instance isn't added to the list of instances.
23+
// We only keep track of that list to destroy a material correctly (ie. all
24+
// its instances have to be destroyed first). However, the default instance
25+
// is not destroyable, so it can be ignored.
26+
return std::make_shared<MaterialInstanceWrapper>(materialInstance);
2427
}
2528

2629
void MaterialImpl::setDefaultFloatParameter(std::string name, double value) {
@@ -33,6 +36,16 @@ void MaterialImpl::setDefaultFloatParameter(std::string name, double value) {
3336
_material->setDefaultParameter(name.c_str(), (float)value);
3437
}
3538

39+
void MaterialImpl::setDefaultIntParameter(std::string name, int value) {
40+
std::unique_lock lock(_mutex);
41+
42+
if (!_material->hasParameter(name.c_str())) {
43+
throw std::runtime_error("MaterialWrapper::setDefaultIntParameter: Material does not have parameter \"" + name + "\"!");
44+
}
45+
46+
_material->setDefaultParameter(name.c_str(), value);
47+
}
48+
3649
void MaterialImpl::setDefaultTextureParameter(std::string name, Texture* texture, TextureSampler sampler) {
3750
std::unique_lock lock(_mutex);
3851

@@ -43,22 +56,59 @@ void MaterialImpl::setDefaultTextureParameter(std::string name, Texture* texture
4356
_material->setDefaultParameter(name.c_str(), texture, sampler);
4457
}
4558

46-
void MaterialImpl::setBaseColorSRGB(std::vector<double> rgba) {
59+
void MaterialImpl::setDefaultFloat3Parameter(std::string name, std::vector<double> vector) {
4760
std::unique_lock lock(_mutex);
48-
if (rgba.size() != 4) {
49-
throw std::runtime_error("MaterialInstanceWrapper::setBaseColorSRGB: RGBA vector must have 4 elements!");
61+
if (vector.size() != 3) {
62+
throw std::runtime_error("setDefaultFloat3Parameter: RGB vector must have 3 elements!");
63+
}
64+
65+
if (!_material->hasParameter(name.c_str())) {
66+
throw std::runtime_error("setDefaultFloat3Parameter: Material does not have parameter \"" + name + "\"!");
5067
}
5168

52-
double r = rgba[0];
53-
double g = rgba[1];
54-
double b = rgba[2];
55-
double a = rgba[3];
69+
float x = vector[0];
70+
float y = vector[1];
71+
float z = vector[2];
5672

57-
_material->setDefaultParameter("baseColorFactor", math::float4({r, g, b, a}));
73+
_material->setDefaultParameter(name.c_str(), math::float3({x, y, z}));
74+
}
75+
76+
void MaterialImpl::setDefaultFloat4Parameter(std::string name, std::vector<double> vector) {
77+
std::unique_lock lock(_mutex);
78+
if (vector.size() != 4) {
79+
throw std::runtime_error("setDefaultFloat4Parameter: RGBA vector must have 4 elements!");
80+
}
81+
82+
if (!_material->hasParameter(name.c_str())) {
83+
throw std::runtime_error("setDefaultFloat4Parameter: Material does not have parameter \"" + name + "\"!");
84+
}
85+
86+
double r = vector[0];
87+
double g = vector[1];
88+
double b = vector[2];
89+
double a = vector[3];
90+
91+
_material->setDefaultParameter(name.c_str(), math::float4({r, g, b, a}));
5892
}
5993
std::string MaterialImpl::getName() {
6094
std::unique_lock lock(_mutex);
6195
return _material->getName();
6296
}
6397

98+
void MaterialImpl::setDefaultMat3fParameter(std::string name, std::vector<double> value) {
99+
std::unique_lock lock(_mutex);
100+
101+
if (!_material->hasParameter(name.c_str())) {
102+
throw std::runtime_error("MaterialWrapper::setDefaultMat3fParameter: Material does not have parameter \"" + name + "\"!");
103+
}
104+
105+
if (value.size() != 9) {
106+
throw std::runtime_error("MaterialWrapper::setDefaultMat3fParameter: Value vector must have 9 elements!");
107+
}
108+
109+
math::mat3f matrix = math::mat3f((float)value[0], (float)value[1], (float)value[2], (float)value[3], (float)value[4], (float)value[5],
110+
(float)value[6], (float)value[7], (float)value[8]);
111+
_material->setDefaultParameter(name.c_str(), matrix);
112+
}
113+
64114
} // namespace margelo

package/cpp/core/RNFMaterialImpl.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,11 @@ class MaterialImpl {
2929
std::shared_ptr<MaterialInstanceWrapper> createInstance();
3030
std::shared_ptr<MaterialInstanceWrapper> getDefaultInstance();
3131
void setDefaultFloatParameter(std::string name, double value);
32+
void setDefaultIntParameter(std::string name, int value);
3233
void setDefaultTextureParameter(std::string name, Texture* texture, TextureSampler sampler);
33-
void setBaseColorSRGB(std::vector<double> rgba);
34+
void setDefaultFloat3Parameter(std::string name, std::vector<double> vector);
35+
void setDefaultFloat4Parameter(std::string name, std::vector<double> vector);
36+
void setDefaultMat3fParameter(std::string name, std::vector<double> value);
3437
std::string getName();
3538

3639
private:

package/cpp/core/RNFMaterialInstanceWrapper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ void MaterialInstanceWrapper::loadHybridMethods() {
1313
registerHybridMethod("setTransparencyMode", &MaterialInstanceWrapper::setTransparencyMode, this);
1414
registerHybridMethod("changeAlpha", &MaterialInstanceWrapper::changeAlpha, this);
1515
registerHybridMethod("setParameter", &MaterialInstanceWrapper::setParameter, this);
16-
registerHybridMethod("setBaseColorSRGB", &MaterialInstanceWrapper::setBaseColorSRGB, this);
16+
registerHybridMethod("setDefaultFloat4Parameter", &MaterialInstanceWrapper::setBaseColorSRGB, this);
1717
registerHybridGetter("getName", &MaterialInstanceWrapper::getName, this);
1818
}
1919

@@ -66,7 +66,7 @@ void MaterialInstanceWrapper::setBaseColorSRGB(std::vector<double> rgba) {
6666
std::unique_lock lock(_mutex);
6767

6868
if (rgba.size() != 4) {
69-
throw std::runtime_error("MaterialInstanceWrapper::setBaseColorSRGB: RGBA vector must have 4 elements!");
69+
throw std::runtime_error("MaterialInstanceWrapper::setDefaultFloat4Parameter: RGBA vector must have 4 elements!");
7070
}
7171

7272
double r = rgba[0];

package/cpp/core/RNFMaterialWrapper.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,18 @@
55
#include "RNFMaterialWrapper.h"
66
#include "RNFRenderableManagerWrapper.h"
77

8+
#include <filament/Texture.h>
9+
810
namespace margelo {
911
void MaterialWrapper::loadHybridMethods() {
1012
registerHybridMethod("createInstance", &MaterialWrapper::createInstance, this);
1113
registerHybridMethod("setDefaultFloatParameter", &MaterialWrapper::setDefaultFloatParameter, this);
1214
registerHybridMethod("setDefaultTextureParameter", &MaterialWrapper::setDefaultTextureParameter, this);
1315
registerHybridMethod("getDefaultInstance", &MaterialWrapper::getDefaultInstance, this);
14-
registerHybridMethod("setBaseColorSRGB", &MaterialWrapper::setBaseColorSRGB, this);
16+
registerHybridMethod("setDefaultMat3fParameter", &MaterialWrapper::setDefaultMat3fParameter, this);
17+
registerHybridMethod("setDefaultFloat3Parameter", &MaterialWrapper::setDefaultFloat3Parameter, this);
18+
registerHybridMethod("setDefaultFloat4Parameter", &MaterialWrapper::setDefaultFloat4Parameter, this);
19+
registerHybridMethod("setDefaultIntParameter", &MaterialWrapper::setDefaultIntParameter, this);
1520
}
1621
std::shared_ptr<MaterialInstanceWrapper> MaterialWrapper::createInstance() {
1722
return pointee()->createInstance();
@@ -22,8 +27,9 @@ std::shared_ptr<MaterialInstanceWrapper> MaterialWrapper::getDefaultInstance() {
2227
void MaterialWrapper::setDefaultFloatParameter(std::string name, double value) {
2328
pointee()->setDefaultFloatParameter(name, value);
2429
}
25-
void MaterialWrapper::setDefaultTextureParameter(std::shared_ptr<RenderableManagerWrapper> renderableManager, std::string name,
26-
std::shared_ptr<FilamentBuffer> buffer, const std::string& textureFlags) {
30+
std::unordered_map<std::string, int>
31+
MaterialWrapper::setDefaultTextureParameter(std::shared_ptr<RenderableManagerWrapper> renderableManager, std::string name,
32+
std::shared_ptr<FilamentBuffer> buffer, const std::string& textureFlags) {
2733

2834
// Create a texture from the buffer using the renderable manager:
2935
Texture* texture = renderableManager->createTextureFromBuffer(buffer, textureFlags);
@@ -32,9 +38,26 @@ void MaterialWrapper::setDefaultTextureParameter(std::shared_ptr<RenderableManag
3238

3339
// Set the texture
3440
pointee()->setDefaultTextureParameter(name, texture, sampler);
41+
42+
// Return the texture size
43+
std::unordered_map<std::string, int> textureSize;
44+
textureSize["width"] = texture->getWidth();
45+
textureSize["height"] = texture->getHeight();
46+
return textureSize;
47+
}
48+
49+
void MaterialWrapper::setDefaultIntParameter(std::string name, int value) {
50+
pointee()->setDefaultIntParameter(name, value);
3551
}
36-
void MaterialWrapper::setBaseColorSRGB(std::vector<double> rgba) {
37-
pointee()->setBaseColorSRGB(rgba);
52+
void MaterialWrapper::setDefaultFloat3Parameter(std::string name, std::vector<double> vector) {
53+
pointee()->setDefaultFloat3Parameter(name, vector);
54+
}
55+
void MaterialWrapper::setDefaultFloat4Parameter(std::string name, std::vector<double> vector) {
56+
pointee()->setDefaultFloat4Parameter(name, vector);
57+
}
58+
59+
void MaterialWrapper::setDefaultMat3fParameter(std::string name, std::vector<double> value) {
60+
pointee()->setDefaultMat3fParameter(name, value);
3861
}
3962
std::string MaterialWrapper::getName() {
4063
return pointee()->getName();

package/cpp/core/RNFMaterialWrapper.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ class MaterialWrapper : public PointerHolder<MaterialImpl> {
2222
std::shared_ptr<MaterialInstanceWrapper> createInstance();
2323
std::shared_ptr<MaterialInstanceWrapper> getDefaultInstance();
2424
void setDefaultFloatParameter(std::string name, double value);
25-
void setDefaultTextureParameter(std::shared_ptr<RenderableManagerWrapper> renderableManager, std::string name,
26-
std::shared_ptr<FilamentBuffer> buffer, const std::string& textureFlags);
27-
void setBaseColorSRGB(std::vector<double> rgba);
25+
std::unordered_map<std::string, int> setDefaultTextureParameter(std::shared_ptr<RenderableManagerWrapper> renderableManager,
26+
std::string name, std::shared_ptr<FilamentBuffer> buffer,
27+
const std::string& textureFlags);
28+
void setDefaultIntParameter(std::string name, int value);
29+
void setDefaultFloat3Parameter(std::string name, std::vector<double> vector);
30+
void setDefaultFloat4Parameter(std::string name, std::vector<double> vector);
31+
void setDefaultMat3fParameter(std::string name, std::vector<double> value);
2832
std::string getName();
2933
};
3034

package/cpp/core/RNFRenderableManagerImpl.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44

55
#include "RNFRenderableManagerImpl.h"
66
#include "RNFEngineWrapper.h"
7+
#include "RNFReferences.h"
78
#include "RNFTextureFlagsEnum.h"
9+
#include "VertexEntity.h"
810
#include "core/RNFFilamentInstanceWrapper.h"
911

1012
#include <cmath>
1113

1214
#include <filament/IndexBuffer.h>
15+
#include <filament/MaterialInstance.h>
1316
#include <gltfio/TextureProvider.h>
1417
#include <math/norm.h>
1518

@@ -230,6 +233,41 @@ std::shared_ptr<EntityWrapper> RenderableManagerImpl::createPlane(std::shared_pt
230233
return std::make_shared<EntityWrapper>(renderable);
231234
}
232235

236+
static constexpr float4 sFullScreenTriangleVertices[3] = {{-1.0f, -1.0f, 1.0f, 1.0f}, {3.0f, -1.0f, 1.0f, 1.0f}, {-1.0f, 3.0f, 1.0f, 1.0f}};
237+
238+
static const uint16_t sFullScreenTriangleIndices[3] = {0, 1, 2};
239+
240+
VertexEntity RenderableManagerImpl::createImageBackground(MaterialInstance* materialInstance) {
241+
VertexBuffer* vertexBuffer = VertexBuffer::Builder()
242+
.vertexCount(3)
243+
.bufferCount(1)
244+
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT4, 0)
245+
.build(*_engine);
246+
vertexBuffer->setBufferAt(*_engine, 0, {sFullScreenTriangleVertices, sizeof(sFullScreenTriangleVertices)});
247+
248+
IndexBuffer* indexBuffer = IndexBuffer::Builder().indexCount(3).bufferType(IndexBuffer::IndexType::USHORT).build(*_engine);
249+
indexBuffer->setBuffer(*_engine, {sFullScreenTriangleIndices, sizeof(sFullScreenTriangleIndices)});
250+
251+
auto& em = utils::EntityManager::get();
252+
Entity imageEntity = em.create();
253+
RenderableManager::Builder(1)
254+
.boundingBox({{}, {1.0f, 1.0f, 1.0f}})
255+
.material(0, materialInstance)
256+
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vertexBuffer, indexBuffer, 0, 3)
257+
.culling(false)
258+
.build(*_engine, imageEntity);
259+
260+
// TODO: enable this pattern once EntityWrappers are PointerHolders!
261+
// std::shared_ptr<VertexBuffer> sharedVertexBuffer = References<VertexBuffer>::adoptEngineRefAuto(_engine, vertexBuffer);
262+
// std::shared_ptr<IndexBuffer> sharedIndexBuffer = References<IndexBuffer>::adoptEngineRefAuto(_engine, indexBuffer);
263+
264+
return {
265+
.entity = imageEntity,
266+
.vertexBuffer = nullptr,
267+
.indexBuffer = nullptr,
268+
};
269+
}
270+
233271
void RenderableManagerImpl::scaleBoundingBox(std::shared_ptr<FilamentAssetWrapper> assetWrapper, double scaleFactor) {
234272
if (assetWrapper == nullptr) {
235273
throw std::invalid_argument("Asset is null");

package/cpp/core/RNFRenderableManagerImpl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "RNFFilamentBuffer.h"
99
#include "RNFMaterialInstanceWrapper.h"
1010
#include "RNFMaterialWrapper.h"
11+
#include "VertexEntity.h"
1112
#include "core/utils/RNFEntityWrapper.h"
1213
#include "jsi/RNFPointerHolder.h"
1314

@@ -61,6 +62,7 @@ class RenderableManagerImpl {
6162

6263
std::shared_ptr<EntityWrapper> createPlane(std::shared_ptr<MaterialWrapper> materialWrapper, double halfExtendX, double halfExtendY,
6364
double halfExtendZ);
65+
VertexEntity createImageBackground(MaterialInstance* materialInstance);
6466
std::shared_ptr<EntityWrapper> createDebugCubeWireframe(float halfExtentX, float halfExtentY, float halfExtentZ,
6567
std::optional<std::shared_ptr<MaterialWrapper>> materialWrapper,
6668
std::optional<double> colorHexCode);
@@ -73,6 +75,10 @@ class RenderableManagerImpl {
7375

7476
Box getAxisAlignedBoundingBox(std::shared_ptr<EntityWrapper> entityWrapper);
7577

78+
std::shared_ptr<Engine> getEngine() {
79+
return _engine;
80+
}
81+
7682
private:
7783
// Calls the TextureProvider to start loading the resource
7884
void startUpdateResourceLoading();

0 commit comments

Comments
 (0)