image_framework_ymj/include/open3d/3rdparty/filament/TransformManager.h

256 lines
9.7 KiB
C
Raw Normal View History

2024-12-06 16:25:16 +08:00
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_TRANSFORMMANAGER_H
#define TNT_FILAMENT_TRANSFORMMANAGER_H
#include <filament/FilamentAPI.h>
#include <utils/compiler.h>
#include <utils/EntityInstance.h>
#include <math/mathfwd.h>
#include <iterator>
namespace utils {
class Entity;
} // namespace utils
namespace filament {
class FTransformManager;
/**
* TransformManager is used to add transform components to entities.
*
* A Transform component gives an entity a position and orientation in space in the coordinate
* space of its parent transform. The TransformManager takes care of computing the world-space
* transform of each component (i.e. its transform relative to the root).
*
* Creation and destruction
* ========================
*
* A transform component is created using TransformManager::create() and destroyed by calling
* TransformManager::destroy().
*
* ~~~~~~~~~~~{.cpp}
* filament::Engine* engine = filament::Engine::create();
* utils::Entity object = utils::EntityManager.get().create();
*
* auto& tcm = engine->getTransformManager();
*
* // create the transform component
* tcm.create(object);
*
* // set its transform
* auto i = tcm.getInstance(object);
* tcm.setTransform(i, mat4f::translation({ 0, 0, -1 }));
*
* // destroy the transform component
* tcm.destroy(object);
* ~~~~~~~~~~~
*
*/
class UTILS_PUBLIC TransformManager : public FilamentAPI {
public:
using Instance = utils::EntityInstance<TransformManager>;
class children_iterator : std::iterator<std::forward_iterator_tag, Instance> {
friend class FTransformManager;
TransformManager const& mManager;
Instance mInstance;
children_iterator(TransformManager const& mgr, Instance instance) noexcept
: mManager(mgr), mInstance(instance) { }
public:
children_iterator& operator++();
children_iterator operator++(int) { // NOLINT
children_iterator ret(*this);
++(*this);
return ret;
}
bool operator == (const children_iterator& other) const noexcept {
return mInstance == other.mInstance;
}
bool operator != (const children_iterator& other) const noexcept {
return mInstance != other.mInstance;
}
value_type operator*() const { return mInstance; }
};
/**
* Returns whether a particular Entity is associated with a component of this TransformManager
* @param e An Entity.
* @return true if this Entity has a component associated with this manager.
*/
bool hasComponent(utils::Entity e) const noexcept;
/**
* Gets an Instance representing the transform component associated with the given Entity.
* @param e An Entity.
* @return An Instance object, which represents the transform component associated with the Entity e.
* @note Use Instance::isValid() to make sure the component exists.
* @see hasComponent()
*/
Instance getInstance(utils::Entity e) const noexcept;
/**
* Creates a transform component and associate it with the given entity.
* @param entity An Entity to associate a transform component to.
* @param parent The Instance of the parent transform, or Instance{} if no parent.
* @param localTransform The transform to initialize the transform component with.
* This is always relative to the parent.
*
* If this component already exists on the given entity, it is first destroyed as if
* destroy(utils::Entity e) was called.
*
* @see destroy()
*/
void create(utils::Entity entity, Instance parent, const math::mat4f& localTransform);
void create(utils::Entity entity, Instance parent = {});
/**
* Destroys this component from the given entity, children are orphaned.
* @param e An entity.
*
* @note If this transform had children, these are orphaned, which means their local
* transform becomes a world transform. Usually it's nonsensical. It's recommended to make
* sure that a destroyed transform doesn't have children.
*
* @see create()
*/
void destroy(utils::Entity e) noexcept;
/**
* Re-parents an entity to a new one.
* @param i The instance of the transform component to re-parent
* @param newParent The instance of the new parent transform
* @attention It is an error to re-parent an entity to a descendant and will cause undefined behaviour.
* @see getInstance()
*/
void setParent(Instance i, Instance newParent) noexcept;
/**
* Returns the parent of a transform component, or the null entity if it is a root.
* @param i The instance of the transform component to query.
*/
utils::Entity getParent(Instance i) const noexcept;
/**
* Returns the number of children of a transform component.
* @param i The instance of the transform component to query.
* @return The number of children of the queried component.
*/
size_t getChildCount(Instance i) const noexcept;
/**
* Gets a list of children for a transform component.
*
* @param i The instance of the transform component to query.
* @param children Pointer to array-of-Entity. The array must have at least "count" elements.
* @param count The maximum number of children to retrieve.
* @return The number of children written to the pointer.
*/
size_t getChildren(Instance i, utils::Entity* children, size_t count) const noexcept;
/**
* Returns an iterator to the Instance of the first child of the given parent.
*
* @param parent Instance of the parent
* @return A forward iterator pointing to the first child of the given parent.
*
* A child_iterator can only safely be dereferenced if it's different from getChildrenEnd(parent)
*/
children_iterator getChildrenBegin(Instance parent) const noexcept;
/**
* Returns an undreferencable iterator representing the end of the children list
*
* @param parent Instance of the parent
* @return A forward iterator.
*
* This iterator cannot be dereferenced
*/
children_iterator getChildrenEnd(Instance parent) const noexcept;
/**
* Sets a local transform of a transform component.
* @param ci The instance of the transform component to set the local transform to.
* @param localTransform The local transform (i.e. relative to the parent).
* @see getTransform()
* @attention This operation can be slow if the hierarchy of transform is too deep, and this
* will be particularly bad when updating a lot of transforms. In that case,
* consider using openLocalTransformTransaction() / commitLocalTransformTransaction().
*/
void setTransform(Instance ci, const math::mat4f& localTransform) noexcept;
/**
* Returns the local transform of a transform component.
* @param ci The instance of the transform component to query the local transform from.
* @return The local transform of the component (i.e. relative to the parent). This always
* returns the value set by setTransform().
* @see setTransform()
*/
const math::mat4f& getTransform(Instance ci) const noexcept;
/**
* Return the world transform of a transform component.
* @param ci The instance of the transform component to query the world transform from.
* @return The world transform of the component (i.e. relative to the root). This is the
* composition of this component's local transform with its parent's world transform.
* @see setTransform()
*/
const math::mat4f& getWorldTransform(Instance ci) const noexcept;
/**
* Opens a local transform transaction. During a transaction, getWorldTransform() can
* return an invalid transform until commitLocalTransformTransaction() is called. However,
* setTransform() will perform significantly better and in constant time.
*
* This is useful when updating many transforms and the transform hierarchy is deep (say more
* than 4 or 5 levels).
*
* @note If the local transform transaction is already open, this is a no-op.
*
* @see commitLocalTransformTransaction(), setTransform()
*/
void openLocalTransformTransaction() noexcept;
/**
* Commits the currently open local transform transaction. When this returns, calls
* to getWorldTransform() will return the proper value.
*
* @attention failing to call this method when done updating the local transform will cause
* a lot of rendering problems. The system never closes the transaction
* automatically.
*
* @note If the local transform transaction is not open, this is a no-op.
*
* @see openLocalTransformTransaction(), setTransform()
*/
void commitLocalTransformTransaction() noexcept;
};
} // namespace filament
#endif // TNT_TRANSFORMMANAGER_H