Adding ViroKit. Needs AWSCore :(

This commit is contained in:
John Lyon-Smith
2018-03-27 17:46:15 -07:00
parent 2ab15e7dc1
commit 02e06dface
844 changed files with 86921 additions and 21 deletions

View File

@@ -0,0 +1,915 @@
//
// VRONode.h
// ViroRenderer
//
// Created by Raj Advani on 11/15/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VRONode_h
#define VRONode_h
#include <memory>
#include <stack>
#include <vector>
#include <string>
#include <set>
#include <atomic>
#include <algorithm>
#include <functional>
#include "optional.hpp"
#include "VROMatrix4f.h"
#include "VROQuaternion.h"
#include "VRORenderContext.h"
#include "VRODriver.h"
#include "VRORenderParameters.h"
#include "VROAnimatable.h"
#include "VROBoundingBox.h"
#include "VROSortKey.h"
#include "VROLog.h"
#include "VROEventDelegate.h"
#include "VROSound.h"
#include "VROFrustumBoxIntersectionMetadata.h"
#include "VROThreadRestricted.h"
#include "VROPhysicsBody.h"
class VROGeometry;
class VROLight;
class VROScene;
class VROAction;
class VROTexture;
class VROPortal;
class VRONodeCamera;
class VROHitTestResult;
class VROConstraint;
class VROExecutableAnimation;
class VROTransformDelegate;
class VROTransaction;
class VRORenderMetadata;
class VROParticleEmitter;
extern bool kDebugSortOrder;
extern const std::string kDefaultNodeTag;
enum class VRONodeType {
Normal,
Portal,
PortalFrame,
};
enum class VROSilhouetteMode {
Flat, // Render silhouettes with constant lighting, no textures
Textured, // Render silhouettes with constant lighting and textures
};
enum class VRODragType {
FixedDistance, // Drags objects with a fixed distance to camera/controller/etc.
FixedToWorld, // Currently available to AR only. Attempts to drag object w.r.t. the real world.
};
class VRONode : public VROAnimatable, public VROThreadRestricted {
public:
static void resetDebugSortIndex();
#pragma mark - Initialization
/*
Default constructor.
*/
VRONode();
/*
Copy constructor. This copies the node but *not* the underlying
geometries or lights. Instead, these are shared by reference with the
copied node. Additionally, this constructor will not copy child nodes.
To copy child nodes recursively, invoke the clone() function.
*/
VRONode(const VRONode &node);
virtual ~VRONode();
/*
Delete any rendering resources. Invoked prior to destruction, on the
rendering thread.
Recurses down the tree.
*/
virtual void deleteGL();
/*
Copy constructor that recursively copies all child nodes. This copies
the node but *not* the underlying geometries or lights. Instead, these
are shared by reference with the copied node.
*/
std::shared_ptr<VRONode> clone();
/*
Get a unique ID for this VRONode.
*/
int getUniqueID() { return _uniqueID; }
#pragma mark - Render Cycle
/*
Recursive function that recomputes the transforms of this node. This includes:
_computedTransform,
_computedRotation,
_computedPosition,
_computedBoundingBox
*/
void computeTransforms(VROMatrix4f parentTransform, VROMatrix4f parentRotation);
/*
Sets both the local position and rotation of this node in terms of world coordinates.
A computeTransform pass is then performed to update the node's bounding boxes
and as well as its child's node transforms recursively.
*/
void setWorldTransform(VROVector3f finalPosition, VROQuaternion finalRotation);
/*
Update the visibility status of this node, using the camera in the current render
context. This will update the _visible flag. Recurses to children.
*/
void updateVisibility(const VRORenderContext &context);
/*
Update the particle emitters attached to this node. Recurses to children.
*/
void updateParticles(const VRORenderContext &context);
/*
Recursively applies transformation constraints (e.g. billboarding) to this node
and its children.
*/
void applyConstraints(const VRORenderContext &context, VROMatrix4f parentTransform,
bool parentUpdated);
/*
Recursively sets the atomic properties computed during a render pass. Should be
called after the computation occurs.
*/
void setAtomicRenderProperties();
/*
Update the position of each light in this node, and add to the outLights vector.
Recurses down the tree.
*/
void collectLights(std::vector<std::shared_ptr<VROLight>> *outLights);
/*
Recursively updates the sort keys of this node, preparing this node and its children
for rendering. This method also computes non-transform-related parameters for each
node (opacity, lights, etc.) that are required prior to render, and outputs metadata
about the forthcoming render to VRORenderMetadata.
Note: this method and getSortKeys() *only* apply to visible nodes. Invisible nodes
are skipped.
*/
void updateSortKeys(uint32_t depth,
VRORenderParameters &params,
std::shared_ptr<VRORenderMetadata> &metadata,
const VRORenderContext &context,
std::shared_ptr<VRODriver> &driver);
/*
Get the sort keys for all visible nodes in this portal. Stops the search
when we reach the hit of the scene graph or hit another portal.
*/
void getSortKeysForVisibleNodes(std::vector<VROSortKey> *outKeys);
/*
Render the given element of this node's geometry, using its latest computed transforms.
*/
void render(int elementIndex,
std::shared_ptr<VROMaterial> &material,
const VRORenderContext &context,
std::shared_ptr<VRODriver> &driver);
/*
Recursively render this node and all of its children, with full texture
and lighting.
Note: this method does not intelligently batch or sort. It is is less efficient
than directly calling render(..) above after proper sorting.
*/
void render(const VRORenderContext &context, std::shared_ptr<VRODriver> &driver);
/*
Recursively render this the silhouette of this node and all of its children.
Lighting is fixed at constant, and the given material is used for all elements.
If mode is set to Textured, then textures will be bound. This method is typically
used to render to the stencil or depth buffers only.
The filter is used to only render the silhouettes of specific objects. Returns
true on each node to render, false to not. Either way we continue down the tree
recursively.
*/
void renderSilhouettes(std::shared_ptr<VROMaterial> &material, VROSilhouetteMode mode,
std::function<bool(const VRONode&)> filter,
const VRORenderContext &context, std::shared_ptr<VRODriver> &driver);
/*
This function recomputes this node's transform before recomputing its umbrella bounding box
using its parent's last computed transform.
*/
void recomputeUmbrellaBoundingBox();
#pragma mark - Geometry
void setGeometry(std::shared_ptr<VROGeometry> geometry) {
passert_thread();
_geometry = geometry;
}
std::shared_ptr<VROGeometry> getGeometry() const {
return _geometry;
}
#pragma mark - Camera
void setCamera(std::shared_ptr<VRONodeCamera> camera) {
passert_thread();
_camera = camera;
}
const std::shared_ptr<VRONodeCamera> &getCamera() const {
return _camera;
}
#pragma mark - Transforms
VROVector3f getComputedPosition() const;
VROMatrix4f getComputedRotation() const;
VROMatrix4f getComputedTransform() const;
VROVector3f getPosition() const {
return _position;
}
VROVector3f getScale() const {
return _scale;
}
VROQuaternion getRotation() const {
return _rotation;
}
VROVector3f getRotationEuler() const {
return _euler;
}
/*
The following are atomic, updated once per frame on the rendering thread. They can
be accessed safely from any thread to get an up-to-date state of the transform.
*/
VROMatrix4f getLastWorldTransform() const;
VROVector3f getLastWorldPosition() const;
VROVector3f getLastLocalPosition() const;
VROVector3f getLastLocalScale() const;
VROQuaternion getLastLocalRotation() const;
VROBoundingBox getLastUmbrellaBoundingBox() const;
/*
Set the rotation, position, or scale. Animatable.
*/
void setRotation(VROQuaternion rotation);
void setPosition(VROVector3f position);
void setScale(VROVector3f scale);
void setTransformDelegate(std::shared_ptr<VROTransformDelegate> delegate);
/*
Notifies attached transform delegate, if any, that a position change had occurred.
*/
void notifyTransformUpdate(bool forced);
/*
Set the rotation as a vector of Euler angles. Using this method
will update the Euler angles stored internally in a predictable
way. Setting rotation by quaternion updates Euler angles in an
unpredictable way (i.e. the quaternion axis may change).
*/
void setRotationEuler(VROVector3f euler);
/*
These piecewise setters are used in order to change one axis
only, without altering the remaining axes. Useful when animating
across multiple axes across separate calls. Animatable.
*/
void setPositionX(float x);
void setPositionY(float y);
void setPositionZ(float z);
void setScaleX(float x);
void setScaleY(float y);
void setScaleZ(float z);
void setRotationEulerX(float radians);
void setRotationEulerY(float radians);
void setRotationEulerZ(float radians);
/*
Pivot points define the center for rotation and scale. For example,
by translating the rotation pivot, you can use rotation to rotate an
object about a faraway point. By translating the scale pivot, you can
scale an object relative to its corner, instead of its center. Not
animatable.
*/
void setRotationPivot(VROMatrix4f pivot);
void setScalePivot(VROMatrix4f pivot);
#pragma mark - Render Settings
std::string getName() const {
return _name;
}
void setName(std::string name) {
_name = name;
}
float getOpacity() const {
return _opacity;
}
void setOpacity(float opacity);
virtual bool isHidden() const {
return _hidden;
}
virtual void setHidden(bool hidden);
int getRenderingOrder() const {
return _renderingOrder;
}
void setRenderingOrder(int renderingOrder) {
_renderingOrder = renderingOrder;
}
bool isHierarchicalRendering() const {
return _hierarchicalRendering;
}
void setHierarchicalRendering(bool hierarchicalRendering) {
_hierarchicalRendering = hierarchicalRendering;
}
/*
Returns true if this node was found visible during the last call to
computeVisibility(). If a node is not visible, that means none of its
children are visible either (we use the umbrella bounding box for
visibility tests).
*/
bool isVisible() const {
return _visible;
}
/*
Debug function to count the number of visible nodes (including this
node if visible, then recursively descending from this node's children)
since the last call to computeVisibility().
*/
int countVisibleNodes() const;
#pragma mark - Particle Emitters
void setParticleEmitter(std::shared_ptr<VROParticleEmitter> emitter);
void removeParticleEmitter();
std::shared_ptr<VROParticleEmitter> getParticleEmitter() const;
#pragma mark - Lights
void addLight(std::shared_ptr<VROLight> light) {
passert_thread();
_lights.push_back(light);
}
void removeLight(std::shared_ptr<VROLight> light) {
passert_thread();
_lights.erase(
std::remove_if(_lights.begin(), _lights.end(),
[light](std::shared_ptr<VROLight> candidate) {
return candidate == light;
}), _lights.end());
}
void removeAllLights() {
passert_thread();
_lights.clear();
}
std::vector<std::shared_ptr<VROLight>> &getLights() {
return _lights;
}
const std::vector<std::shared_ptr<VROLight>> &getComputedLights() const {
return _computedLights;
}
uint32_t getComputedLightsHash() const {
return _computedLightsHash;
}
void setLightReceivingBitMask(int bitMask, bool recursive = false) {
_lightReceivingBitMask = bitMask;
if (recursive) {
for (std::shared_ptr<VRONode> &child : _subnodes) {
child->setLightReceivingBitMask(bitMask, recursive);
}
}
}
int getLightReceivingBitMask() const {
return _lightReceivingBitMask;
}
void setShadowCastingBitMask(int bitMask, bool recursive = false) {
_shadowCastingBitMask = bitMask;
if (recursive) {
for (std::shared_ptr<VRONode> &child : _subnodes) {
child->setShadowCastingBitMask(bitMask, recursive);
}
}
}
int getShadowCastingBitMask() const {
return _shadowCastingBitMask;
}
#pragma mark - Sounds
void addSound(std::shared_ptr<VROSound> sound) {
passert_thread();
if (sound->getType() == VROSoundType::Spatial) {
_sounds.push_back(sound);
}
}
void removeSound(std::shared_ptr<VROSound> sound) {
passert_thread();
_sounds.erase(
std::remove_if(_sounds.begin(), _sounds.end(),
[sound](std::shared_ptr<VROSound> candidate) {
return candidate == sound;
}), _sounds.end());
}
void removeAllSounds() {
passert_thread();
_sounds.clear();
}
#pragma mark - Scene Graph
void addChildNode(std::shared_ptr<VRONode> node);
void removeFromParentNode();
/*
Return a copy of the subnode list.
*/
std::vector<std::shared_ptr<VRONode>> getChildNodes() const;
/*
Remove all children from this node.
*/
void removeAllChildren();
/*
Return the parent node. Null if this node is root or does not have a parent.
*/
std::shared_ptr<VRONode> getParentNode() const {
return _supernode.lock();
}
/*
Get the parent scene of this VRONode. If this node is not attached to the
scene graph, this will return null.
*/
std::shared_ptr<VROScene> getScene() const {
return _scene.lock();
}
/*
Set the parent scene of this node. Internal use only.
*/
void setScene(std::shared_ptr<VROScene> scene, bool recursive);
/*
Returns the type of this node. Faster then dynamic_cast.
*/
VRONodeType getType() const {
return _type;
}
/*
Get the nearest portal that's an ancestor of this node. Returns null if this is
the root node.
*/
const std::shared_ptr<VROPortal> getParentPortal() const;
/*
Get the nearest child portals of this node. This recurses down the graph in all
directions, stopping whenever we hit a portal or the end of the graph.
*/
void getChildPortals(std::vector<std::shared_ptr<VROPortal>> *outPortals) const;
#pragma mark - Actions and Animations
/*
Actions enable open-ended and fully customizable manipulation of nodes over successive
frames.
*/
void runAction(std::shared_ptr<VROAction> action);
void removeAction(std::shared_ptr<VROAction> action);
void removeAllActions();
/*
Animations enable structured manipulation of nodes over successive frames. They can
be as simple interpolating batches of properties over time, or as complex as full
skeletal animation.
These methods take a key parameter. Keys identify animations that run together in
a single transaction; e.g., there can be multiple animations with a single key.
removeAnimation will remove *all* animations with the given key.
*/
void addAnimation(std::string key, std::shared_ptr<VROExecutableAnimation> animation);
void removeAnimation(std::string key);
/*
Get the keys for all animations in this node. If recursive is true, will search
down the hierarchy as well.
*/
std::set<std::string> getAnimationKeys(bool recursive);
/*
Retrieve all animations with the given key, as a single, composite executable animation.
If recursive is true, then this will return a new parallel VROAnimationChain that
contains every animation in this node and every animation in any subnode that shares
the same key.
For example, if the animation 'Take 001' contains a torso animation and an arm animation,
both will be returned in a single animation group.
*/
std::shared_ptr<VROExecutableAnimation> getAnimation(std::string key, bool recursive);
/*
Remove all animations from this node.
*/
void removeAllAnimations();
/*
Triggered when the animation running this animatable node completes.
*/
void onAnimationFinished();
#pragma mark - Events
VROBoundingBox getBoundingBox() const;
VROBoundingBox getUmbrellaBoundingBox() const;
std::vector<VROHitTestResult> hitTest(const VROCamera &camera, VROVector3f origin, VROVector3f ray,
bool boundsOnly = false);
void setSelectable(bool selectable) {
_selectable = selectable;
}
void setEventDelegate(std::shared_ptr<VROEventDelegate> delegate) {
passert_thread();
_eventDelegateWeak = delegate;
}
std::shared_ptr<VROEventDelegate> getEventDelegate() {
if (_eventDelegateWeak.expired()){
return nullptr;
}
return _eventDelegateWeak.lock();
}
bool isSelectable() const {
return _selectable;
}
void setIgnoreEventHandling(bool canHandle) {
_ignoreEventHandling = canHandle;
}
bool getIgnoreEventHandling() const {
return _ignoreEventHandling;
}
void setTag(std::string tag) {
_tag = tag;
}
std::string getTag() const {
return _tag;
}
void setHighAccuracyGaze(bool enabled);
bool getHighAccuracyGaze() const {
return _highAccuracyGaze;
}
void setIsBeingDragged(bool isDragging) {
std::shared_ptr<VROPhysicsBody> physicsBody = getPhysicsBody();
if (physicsBody != nullptr) {
physicsBody->setKinematicDrag(isDragging);
}
}
void setDragType(VRODragType dragType) {
_dragType = dragType;
}
VRODragType getDragType() {
return _dragType;
}
bool isAnimatingDrag() {
return _isAnimatingDrag;
}
void setIsAnimatingDrag(bool isAnimatingDrag) {
_isAnimatingDrag = isAnimatingDrag;
}
std::shared_ptr<VROTransaction> getDragAnimation() {
return _dragAnimation;
}
void setDragAnimation(std::shared_ptr<VROTransaction> dragAnimation) {
_dragAnimation = dragAnimation;
}
#pragma mark - Constraints
void addConstraint(std::shared_ptr<VROConstraint> constraint);
void removeConstraint(std::shared_ptr<VROConstraint> constraint);
void removeAllConstraints();
#pragma mark - Physics
std::shared_ptr<VROPhysicsBody> initPhysicsBody(VROPhysicsBody::VROPhysicsBodyType type,
float mass,
std::shared_ptr<VROPhysicsShape> shape);
std::shared_ptr<VROPhysicsBody> getPhysicsBody() const;
void clearPhysicsBody();
protected:
VRONodeType _type;
/*
The node's parent and children.
*/
std::vector<std::shared_ptr<VRONode>> _subnodes;
std::weak_ptr<VRONode> _supernode;
/*
The VROScene to which this node belongs.
*/
std::weak_ptr<VROScene> _scene;
/*
The geometry in the node. Null means the node has no geometry.
*/
std::shared_ptr<VROGeometry> _geometry;
/*
True if this node was found visible during the last call to computeVisibility().
*/
bool _visible;
/*
Last frame that this node was visited during sorting. Used for graph traversal.
*/
int _lastVisitedRenderingFrame;
private:
/*
Name for debugging.
*/
std::string _name;
/*
Unique identifier.
*/
int _uniqueID;
/*
Lights, sound, particles, and camera.
*/
std::vector<std::shared_ptr<VROLight>> _lights;
std::vector<std::shared_ptr<VROSound>> _sounds;
std::shared_ptr<VROParticleEmitter> _particleEmitter;
std::shared_ptr<VRONodeCamera> _camera;
/*
Scale and position.
*/
VROVector3f _scale;
VROVector3f _position;
/*
Rotation is stored as a quaternion, but we also maintain euler angles
for use in animation (since we cannot additively rotate by reading euler
angles from a quaternion and writing them again).
*/
VROQuaternion _rotation;
VROVector3f _euler;
/*
Pivots define the center of the rotation and scale operations.
Declared optional becuase they are not always used, and we can optimize
them away when not used.
*/
std::experimental::optional<VROMatrix4f> _rotationPivot;
std::experimental::optional<VROMatrix4f> _rotationPivotInverse;
std::experimental::optional<VROMatrix4f> _scalePivot;
std::experimental::optional<VROMatrix4f> _scalePivotInverse;
/*
User-defined rendering order for this node.
*/
int _renderingOrder;
/*
Parameters computed by descending down the tree. These are updated whenever
any parent or this node itself is updated. For example, computedOpacity is
the opacity of this node multiplied by the opacities of all this node's
ancestors. Similarly, computedTransform is the full cascaded transformation
matrix for the node.
computedRotation only takes into account rotations (not scale or translation).
computedLights are the lights that influence this node, based on distance from
the light and light attenuation, unrelated to the scene graph (e.g. the lights
in _computedLights may belong to any node in the scene).
*/
VROMatrix4f _computedTransform;
VROMatrix4f _computedInverseTransposeTransform;
VROMatrix4f _computedRotation;
float _computedOpacity;
std::vector<std::shared_ptr<VROLight>> _computedLights;
uint32_t _computedLightsHash;
VROVector3f _computedPosition;
std::weak_ptr<VROTransformDelegate> _transformDelegate;
/*
Because _computedTransform is computed multiple times during a single render, storing
the last fully computed transform is necessary to retrieve a "valid" computedTransform.
We also store the last *local* position, scale, and rotation atomically.
*/
std::atomic<VROMatrix4f> _lastComputedTransform;
std::atomic<VROVector3f> _lastComputedPosition;
std::atomic<VROVector3f> _lastPosition;
std::atomic<VROVector3f> _lastScale;
std::atomic<VROQuaternion> _lastRotation;
std::atomic<VROBoundingBox> _lastUmbrellaBoundingBox;
/*
The transformed bounding box containing this node's geometry. The
_umbrellaBoundingBox encompasses not only this geometry, but the geometries
of all this node's children.
*/
VROBoundingBox _computedBoundingBox;
VROBoundingBox _umbrellaBoundingBox;
VROFrustumBoxIntersectionMetadata _umbrellaBoxMetadata;
/*
True if this node is hidden. Hidden nodes are not rendered, and do not
respond to tap events. Hiding a node within an animation results in a
fade-out animation. The _opacityFromHiddenFlag is the opacity as derived
from _hidden: 0.0 if _hidden is true, 1.0 if _hidden is false, or somewhere
in-between during animation.
*/
bool _hidden;
float _opacityFromHiddenFlag;
/*
The opacity of the node (0.0 is transparent, 1.0 is opaque). When opacity
drops below a threshold value, the node is hidden. This opacity is set by
the user.
*/
float _opacity;
/*
True if this node is selectable by hit testing. Defaults to true.
*/
bool _selectable;
/*
True if this node is set to ignore all events fired from VROBaseInputController.
*/
bool _ignoreEventHandling;
/*
Delegate through which events are notified from the VROEventManager.
*/
std::weak_ptr<VROEventDelegate> _eventDelegateWeak;
/*
True if we want to perform more accurate hit testing against this node's geometry
rather than its bounding box.
*/
bool _highAccuracyGaze;
/*
Active actions on this node.
*/
std::vector<std::shared_ptr<VROAction>> _actions;
/*
Animations stored with this node.
*/
std::map<std::string, std::vector<std::shared_ptr<VROExecutableAnimation>>> _animations;
/*
Constraints on the node, which can modify the node's transformation matrix.
*/
std::vector<std::shared_ptr<VROConstraint>> _constraints;
/*
True indicates that this node's descendants (children, grand-children, and so on)
should be rendered by order of their scene graph depth. Useful when rendering
2D layouts like flexbox views. Defaults to false.
*/
bool _hierarchicalRendering;
/*
The drag type to use for this VRONode.
*/
VRODragType _dragType;
/*
Whether or not a drag is still being animated (used only if _dragType == VRODragType::FixedToWorld
*/
bool _isAnimatingDrag;
/*
The VROTransaction representing the animation from dragging while _dragType == VRODragType::FixedToWorld.
*/
std::shared_ptr<VROTransaction> _dragAnimation;
#pragma mark - Private
/*
Recursively set the visibility of this node and all of its children to the
given value.
*/
void setVisibilityRecursive(bool visible);
/*
Recursively expand the given bounding box by this node's _computedBoundingBox.
*/
void computeUmbrellaBounds(VROBoundingBox *bounds) const;
/*
Compute the transform for this node, taking into the account the parent's transform.
Updates all related variables:
_computedTransform
_computedPosition
_computedBoundingBox
*/
void doComputeTransform(VROMatrix4f parentTransform);
/*
Action processing: execute all current actions and remove those that are
expired.
*/
void processActions();
/*
Get the animations in this node under the given key, and add them to the
given vector.
*/
void getAnimations(std::vector<std::shared_ptr<VROExecutableAnimation>> &animations,
std::string key, bool recursive);
/*
Get the keys of all animations in this node, and add them to the given set.
*/
void getAnimationKeys(std::set<std::string> &animations, bool recursive);
/*
Hit test helper functions.
*/
void hitTest(const VROCamera &camera, VROVector3f origin, VROVector3f ray,
bool boundsOnly, std::vector<VROHitTestResult> &results);
bool hitTestGeometry(VROVector3f origin, VROVector3f ray, VROMatrix4f transform);
/*
The light and shadow bit masks. These are logically ANDed with each light's
influence bit mask.
If the result is non-zero for the light bit mask, then the light will illuminate
the node. If the result is zero, then this node will be excluded from the light's
illumination, including receipt of that light's shadows.
If the AND result is non-zero for the shadow casting bit map, then the node
will be cast shadows from the light (e.g. it will be rendered to that light's
shadow map). If the result is zero, it will not cast shadows from said light.
These both default to 1.
*/
int _lightReceivingBitMask;
int _shadowCastingBitMask;
/*
Physics rigid body that if defined, drives and sets the transformations of this node.
*/
std::shared_ptr<VROPhysicsBody> _physicsBody;
/*
Non-unique tag identifier representing this node. Defaults to kDefaultNodeTag.
*/
std::string _tag = kDefaultNodeTag;
};
#endif /* VRONode_h */