feat: Rename Gizmo material to UnlitFixedSize, and expose methods for using this material on other entities. Also exposes new methods for setting single float parameters.

This commit is contained in:
Nick Fisher
2024-10-31 22:34:51 +08:00
parent c77ede9109
commit 4650ae1295
31 changed files with 1813 additions and 1634 deletions

View File

@@ -33,9 +33,12 @@
#include "CustomGeometry.hpp"
#include "UnprojectTexture.hpp"
#include "Gizmo.hpp"
extern "C"
{
#include "material/image.h"
#include "material/unlit_fixed_size.h"
}
namespace thermion
@@ -52,9 +55,8 @@ namespace thermion
Engine *engine,
Scene *scene,
const char *uberArchivePath,
Camera *mainCamera)
:
_resourceLoaderWrapper(resourceLoaderWrapper),
Camera *mainCamera)
: _resourceLoaderWrapper(resourceLoaderWrapper),
_engine(engine),
_scene(scene),
_mainCamera(mainCamera)
@@ -103,17 +105,22 @@ namespace thermion
_scene->addEntity(_gridOverlay->sphere());
_scene->addEntity(_gridOverlay->grid());
_gizmoMaterial =
Material::Builder()
.package(UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_DATA, UNLIT_FIXED_SIZE_UNLIT_FIXED_SIZE_SIZE)
.build(*_engine);
}
SceneManager::~SceneManager()
{
for(auto camera : _cameras) {
for (auto camera : _cameras)
{
auto entity = camera->getEntity();
_engine->destroyCameraComponent(entity);
_engine->getEntityManager().destroy(entity);
}
_cameras.clear();
_gridOverlay->destroy();
destroyAll();
@@ -131,8 +138,14 @@ namespace thermion
AssetLoader::destroy(&_assetLoader);
}
bool SceneManager::isGizmoEntity(Entity entity) {
return false; // TODO
Gizmo *SceneManager::createGizmo(View *view, Scene *scene)
{
return new Gizmo(_engine, view, scene, _gizmoMaterial);
}
bool SceneManager::isGizmoEntity(Entity entity)
{
return false; // TODO
}
int SceneManager::getInstanceCount(EntityId entityId)
@@ -246,15 +259,16 @@ namespace thermion
return eid;
}
void SceneManager::setVisibilityLayer(EntityId entityId, int layer) {
auto& rm = _engine->getRenderableManager();
void SceneManager::setVisibilityLayer(EntityId entityId, int layer)
{
auto &rm = _engine->getRenderableManager();
auto renderable = rm.getInstance(utils::Entity::import(entityId));
if(!renderable.isValid()) {
if (!renderable.isValid())
{
Log("Warning: no renderable found");
}
rm.setLayerMask(renderable, 0xFF, 1u << layer);
}
EntityId SceneManager::loadGlbFromBuffer(const uint8_t *data, size_t length, int numInstances, bool keepData, int priority, int layer, bool loadResourcesAsync)
@@ -281,11 +295,13 @@ namespace thermion
_scene->addEntities(asset->getEntities(), entityCount);
auto & rm = _engine->getRenderableManager();
auto &rm = _engine->getRenderableManager();
for(int i=0; i < entityCount; i++) {
for (int i = 0; i < entityCount; i++)
{
auto instance = rm.getInstance(asset->getEntities()[i]);
if(!instance.isValid()) {
if (!instance.isValid())
{
Log("No valid renderable for entity");
continue;
}
@@ -304,13 +320,16 @@ namespace thermion
_gltfResourceLoader->asyncUpdateLoad();
}
#else
if(loadResourcesAsync) {
if (loadResourcesAsync)
{
if (!_gltfResourceLoader->asyncBeginLoad(asset))
{
Log("Unknown error loading glb asset");
return 0;
}
} else {
}
else
{
if (!_gltfResourceLoader->loadResources(asset))
{
Log("Unknown error loading glb asset");
@@ -539,11 +558,13 @@ namespace thermion
asset.second->getLightEntityCount());
_assetLoader->destroyAsset(asset.second);
}
for(auto *texture : _textures) {
for (auto *texture : _textures)
{
_engine->destroy(texture);
}
for(auto *materialInstance : _materialInstances) {
for (auto *materialInstance : _materialInstances)
{
_engine->destroy(materialInstance);
}
@@ -661,7 +682,6 @@ namespace thermion
auto entity = Entity::import(entityId);
if (_animationComponentManager->hasComponent(entity))
{
_animationComponentManager->removeComponent(entity);
@@ -674,7 +694,8 @@ namespace thermion
_scene->remove(entity);
if(isGeometryEntity(entityId)) {
if (isGeometryEntity(entityId))
{
return;
}
@@ -1412,7 +1433,7 @@ namespace thermion
return texture;
}
bool SceneManager::applyTexture(EntityId entityId, Texture *texture, const char* parameterName, int materialIndex)
bool SceneManager::applyTexture(EntityId entityId, Texture *texture, const char *parameterName, int materialIndex)
{
auto entity = Entity::import(entityId);
@@ -1446,10 +1467,12 @@ namespace thermion
return true;
}
void SceneManager::destroyTexture(Texture* texture) {
if(_textures.find(texture) == _textures.end()) {
void SceneManager::destroyTexture(Texture *texture)
{
if (_textures.find(texture) == _textures.end())
{
Log("Warning: couldn't find texture");
}
}
_textures.erase(texture);
_engine->destroy(texture);
}
@@ -1904,7 +1927,7 @@ namespace thermion
tm.setTransform(transformInstance, newTransform);
}
void SceneManager::queueRelativePositionUpdateFromViewportVector(View* view, EntityId entityId, float viewportCoordX, float viewportCoordY)
void SceneManager::queueRelativePositionUpdateFromViewportVector(View *view, EntityId entityId, float viewportCoordX, float viewportCoordY)
{
// Get the camera and viewport
const auto &camera = view->getCamera();
@@ -1941,14 +1964,14 @@ namespace thermion
auto entityPlaneInWorldSpace = camera.getModelMatrix() * entityPlaneInCameraSpace;
// Queue the position update (as a relative movement)
}
void SceneManager::queueTransformUpdates(EntityId* entities, math::mat4* transforms, int numEntities)
void SceneManager::queueTransformUpdates(EntityId *entities, math::mat4 *transforms, int numEntities)
{
std::lock_guard lock(_mutex);
for(int i= 0; i < numEntities; i++) {
for (int i = 0; i < numEntities; i++)
{
auto entity = entities[i];
const auto &pos = _transformUpdates.find(entity);
if (pos == _transformUpdates.end())
@@ -2279,112 +2302,117 @@ namespace thermion
}
}
EntityId SceneManager::createGeometry(
float *vertices,
uint32_t numVertices,
float *normals,
uint32_t numNormals,
float *uvs,
uint32_t numUvs,
uint16_t *indices,
uint32_t numIndices,
filament::RenderableManager::PrimitiveType primitiveType,
filament::MaterialInstance* materialInstance,
bool keepData)
{
auto geometry = std::make_unique<CustomGeometry>(vertices, numVertices, normals, numNormals, uvs, numUvs, indices, numIndices, primitiveType, _engine);
auto entity = utils::EntityManager::get().create();
RenderableManager::Builder builder(1);
builder.boundingBox(geometry->getBoundingBox())
.geometry(0, primitiveType, geometry->vertexBuffer(), geometry->indexBuffer(), 0, numIndices)
.culling(true)
.receiveShadows(true)
.castShadows(true);
filament::Material *mat = nullptr;
if (!materialInstance) {
Log("Using default ubershader material");
filament::gltfio::MaterialKey config;
memset(&config, 0, sizeof(config)); // Initialize all bits to zero
config.unlit = false;
config.doubleSided = false;
config.useSpecularGlossiness = false;
config.alphaMode = filament::gltfio::AlphaMode::OPAQUE;
config.hasBaseColorTexture = numUvs > 0;
config.hasClearCoat = false;
config.hasClearCoatNormalTexture = false;
config.hasClearCoatRoughnessTexture = false;
config.hasEmissiveTexture = false;
config.hasIOR = false;
config.hasMetallicRoughnessTexture = false;
config.hasNormalTexture = false;
config.hasOcclusionTexture = false;
config.hasSheen = false;
config.hasSheenColorTexture = false;
config.hasSheenRoughnessTexture = false;
config.hasSpecularGlossinessTexture = false;
config.hasTextureTransforms = false;
config.hasTransmission = false;
config.hasTransmissionTexture = false;
config.hasVolume = false;
config.hasVolumeThicknessTexture = false;
config.baseColorUV = 0;
config.hasVertexColors = false;
config.hasVolume = false;
materialInstance = createUbershaderMaterialInstance(config);
if(!materialInstance) {
Log("Failed to create material instance");
return Entity::smuggle(Entity());
}
}
// Set up texture and sampler if UVs are available
if (uvs != nullptr && numUvs > 0)
EntityId SceneManager::createGeometry(
float *vertices,
uint32_t numVertices,
float *normals,
uint32_t numNormals,
float *uvs,
uint32_t numUvs,
uint16_t *indices,
uint32_t numIndices,
filament::RenderableManager::PrimitiveType primitiveType,
filament::MaterialInstance *materialInstance,
bool keepData)
{
// Create a default white texture
static constexpr uint32_t textureSize = 1;
static constexpr uint32_t white = 0x00ffffff;
Texture* texture = Texture::Builder()
.width(textureSize)
.height(textureSize)
.levels(1)
.format(Texture::InternalFormat::RGBA8)
.build(*_engine);
auto geometry = std::make_unique<CustomGeometry>(vertices, numVertices, normals, numNormals, uvs, numUvs, indices, numIndices, primitiveType, _engine);
_textures.insert(texture);
filament::backend::PixelBufferDescriptor pbd(&white, 4, Texture::Format::RGBA, Texture::Type::UBYTE);
texture->setImage(*_engine, 0, std::move(pbd));
auto entity = utils::EntityManager::get().create();
RenderableManager::Builder builder(1);
// Create a sampler
TextureSampler sampler(TextureSampler::MinFilter::NEAREST, TextureSampler::MagFilter::NEAREST);
sampler.setWrapModeS(TextureSampler::WrapMode::REPEAT);
sampler.setWrapModeT(TextureSampler::WrapMode::REPEAT);
builder.boundingBox(geometry->getBoundingBox())
.geometry(0, primitiveType, geometry->vertexBuffer(), geometry->indexBuffer(), 0, numIndices)
.culling(true)
.receiveShadows(true)
.castShadows(true);
// Set the texture and sampler to the material instance
materialInstance->setParameter("baseColorMap", texture, sampler);
filament::Material *mat = nullptr;
if (!materialInstance)
{
Log("Using default ubershader material");
filament::gltfio::MaterialKey config;
memset(&config, 0, sizeof(config)); // Initialize all bits to zero
config.unlit = false;
config.doubleSided = false;
config.useSpecularGlossiness = false;
config.alphaMode = filament::gltfio::AlphaMode::OPAQUE;
config.hasBaseColorTexture = numUvs > 0;
config.hasClearCoat = false;
config.hasClearCoatNormalTexture = false;
config.hasClearCoatRoughnessTexture = false;
config.hasEmissiveTexture = false;
config.hasIOR = false;
config.hasMetallicRoughnessTexture = false;
config.hasNormalTexture = false;
config.hasOcclusionTexture = false;
config.hasSheen = false;
config.hasSheenColorTexture = false;
config.hasSheenRoughnessTexture = false;
config.hasSpecularGlossinessTexture = false;
config.hasTextureTransforms = false;
config.hasTransmission = false;
config.hasTransmissionTexture = false;
config.hasVolume = false;
config.hasVolumeThicknessTexture = false;
config.baseColorUV = 0;
config.hasVertexColors = false;
config.hasVolume = false;
materialInstance = createUbershaderMaterialInstance(config);
if (!materialInstance)
{
Log("Failed to create material instance");
return Entity::smuggle(Entity());
}
}
// Set up texture and sampler if UVs are available
if (uvs != nullptr && numUvs > 0)
{
if(materialInstance->getMaterial()->hasParameter("baseColorMap")) {
// Create a default white texture
static constexpr uint32_t textureSize = 1;
static constexpr uint32_t white = 0x00ffffff;
Texture *texture = Texture::Builder()
.width(textureSize)
.height(textureSize)
.levels(1)
.format(Texture::InternalFormat::RGBA8)
.build(*_engine);
_textures.insert(texture);
filament::backend::PixelBufferDescriptor pbd(&white, 4, Texture::Format::RGBA, Texture::Type::UBYTE);
texture->setImage(*_engine, 0, std::move(pbd));
// Create a sampler
TextureSampler sampler(TextureSampler::MinFilter::NEAREST, TextureSampler::MagFilter::NEAREST);
sampler.setWrapModeS(TextureSampler::WrapMode::REPEAT);
sampler.setWrapModeT(TextureSampler::WrapMode::REPEAT);
// Set the texture and sampler to the material instance
materialInstance->setParameter("baseColorMap", texture, sampler);
}
}
builder.material(0, materialInstance);
builder.build(*_engine, entity);
_scene->addEntity(entity);
auto entityId = Entity::smuggle(entity);
_geometry.emplace(entityId, std::move(geometry));
return entityId;
}
builder.material(0, materialInstance);
builder.build(*_engine, entity);
_scene->addEntity(entity);
auto entityId = Entity::smuggle(entity);
_geometry.emplace(entityId, std::move(geometry));
return entityId;
}
MaterialInstance* SceneManager::getMaterialInstanceAt(EntityId entityId, int materialIndex) {
MaterialInstance *SceneManager::getMaterialInstanceAt(EntityId entityId, int materialIndex)
{
auto entity = Entity::import(entityId);
const auto &rm = _engine->getRenderableManager();
auto renderableInstance = rm.getInstance(entity);
@@ -2436,7 +2464,7 @@ EntityId SceneManager::createGeometry(
materialInstance->setParameter(property, value);
}
void SceneManager::setMaterialProperty(EntityId entityId, int materialIndex, const char *property, filament::math::float4& value)
void SceneManager::setMaterialProperty(EntityId entityId, int materialIndex, const char *property, filament::math::float4 &value)
{
auto entity = Entity::import(entityId);
const auto &rm = _engine->getRenderableManager();
@@ -2453,17 +2481,20 @@ EntityId SceneManager::createGeometry(
Log("Parameter %s not found", property);
return;
}
materialInstance->setParameter(property, filament::math::float4 { value.x, value.y, value.z, value.w });
materialInstance->setParameter(property, filament::math::float4{value.x, value.y, value.z, value.w});
}
void SceneManager::destroy(MaterialInstance* instance) {
void SceneManager::destroy(MaterialInstance *instance)
{
_engine->destroy(instance);
}
MaterialInstance* SceneManager::createUbershaderMaterialInstance(filament::gltfio::MaterialKey config) {
filament::gltfio::UvMap uvmap {};
auto * materialInstance = _ubershaderProvider->createMaterialInstance(&config, &uvmap);
if(!materialInstance) {
MaterialInstance *SceneManager::createUbershaderMaterialInstance(filament::gltfio::MaterialKey config)
{
filament::gltfio::UvMap uvmap{};
auto *materialInstance = _ubershaderProvider->createMaterialInstance(&config, &uvmap);
if (!materialInstance)
{
Log("Invalid material configuration");
return nullptr;
}
@@ -2473,44 +2504,58 @@ EntityId SceneManager::createGeometry(
return materialInstance;
}
MaterialInstance* SceneManager::createUnlitMaterialInstance() {
MaterialInstance *SceneManager::createUnlitFixedSizeMaterialInstance()
{
auto instance = _gizmoMaterial->createInstance();
instance->setParameter("scale", 1.0f);
return instance;
}
MaterialInstance *SceneManager::createUnlitMaterialInstance()
{
UvMap uvmap;
auto instance = _unlitMaterialProvider->createMaterialInstance(nullptr, &uvmap);
instance->setParameter("uvScale", filament::math::float2 { 1.0f, 1.0f });
instance->setParameter("uvScale", filament::math::float2{1.0f, 1.0f});
_materialInstances.push_back(instance);
return instance;
}
Camera* SceneManager::createCamera() {
Camera *SceneManager::createCamera()
{
auto entity = EntityManager::get().create();
auto camera = _engine->createCamera(entity);
_cameras.push_back(camera);
return camera;
}
void SceneManager::destroyCamera(Camera* camera) {
void SceneManager::destroyCamera(Camera *camera)
{
auto entity = camera->getEntity();
_engine->destroyCameraComponent(entity);
_engine->getEntityManager().destroy(entity);
auto it = std::find(_cameras.begin(), _cameras.end(), camera);
if(it != _cameras.end()) {
if (it != _cameras.end())
{
_cameras.erase(it);
}
}
size_t SceneManager::getCameraCount() {
size_t SceneManager::getCameraCount()
{
return _cameras.size() + 1;
}
Camera* SceneManager::getCameraAt(size_t index) {
if(index == 0) {
Camera *SceneManager::getCameraAt(size_t index)
{
if (index == 0)
{
return _mainCamera;
}
if(index - 1 > _cameras.size() - 1) {
if (index - 1 > _cameras.size() - 1)
{
return nullptr;
}
return _cameras[index-1];
return _cameras[index - 1];
}
} // namespace thermion