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,104 @@
//
// VROARAnchor.h
// ViroKit
//
// Created by Raj Advani on 6/6/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARAnchor_h
#define VROARAnchor_h
#include "VROMatrix4f.h"
#include "VROVector3f.h"
#include "VROQuaternion.h"
#include "VROARNode.h"
/*
Anchors are real world objects detected by the AR engine. Each time an
anchor is detected, the VROARSessionDelegate is given an opportunity to
create a VRONode with virtual content to attach to that anchor. The
ARSession will thereafter ensure that the virtual content is fused with
the real-world anchor, thereby enabling applications to 'augment'
reality with virtual content.
For example, if a plane anchor is detected, the can use its corresponding
VRONode to place virtual objects for a table-top game.
Anchors are regularly updated by the AR engine as the characteristics of
the anchor are further refined: for example, the AR engine may start with
an approximation of a surface, and later determine the surface's width and
height.
VROARAnchor is subclassed by specific anchor types; planes, image targets,
etc.
*/
class VROARAnchor {
public:
/*
Create a new anchor.
*/
VROARAnchor() {}
virtual ~VROARAnchor() {}
/*
String representing the ID of the anchor in the underlying platform (ARKit/ARCore).
*/
std::string getId() const {
return _id;
}
void setId(std::string id) {
_id = id;
}
/*
Transformation matrix encoding the position, orientation and scale of the
anchor in world coordinates.
*/
VROMatrix4f getTransform() const {
return _transform;
};
void setTransform(VROMatrix4f transform) {
_transform = transform;
}
/*
The node associated with the anchor. Updated alongside the anchor.
*/
const std::shared_ptr<VROARNode> getARNode() const {
return _node;
}
void setARNode(std::shared_ptr<VROARNode> node) {
_node = node;
updateNodeTransform();
}
/*
Update the anchor's node's transforms given the data in the anchor.
*/
void updateNodeTransform() {
if (_node && !_node->shouldPauseUpdates()) {
VROVector3f scale = getTransform().extractScale();
VROQuaternion rotation = getTransform().extractRotation(scale);
VROVector3f position = getTransform().extractTranslation();
_node->setScale(scale);
_node->setRotation(rotation);
_node->setPosition(position);
}
}
private:
std::string _id;
VROMatrix4f _transform;
/*
The node associated with this anchor.
*/
std::shared_ptr<VROARNode> _node;
};
#endif /* VROARAnchor_h */

View File

@@ -0,0 +1,78 @@
//
// VROARCamera.h
// ViroKit
//
// Created by Raj Advani on 6/6/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARCamera_h
#define VROARCamera_h
#include <stdio.h>
class VROViewport;
class VROMatrix4f;
class VROVector3f;
class VROFieldOfView;
enum class VROARTrackingState {
Unavailable,
Limited,
Normal,
};
/*
Provides reasons for why we are in Limited tracking state.
*/
enum class VROARTrackingStateReason {
None,
ExcessiveMotion,
InsufficientFeatures
};
/*
Contains information about the current camera position and imaging
characteristics. Updated periodically by the VROARSession.
*/
class VROARCamera {
public:
VROARCamera() {}
virtual ~VROARCamera() {}
/*
Get the quality of the tracking. If we are in limited tracking state,
getLimitedTrackingStateReason() will return the reason for this state.
*/
virtual VROARTrackingState getTrackingState() const = 0;
virtual VROARTrackingStateReason getLimitedTrackingStateReason() const = 0;
/*
Get the position and rotation of the user in world space. These values
are derived from the AR camera's extrinsic matrix, acquired via visual and
inertial algorithms. They can be used to construct the view matrix for the
renderer.
*/
virtual VROMatrix4f getRotation() const = 0;
virtual VROVector3f getPosition() const = 0;
/*
Get the projection matrix needed to render a 3D scene to match the image
captured by this AR camera. The returned matrix is a concatenation of the
AR camera's intrinsic matrix (3D space --> 2D space) and the renderer's
orthographic projection matrix (2D space --> normalized device space).
This function should also output the field of view in the provided output
variable.
*/
virtual VROMatrix4f getProjection(VROViewport viewport, float near, float far, VROFieldOfView *outFOV) const = 0;
/*
Get the image size (width, height) for the camera. Stored in the
vector's x and y components.
*/
virtual VROVector3f getImageSize() const = 0;
};
#endif /* VROARCamera_h */

View File

@@ -0,0 +1,124 @@
//
// VROARConstraintMatcher.h
// ViroKit
//
// Created by Andy Chu on 6/16/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARConstraintMatcher_h
#define VROARConstraintMatcher_h
#include "VROARSession.h"
#include <map>
#include <vector>
class VROARAnchor;
class VROARDeclarativeNode;
class VROARConstraintMatcherDelegate;
/*
VROARConstraintMatcher handles matching declarative nodes with anchors that
meet their requirements.
*/
class VROARConstraintMatcher {
public:
VROARConstraintMatcher() {};
virtual ~VROARConstraintMatcher() {};
void addARNode(std::shared_ptr<VROARDeclarativeNode> node);
void removeARNode(std::shared_ptr<VROARDeclarativeNode> node);
void updateARNode(std::shared_ptr<VROARDeclarativeNode> node);
void setDelegate(std::shared_ptr<VROARConstraintMatcherDelegate> delegate);
/*
This function will silently detach all the anchors from the given nodes. This
is currently used when ARScene is being detached.
*/
void detachAllNodes(std::vector<std::shared_ptr<VROARDeclarativeNode>> nodes);
void anchorWasDetected(std::shared_ptr<VROARAnchor> anchor);
void anchorDidUpdate(std::shared_ptr<VROARAnchor> anchor);
void anchorWasRemoved(std::shared_ptr<VROARAnchor> anchor);
private:
// Map between a string ID and the VROARAnchor with that ID.
std::map<std::string, std::shared_ptr<VROARAnchor>> _nativeAnchorMap;
std::shared_ptr<VROARAnchor> getAnchorFromId(std::string id);
std::weak_ptr<VROARConstraintMatcherDelegate> _delegate;
// Anchors without an associated Node
std::vector<std::shared_ptr<VROARAnchor>> _detachedAnchors;
// Nodes w/o id's without an associated Anchor
std::vector<std::shared_ptr<VROARDeclarativeNode>> _detachedNodes;
// Nodes w/ id's without an associated Anchor
std::vector<std::shared_ptr<VROARDeclarativeNode>> _detachedNodesWithID;
/*
Returns a detached anchor that is suitable for the given node.
*/
std::shared_ptr<VROARAnchor> findDetachedAnchor(std::shared_ptr<VROARDeclarativeNode> node);
/*
Returns a detached node satisfied by the given anchor.
*/
std::shared_ptr<VROARDeclarativeNode> findDetachedNode(std::shared_ptr<VROARAnchor> anchor);
/*
This function either attaches the detached node to an anchor or adds the node to
_detachedNodes.
*/
void processDetachedNode(std::shared_ptr<VROARDeclarativeNode> node);
/*
This function either attaches the detached anchor to an node or adds the anchor to
_detachedAnchors.
*/
void processDetachedAnchor(std::shared_ptr<VROARAnchor> anchor);
/*
This function handles the logic and updating required for attaching a node to an anchor
*/
void attachNodeToAnchor(std::shared_ptr<VROARDeclarativeNode> node, std::shared_ptr<VROARAnchor> anchor);
/*
This function handles detaching a node from an anchor
*/
void detachNodeFromAnchor(std::shared_ptr<VROARAnchor> anchor);
/*
Functions to abstract out the notification of the delegate
*/
void notifyAnchorWasAttached(std::shared_ptr<VROARAnchor> anchor);
void notifyAnchorWasDetached(std::shared_ptr<VROARAnchor> anchor);
/*
Helper functions to remove the given objects from the _detached* vectors
*/
void removeFromDetachedList(std::shared_ptr<VROARDeclarativeNode> node);
void removeFromDetachedList(std::shared_ptr<VROARAnchor> anchor);
};
class VROARConstraintMatcherDelegate {
public:
/*
Invoked when an anchor is attached to node.
*/
virtual void anchorWasAttached(std::shared_ptr<VROARAnchor> anchor) = 0;
/*
Invoked when an anchor is detached from a node.
*/
virtual void anchorWasDetached(std::shared_ptr<VROARAnchor> anchor) = 0;
};
#endif /* VROARConstraintMatcher_h */

View File

@@ -0,0 +1,43 @@
//
// VROARDeclarativeImageNode.h
// ViroKit
//
// Created by Andy Chu on 1/30/18.
// Copyright © 2018 Viro Media. All rights reserved.
//
#ifndef VROARDeclarativeImageNode_h
#define VROARDeclarativeImageNode_h
#include "VROARImageAnchor.h"
#include "VROARDeclarativeNode.h"
#include "VROARImageTarget.h"
class VROARDeclarativeImageNode : public VROARDeclarativeNode {
public:
VROARDeclarativeImageNode() {}
virtual ~VROARDeclarativeImageNode() {}
/*
Returns whether or not the given VROARAnchor fulfills this image marker's requirements.
*/
bool hasRequirementsFulfilled(std::shared_ptr<VROARAnchor> candidate) {
std::shared_ptr<VROARImageAnchor> imageAnchor = std::dynamic_pointer_cast<VROARImageAnchor>(candidate);
// a VROARImageAnchor matches an VROAR*ImageNode if they share the same VROImageTarget
return imageAnchor && _imageTarget == imageAnchor->getImageTarget();
}
void setImageTarget(std::shared_ptr<VROARImageTarget> imageTarget) {
_imageTarget = imageTarget;
}
std::shared_ptr<VROARImageTarget> getImageTarget() {
return _imageTarget;
}
private:
std::shared_ptr<VROARImageTarget> _imageTarget;
};
#endif /* VROARDeclarativeImageNode_h */

View File

@@ -0,0 +1,130 @@
//
// VROARDeclarativeNode.h
// ViroKit
//
// Created by Raj Advani on 11/3/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARDeclarativeNode_h
#define VROARDeclarativeNode_h
#include "VROARNode.h"
#include "VROARDeclarativeNodeDelegate.h"
/*
Declarative AR nodes implement a *declarative* system for working with AR anchors.
Instead of waiting for an anchor to appear and implementing the control flow yourself,
you can use these nodes to simply specify the constraints of the anchor you desire,
and the system will find the first available ARAnchor that meets those constraints
and assign them to the node.
For example, you can use VROARDeclarativePlane to specify the minimum width and height
of the desired plane on which to play a table-top game.
*/
class VROARDeclarativeNode : public VROARNode {
public:
VROARDeclarativeNode() : _isAttached(false), _internalHidden(false) {
}
virtual ~VROARDeclarativeNode() {}
/*
Returns true if the given anchor fulfills the requirements for this declarative
AR node.
*/
virtual bool hasRequirementsFulfilled(std::shared_ptr<VROARAnchor> candidate) = 0;
/*
Set an anchor ID to override the constraint system. The VROARConstraintMatcher will
first match nodes to anchors that have matching IDs, prior to checking constraints.
*/
void setAnchorId(std::string anchorId) {
_anchorId = anchorId;
}
std::string getAnchorId() {
return _anchorId;
}
/*
Set a delegate to respond to the node being attached/detached/updated.
*/
void setARNodeDelegate(std::shared_ptr<VROARDeclarativeNodeDelegate> delegate) {
_arNodeDelegate = delegate;
}
std::shared_ptr<VROARDeclarativeNodeDelegate> getARNodeDelegate() {
return _arNodeDelegate.lock();
}
/*
Declarative AR nodes are kept hidden until they find a matching anchor.
*/
virtual void setHidden(bool hidden) {
_internalHidden = hidden;
VRONode::setHidden(!_isAttached || _internalHidden);
}
/*
Set whether this declarative AR node is attached to an anchor.
*/
void setAttached(bool attached) {
_isAttached = attached;
// set hidden again when the _isAttached changes.
setHidden(_internalHidden);
}
/*
Invoked internally by the VROARConstraintMatcher.
*/
virtual void onARAnchorAttached() {
setAttached(true);
std::shared_ptr<VROARDeclarativeNodeDelegate> delegate = getARNodeDelegate();
if (delegate) {
delegate->onARAnchorAttached(getAnchor());
}
}
virtual void onARAnchorUpdated() {
std::shared_ptr<VROARDeclarativeNodeDelegate> delegate = getARNodeDelegate();
if (delegate) {
delegate->onARAnchorUpdated(getAnchor());
}
}
virtual void onARAnchorRemoved() {
setAttached(false);
std::shared_ptr<VROARDeclarativeNodeDelegate> delegate = getARNodeDelegate();
if (delegate) {
delegate->onARAnchorRemoved();
}
}
private:
/*
It is possible to override the declarative system and directly set an anchor ID.
The VROARConstraintMatcher will first match nodes to anchors that have matching
IDs, prior to checking constraints.
*/
std::string _anchorId;
/*
True if the VROARConstraintMatcher has found a match for this node.
*/
bool _isAttached;
/*
Declarative AR nodes are kept hidden until they find a matching anchor. This way
their contents are not displayed to the user until they've been correctly anchored
to the real world. This is achieved by overriding VRONode::setHidden().
*/
bool _internalHidden;
/*
Delegate to respond to this node being attached / detached.
*/
std::weak_ptr<VROARDeclarativeNodeDelegate> _arNodeDelegate;
};
#endif /* VROARDeclarativeNode_h */

View File

@@ -0,0 +1,38 @@
//
// VROARNodeDelegate.h
// ViroKit
//
// Created by Andy Chu on 7/3/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARNodeDelegate_h
#define VROARNodeDelegate_h
class VROARAnchor;
class VROARDeclarativeNodeDelegate {
public:
VROARDeclarativeNodeDelegate() {}
virtual ~VROARDeclarativeNodeDelegate() {}
/*
Notifies the delegate that the node was attached to the given anchor. The
delegate should NOT hold onto the anchor.
*/
virtual void onARAnchorAttached(std::shared_ptr<VROARAnchor> anchor) = 0;
/*
Notifies the delegate that the underlying anchor was updated. The
delegate should NOT hold onto the anchor.
*/
virtual void onARAnchorUpdated(std::shared_ptr<VROARAnchor> anchor) = 0;
/*
Notifies the delegate that the underlying anchor was removed.
*/
virtual void onARAnchorRemoved() = 0;
};
#endif /* VROARNodeDelegate_h */

View File

@@ -0,0 +1,115 @@
//
// VROARPlaneNode.h
// ViroRenderer
//
// Created by Andy Chu on 6/17/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARPlaneNode_h
#define VROARPlaneNode_h
#include "VROARPlaneAnchor.h"
#include "VROARDeclarativeNode.h"
/*
This class is a nice container that associates the virtual (VRONode), the real (VROARAnchor) and
the constraints that bind them together.
*/
class VROARDeclarativePlane : public VROARDeclarativeNode {
public:
VROARDeclarativePlane(float minWidth, float minHeight, VROARPlaneAlignment alignment) :
_minWidth(minWidth),
_minHeight(minHeight),
_alignment(alignment)
{}
virtual ~VROARDeclarativePlane() {}
/*
Returns whether or not the given VROARAnchor fulfills this plane's requirements.
*/
bool hasRequirementsFulfilled(std::shared_ptr<VROARAnchor> candidate) {
std::shared_ptr<VROARPlaneAnchor> planeAnchor = std::dynamic_pointer_cast<VROARPlaneAnchor>(candidate);
if (!planeAnchor) {
return false;
}
if (planeAnchor->getExtent().x < _minWidth || planeAnchor->getExtent().z < _minHeight) {
return false;
}
/*
The below alignment logic follows this table:
Anchor Alignment | Android - ViroARPlane | iOS - ViroARPlane
Horizontal | n/a | Horizontal, Up, Down
Up | Up, Horizontal | n/a
Down | Down, Horizontal | n/a
Vertical | n/a | Vertical
*/
#if VRO_PLATFORM_IOS
// For iOS, there's no differentiation between upwards and downwards plane, so
// they'll match "Horizontal" alignments.
switch (_alignment) {
case VROARPlaneAlignment::Horizontal:
case VROARPlaneAlignment::HorizontalUpward:
case VROARPlaneAlignment::HorizontalDownward:
if (planeAnchor->getAlignment() != VROARPlaneAlignment::Horizontal) {
return false;
}
break;
case VROARPlaneAlignment::Vertical:
if (planeAnchor->getAlignment() != VROARPlaneAlignment::Vertical) {
return false;
}
break;
}
#elif VRO_PLATFORM_ANDROID
// Android really only has 2 types of plane alignments, up and down.
switch (planeAnchor->getAlignment()) {
case VROARPlaneAlignment::HorizontalUpward:
if (_alignment != VROARPlaneAlignment::Horizontal
&& _alignment != VROARPlaneAlignment::HorizontalUpward) {
return false;
}
break;
case VROARPlaneAlignment::HorizontalDownward:
if (_alignment != VROARPlaneAlignment::Horizontal
&& _alignment != VROARPlaneAlignment::HorizontalDownward) {
return false;
}
}
#endif
return true;
}
void setMinWidth(float minWidth) {
_minWidth = minWidth;
}
float getMinWidth() {
return _minWidth;
}
void setMinHeight(float minHeight) {
_minHeight = minHeight;
}
float getMinHeight() {
return _minHeight;
}
void setAlignment(VROARPlaneAlignment alignment) {
_alignment = alignment;
}
VROARPlaneAlignment getAlignment() {
return _alignment;
}
private:
float _minWidth;
float _minHeight;
VROARPlaneAlignment _alignment;
};
#endif /* VROARPlaneNode_h */

View File

@@ -0,0 +1,88 @@
//
// VROARDeclarativeSession.h
// ViroKit
//
// Created by Raj Advani on 11/3/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARDeclarativeSession_h
#define VROARDeclarativeSession_h
#include "VROARSession.h"
#include "VROARConstraintMatcher.h"
class VROARScene;
class VROARDeclarativeSessionDelegate;
/*
VROARDeclarativeSession controls the 'declarative' style API for using AR.
In this paradigm, instead of directly responding to ARSessionDelegate methods,
the user simply specifies the requirements of the ARAnchor they're interested in
via a VROARDeclarativeNode, and then the user can immediately start adding
content to that node. Once an ARAnchor meeting the constraints is found, the
node (and all of its content) will be made visible.
This largely simplifies the state handling with AR objects. To use this:
1. Create the VROARDeclarativeNode and set its requirements (e.g. min width and
height for a plane).
2. Add the node to the VROARDeclarativeSession via addARNode. This adds the node
to the declarative session where it find an anchor that matches with it.
3. Add the node to the VROARScene via VROARScene::addNode. This physically adds
the node to the scene.
To use the declarative session you must first call VROARScene->initDeclarativeSession().
*/
class VROARDeclarativeSession : public VROARSessionDelegate, public VROARConstraintMatcherDelegate,
public std::enable_shared_from_this<VROARDeclarativeSession> {
public:
VROARDeclarativeSession();
virtual ~VROARDeclarativeSession();
void init();
void setDelegate(std::shared_ptr<VROARDeclarativeSessionDelegate> delegate);
void setARSession(std::shared_ptr<VROARSession> session);
void addARImageTarget(std::shared_ptr<VROARImageTarget> target);
void removeARImageTarget(std::shared_ptr<VROARImageTarget> target);
void addARNode(std::shared_ptr<VROARDeclarativeNode> plane);
void removeARNode(std::shared_ptr<VROARDeclarativeNode> plane);
void updateARNode(std::shared_ptr<VROARDeclarativeNode> plane);
void sceneWillAppear();
void sceneWillDisappear();
// VROARSessionDelegate methods
virtual void anchorWasDetected(std::shared_ptr<VROARAnchor> anchor);
virtual void anchorWillUpdate(std::shared_ptr<VROARAnchor> anchor);
virtual void anchorDidUpdate(std::shared_ptr<VROARAnchor> anchor);
virtual void anchorWasRemoved(std::shared_ptr<VROARAnchor> anchor);
// VROARConstraintMatcherDelegate methods
void anchorWasAttached(std::shared_ptr<VROARAnchor> anchor);
void anchorWasDetached(std::shared_ptr<VROARAnchor> anchor);
private:
std::weak_ptr<VROARSession> _arSession;
std::weak_ptr<VROARDeclarativeSessionDelegate> _delegate;
std::shared_ptr<VROARConstraintMatcher> _constraintMatcher;
std::vector<std::shared_ptr<VROARDeclarativeNode>> _nodes;
std::vector<std::shared_ptr<VROARImageTarget>> _imageTargets;
};
class VROARDeclarativeSessionDelegate {
public:
virtual void anchorWasDetected(std::shared_ptr<VROARAnchor> anchor) = 0;
virtual void anchorWillUpdate(std::shared_ptr<VROARAnchor> anchor) = 0;
virtual void anchorDidUpdate(std::shared_ptr<VROARAnchor> anchor) = 0;
virtual void anchorWasRemoved(std::shared_ptr<VROARAnchor> anchor) = 0;
};
#endif /* VROARDeclarativeSession_h */

View File

@@ -0,0 +1,90 @@
//
// VROARFrame.h
// ViroKit
//
// Created by Raj Advani on 6/6/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARFrame_h
#define VROARFrame_h
#include "VROARPointCloud.h"
#include <memory>
#include <vector>
#include <set>
class VROARCamera;
class VROARAnchor;
class VROARHitTestResult;
class VROMatrix4f;
enum class VROARHitTestResultType;
enum class VROCameraOrientation;
/*
The continual output of a VROARSession. These frames contain the current camera
video image, camera parameters, and updated anchors.
*/
class VROARFrame {
public:
VROARFrame() {}
virtual ~VROARFrame() {}
/*
Get the timestamp, in seconds.
*/
virtual double getTimestamp() const = 0;
/*
Contains information about the camera position, orientation, and imaging
parameters for this frame.
*/
virtual const std::shared_ptr<VROARCamera> &getCamera() const = 0;
/*
Perform a hit test on the given point in the viewport. The coordinate
system is viewport pixels (e.g. the coordinate system in which
VROViewport is defined).
*/
virtual std::vector<VROARHitTestResult> hitTest(int x, int y, std::set<VROARHitTestResultType> types) = 0;
/*
Returns the affine transform to move from viewport space to camera
image space. Camera image space is the texture coordinate space of
the camera's image, ranging from (0,0) at the upper left to (1,1) on
the lower right. Viewport space is the coordinate space of the current
viewport, taking into account the current orientation.
To render the camera image, either this transform should be applied to
the camera background's texture coordinates, or the *inverse* of this
transform should be applied to the camera background's vertices.
This ensures the camera image maps correctly to the current viewport and
orientation.
*/
virtual VROMatrix4f getViewportToCameraImageTransform() = 0;
/*
Return the estimated intensity of ambient light in the physical scene.
*/
virtual float getAmbientLightIntensity() const = 0;
/*
Return the estimate color temperature of ambient light in the physical scene.
*/
virtual float getAmbientLightColorTemperature() const = 0;
/*
Get all the anchors representing tracked positions and objects in the
scene.
*/
virtual const std::vector<std::shared_ptr<VROARAnchor>> &getAnchors() const = 0;
/*
Retrieves the point cloud from this frame.
*/
virtual std::shared_ptr<VROARPointCloud> getPointCloud() = 0;
};
#endif /* VROARFrame_h */

View File

@@ -0,0 +1,83 @@
//
// VROARHitTestResult.h
// ViroRenderer
//
// Created by Raj Advani on 6/12/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARHitTestResult_h
#define VROARHitTestResult_h
#include <stdio.h>
#include "VROARAnchor.h"
/*
Types of hit test results:
ExistingPlaneUsingExtent: Hit test found a plane for which we have an anchor,
and the hit location was within the plane's estimated
extent.
ExistingPlane: Hit test found a plane for which we have an anchor, but our hit
test did not take into account the estimated extent. The hit point
may be outside the actual extent of the surface.
EstimatedHorizontalPlane: Hit test found a plane, but one for which we have no
anchor.
Feature Point: Hit test found a point that the AR session believes is part of a
continuous surface. This surface may not be horizontal.
*/
enum class VROARHitTestResultType {
ExistingPlaneUsingExtent,
ExistingPlane,
EstimatedHorizontalPlane,
FeaturePoint,
};
/*
Return value of AR hit tests. AR hit tests determine anchors or
less defined features the user hits in the camera view.
*/
class VROARHitTestResult {
public:
VROARHitTestResult(VROARHitTestResultType type, std::shared_ptr<VROARAnchor> anchor, float distance,
VROMatrix4f worldTransform, VROMatrix4f localTransform) :
_type(type), _anchor(anchor), _distance(distance), _worldTransform(worldTransform), _localTransform(localTransform) {}
/*
Get the type of hit test result.
*/
VROARHitTestResultType getType() const { return _type; }
/*
Return the anchor associated with the hit test, if any.
*/
const std::shared_ptr<VROARAnchor> getAnchor() const { return _anchor; }
/*
Get the distance from the camera to the hit test result.
*/
float getDistance() const { return _distance; }
/*
Get the position and orientation of the hit test result surface, in world coordinates.
*/
VROMatrix4f getWorldTransform() const { return _worldTransform; }
/*
Get the position and orientation of the hit test result surface, in the coordinate
space of the anchor. Undefined if there is no anchor associated with this result.
*/
VROMatrix4f getLocalTransform() const { return _localTransform; }
private:
VROARHitTestResultType _type;
std::shared_ptr<VROARAnchor> _anchor;
float _distance;
VROMatrix4f _worldTransform;
VROMatrix4f _localTransform;
};
#endif /* VROARHitTestResult_h */

View File

@@ -0,0 +1,32 @@
//
// VROARImageAnchor.h
// ViroKit
//
// Created by Andy Chu on 1/30/18.
// Copyright © 2018 Viro Media. All rights reserved.
//
#ifndef VROARImageAnchor_h
#define VROARImageAnchor_h
#include "VROARAnchor.h"
#include "VROARImageTarget.h"
class VROARImageAnchor : public VROARAnchor {
public:
VROARImageAnchor(std::shared_ptr<VROARImageTarget> imageTarget) :
_imageTarget(imageTarget) {}
virtual ~VROARImageAnchor() {}
std::shared_ptr<VROARImageTarget> getImageTarget() {
return _imageTarget;
}
private:
std::shared_ptr<VROARImageTarget> _imageTarget;
};
#endif /* VROARImageAnchor_h */

View File

@@ -0,0 +1,45 @@
//
// VROARImageTarget.h
// ViroKit
//
// Created by Andy Chu on 1/30/18.
// Copyright © 2018 Viro Media. All rights reserved.
//
#ifndef VROARImageTarget_h
#define VROARImageTarget_h
#include <memory>
#include "VROARSession.h"
/*
The orientation of the given target image.
*/
enum class VROImageOrientation {
Up,
Down,
Left,
Right
};
class VROARImageTarget {
public:
VROARImageTarget() {}
virtual ~VROARImageTarget() {}
virtual void initWithTrackingImpl(VROImageTrackingImpl impl) = 0;
void setAnchor(std::shared_ptr<VROARAnchor> anchor) {
_anchor = anchor;
}
std::shared_ptr<VROARAnchor> getAnchor() {
return _anchor.lock();
}
private:
std::weak_ptr<VROARAnchor> _anchor;
};
#endif /* VROARImageTarget_h */

View File

@@ -0,0 +1,46 @@
//
// VROARImageTargetiOS.h
// ViroKit
//
// Created by Andy Chu on 1/30/18.
// Copyright © 2018 Viro Media. All rights reserved.
//
#ifndef VROARImageTargetiOS_h
#define VROARImageTargetiOS_h
#include "VROARImageTarget.h"
#include <UIKit/UIKit.h>
@class ARReferenceImage;
class VROARImageTargetiOS : public VROARImageTarget {
public:
VROARImageTargetiOS(UIImage *sourceImage, VROImageOrientation orientation, float physicalWidth);
virtual ~VROARImageTargetiOS();
void initWithTrackingImpl(VROImageTrackingImpl impl);
UIImage *getSourceImage() {
return _sourceImage;
}
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110300
ARReferenceImage *getARReferenceImage();
#endif
private:
UIImage *_sourceImage;
VROImageOrientation _orientation;
float _physicalWidth;
VROImageTrackingImpl _currentImpl;
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110300
ARReferenceImage *_referenceImage;
#endif
};
#endif /* VROARImageTargetiOS_h */

View File

@@ -0,0 +1,46 @@
//
// VROARNode.h
// ViroKit
//
// Created by Andy Chu on 6/16/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARNode_h
#define VROARNode_h
#include "VRONode.h"
class VROARAnchor;
/*
ARNode is a specialized Node that corresponds to a detected ARAnchor. Each ARNode is
continually updated to stay in sync with its corresponding ARAnchor: if the anchor's
position, orientation, or other detected properties change, the ARNode will be changed
as well.
*/
class VROARNode : public VRONode {
public:
VROARNode() : _pauseUpdates(false) {}
virtual ~VROARNode() {}
void setAnchor(std::shared_ptr<VROARAnchor> anchor) {
_anchor = anchor;
}
std::shared_ptr<VROARAnchor> getAnchor() {
return _anchor.lock();
}
void setPauseUpdates(bool pauseUpdates);
bool shouldPauseUpdates() {
return _pauseUpdates;
}
protected:
std::weak_ptr<VROARAnchor> _anchor;
bool _pauseUpdates;
};
#endif /* VROARNode_h */

View File

@@ -0,0 +1,46 @@
//
// VROARNodeDelegateiOS.h
// ViroKit
//
// Created by Andy Chu on 7/3/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARNodeDelegateiOS_h
#define VROARNodeDelegateiOS_h
#import "VROARDeclarativeNodeDelegate.h"
#import <Foundation/Foundation.h>
@protocol VROARNodeDelegateProtocol<NSObject>
@required
- (void)onARAnchorAttached:(std::shared_ptr<VROARAnchor>) anchor;
- (void)onARAnchorUpdated:(std::shared_ptr<VROARAnchor>) anchor;
- (void)onARAnchorRemoved;
@end
class VROARNodeDelegateiOS : public VROARDeclarativeNodeDelegate {
public:
VROARNodeDelegateiOS(id<VROARNodeDelegateProtocol> delegate) :
_delegate(delegate) {}
virtual ~VROARNodeDelegateiOS() {}
virtual void onARAnchorAttached(std::shared_ptr<VROARAnchor> anchor) {
[_delegate onARAnchorAttached:anchor];
}
virtual void onARAnchorUpdated(std::shared_ptr<VROARAnchor> anchor) {
[_delegate onARAnchorUpdated:anchor];
}
virtual void onARAnchorRemoved() {
[_delegate onARAnchorRemoved];
}
private:
__weak id<VROARNodeDelegateProtocol> _delegate;
};
#endif /* VROARNodeDelegateiOS_h */

View File

@@ -0,0 +1,84 @@
//
// VROARPlaneAnchor.h
// ViroRenderer
//
// Created by Raj Advani on 6/11/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARPlaneAnchor_h
#define VROARPlaneAnchor_h
#include "VROARAnchor.h"
#include "VROVector3f.h"
enum class VROARPlaneAlignment {
Horizontal = 0x1,
HorizontalUpward = 0x11,
HorizontalDownward = 0x101,
Vertical = 0x10,
NonHorizontal = 0x0
};
/*
Anchor representing a planar surface.
*/
class VROARPlaneAnchor : public VROARAnchor {
public:
VROARPlaneAnchor() {}
virtual ~VROARPlaneAnchor() {}
/*
The approximate alignment of the detected plane.
*/
VROARPlaneAlignment getAlignment() const {
return _alignment;
}
void setAlignment(VROARPlaneAlignment alignment) {
_alignment = alignment;
}
/*
The center point of the detected plane. Relative to the parent
anchor position.
*/
VROVector3f getCenter() const {
return _center;
}
void setCenter(VROVector3f center) {
_center = center;
}
/*
The width and length of the detected plane.
*/
VROVector3f getExtent() const {
return _extent;
}
void setExtent(VROVector3f extent) {
_extent = extent;
}
private:
/*
The approximate alignment of the detected plane.
*/
VROARPlaneAlignment _alignment;
/*
The center point of the detected plane. Relative to the parent
anchor position.
*/
VROVector3f _center;
/*
The width and length of the detected plane.
*/
VROVector3f _extent;
};
#endif /* VROARPlaneAnchor_h */

View File

@@ -0,0 +1,48 @@
//
// VROARPointCloud.h
// ViroKit
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARPointCloud_h
#define VROARPointCloud_h
#include <cstdint>
#include <vector>
class VROVector4f;
class VROMatrix3f;
// TODO: possible need to guard uint64_t usage with #ifdef UINT64_MAX, seems fine on iOS/Android
class VROARPointCloud {
public:
VROARPointCloud() {}
VROARPointCloud(std::vector<VROVector4f> points, std::vector<uint64_t> identifiers) :
_points(points),
_identifiers(identifiers) {}
~VROARPointCloud() {}
/*
Retrieves the point that make up this point cloud. Note: the 4th value in the
vector is a "confidence" value only available on Android.
*/
std::vector<VROVector4f> getPoints() {
return _points;
}
/*
Retrieves the identifiers corresponding to each point. Note: iOS only (it's empty
on Android).
*/
std::vector<uint64_t> getIdentifiers() {
return _identifiers;
}
private:
std::vector<VROVector4f> _points;
std::vector<uint64_t> _identifiers; // used only on iOS (Android does not provide identifiers).
};
#endif /* VROARPointCloud_h */

View File

@@ -0,0 +1,120 @@
//
// VROARScene.h
// ViroKit
//
// Created by Andy Chu on 6/13/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARScene_h
#define VROARScene_h
#include <vector>
#include "VROARSession.h"
#include "VROScene.h"
class VROARAnchor;
class VROARDeclarativeSession;
class VROARImperativeSession;
class VROPointCloudEmitter;
class VROARSceneDelegate {
public:
virtual void onTrackingInitialized() = 0;
virtual void onAmbientLightUpdate(float ambientLightIntensity, float colorTemperature) = 0;
};
class VROARScene : public VROScene {
public:
VROARScene() :
_hasTrackingInitialized(false),
_displayPointCloud(false),
_pointCloudSurfaceScale(VROVector3f(.01, .01, 1)),
_pointCloudMaxPoints(500) {
_pointCloudNode = std::make_shared<VRONode>();
_detectionTypes = { VROAnchorDetection::PlanesHorizontal }; //default is horizontal
};
virtual ~VROARScene();
void initDeclarativeSession();
void initImperativeSession();
std::shared_ptr<VROARSessionDelegate> getSessionDelegate();
void setARSession(std::shared_ptr<VROARSession> arSession);
void setDriver(std::shared_ptr<VRODriver> driver);
/*
Add AR nodes. These are directly added to the root node.
*/
void addNode(std::shared_ptr<VRONode> node);
/*
The set of anchor detection types we want to enable for this scene.
*/
void setAnchorDetectionTypes(std::set<VROAnchorDetection> detectionTypes);
/*
Set true to display/render the point cloud particles.
*/
void displayPointCloud(bool display);
/*
Reset the point cloud surface to the default.
*/
void resetPointCloudSurface();
/*
Set the surface to use for the individual point cloud particles.
*/
void setPointCloudSurface(std::shared_ptr<VROSurface> surface);
/*
Set the scale of the individual point cloud particles.
*/
void setPointCloudSurfaceScale(VROVector3f scale);
/*
Sets the max number of point cloud points to display/render at any one time.
*/
void setPointCloudMaxPoints(int maxPoints);
void setDelegate(std::shared_ptr<VROARSceneDelegate> delegate);
void trackingHasInitialized();
void updateAmbientLight(float intensity, float colorTemperature);
void willAppear();
void willDisappear();
std::shared_ptr<VROARDeclarativeSession> getDeclarativeSession() {
return _declarativeSession;
}
std::shared_ptr<VROARImperativeSession> getImperativeSession() {
return _imperativeSession;
}
private:
std::set<VROAnchorDetection> _detectionTypes;
std::weak_ptr<VROARSession> _arSession;
std::weak_ptr<VRODriver> _driver;
std::shared_ptr<VROARDeclarativeSession> _declarativeSession;
std::shared_ptr<VROARImperativeSession> _imperativeSession;
std::shared_ptr<VRONode> _pointCloudNode;
std::shared_ptr<VROPointCloudEmitter> _pointCloudEmitter;
std::weak_ptr<VROARSceneDelegate> _delegate;
bool _hasTrackingInitialized;
/* Point Cloud Properties */
bool _displayPointCloud;
std::shared_ptr<VROSurface> _pointCloudSurface;
VROVector3f _pointCloudSurfaceScale;
int _pointCloudMaxPoints;
/*
Creates an instance of VROPointCloudEmitter if possible.
*/
std::shared_ptr<VROPointCloudEmitter> createPointCloudEmitter();
};
#endif /* VROARScene_h */

View File

@@ -0,0 +1,25 @@
//
// VROARSceneController.h
// ViroKit
//
// Created by Andy Chu on 6/14/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARSceneController_h
#define VROARSceneController_h
#include "VROSceneController.h"
#include "VROARScene.h"
#include "VROARDeclarativeSession.h"
class VROARSceneController : public VROSceneController {
public:
VROARSceneController();
virtual ~VROARSceneController();
virtual void onSceneWillAppear(VRORenderContext *context, std::shared_ptr<VRODriver> driver);
virtual void onSceneWillDisappear(VRORenderContext *context, std::shared_ptr<VRODriver> driver);
};
#endif /* VROARSceneController_h */

View File

@@ -0,0 +1,59 @@
//
// VROARSceneDelegateiOS.h
// ViroKit
//
// Created by Andy Chu on 7/10/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARSceneDelegateiOS_h
#define VROARSceneDelegateiOS_h
#import "VROARScene.h"
#import "VROARDeclarativeSession.h"
#import <Foundation/Foundation.h>
@protocol VROARSceneDelegateProtocol <NSObject>
@required
- (void)onTrackingInitialized;
- (void)onAmbientLightUpdate:(float)intensity colorTemperature:(float)colorTemperature;
- (void)onAnchorFound:(std::shared_ptr<VROARAnchor>)anchor;
- (void)onAnchorUpdated:(std::shared_ptr<VROARAnchor>)anchor;
- (void)onAnchorRemoved:(std::shared_ptr<VROARAnchor>)anchor;
@end
class VROARSceneDelegateiOS : public VROARSceneDelegate, public VROARDeclarativeSessionDelegate {
public:
VROARSceneDelegateiOS(id<VROARSceneDelegateProtocol> delegate) :
_delegate(delegate) {}
virtual ~VROARSceneDelegateiOS() {}
virtual void onTrackingInitialized() {
[_delegate onTrackingInitialized];
}
virtual void anchorWasDetected(std::shared_ptr<VROARAnchor> anchor) {
[_delegate onAnchorFound:anchor];
}
virtual void anchorWillUpdate(std::shared_ptr<VROARAnchor> anchor) {
}
virtual void anchorDidUpdate(std::shared_ptr<VROARAnchor> anchor) {
[_delegate onAnchorUpdated:anchor];
}
virtual void anchorWasRemoved(std::shared_ptr<VROARAnchor> anchor) {
[_delegate onAnchorRemoved:anchor];
}
virtual void onAmbientLightUpdate(float intensity, float colorTemperature) {
[_delegate onAmbientLightUpdate:intensity colorTemperature:colorTemperature];
}
private:
__weak id<VROARSceneDelegateProtocol> _delegate;
};
#endif /* VROARSceneDelegateiOS_h */

View File

@@ -0,0 +1,253 @@
//
// VROARSession.h
// ViroKit
//
// Created by Raj Advani on 6/6/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARSession_h
#define VROARSession_h
#include <memory>
#include <set>
#include "VROLog.h"
#include "VROMatrix4f.h"
class VROARAnchor;
class VROARFrame;
class VROTexture;
class VROViewport;
class VROScene;
class VROARNode;
class VRONode;
class VROARSessionDelegate;
class VROARImageTarget;
enum class VROCameraOrientation; //defined in VROCameraTexture.h
/*
Determines if the AR session tracks orientation only, or
tracks position and orientation.
*/
enum class VROTrackingType {
DOF3,
DOF6
};
/*
The types of objects the AR session should scan each frame
to detect. A VROARAnchor is created for each detected object.
*/
enum class VROAnchorDetection {
None,
PlanesHorizontal,
PlanesVertical
};
/*
The world alignment chosen at the start of the AR Session.
*/
enum class VROWorldAlignment {
Gravity,
GravityAndHeading,
Camera
};
/*
The video quality that the ARSession should *attempt* to use.
*/
enum class VROVideoQuality {
Low,
High
};
/*
The implementation of image tracking to use.
*/
enum class VROImageTrackingImpl {
ARKit,
Viro // not available for devs to use yet.
};
/*
Manages the device camera and motion tracking for AR.
*/
class VROARSession {
public:
VROARSession(VROTrackingType trackingType, VROWorldAlignment worldAlignment) :
_trackingType(trackingType),
_worldAlignment(worldAlignment),
_imageTrackingImpl(VROImageTrackingImpl::ARKit) {}
virtual ~VROARSession() {}
VROTrackingType getTrackingType() const {
return _trackingType;
}
VROWorldAlignment getWorldAlignment() const {
return _worldAlignment;
}
VROImageTrackingImpl getImageTrackingImpl() const {
return _imageTrackingImpl;
}
/*
The scene associated with this session.
*/
const std::shared_ptr<VROScene> getScene() const {
return _scene;
}
virtual void setScene(std::shared_ptr<VROScene> scene) {
_scene = scene;
}
/*
The delegate set by the application to respond to events from the
AR session.
*/
std::shared_ptr<VROARSessionDelegate> getDelegate() {
return _delegate.lock();
}
virtual void setDelegate(std::shared_ptr<VROARSessionDelegate> delegate) {
_delegate = delegate;
}
/*
Start the session. The session cannot be started until its
scene, viewport, and orientation have been set.
*/
virtual void run() = 0;
/*
Pause the session. No new frames will be created.
*/
virtual void pause() = 0;
/*
Resets the VROARSession depending on the given boolean flags. If no flags
are set to true, then nothing will happen.
*/
virtual void resetSession(bool resetTracking, bool removeAnchors) = 0;
/*
Returns true if at least one frame has been generated.
*/
virtual bool isReady() const = 0;
/*
Set what anchors will be auto-detected by the AR session. Returns true if successful (e.g.
if the device supports these forms of anchor detection).
*/
virtual bool setAnchorDetection(std::set<VROAnchorDetection> types) = 0;
/*
Adds an image target that should be tracked by this session.
*/
virtual void addARImageTarget(std::shared_ptr<VROARImageTarget> target) = 0;
/*
Removes an image target that should no longer be tracked by this session and the
corresponding anchor that matched with the target. If the image target has not
been found yet, then the given anchor should be nullptr
*/
virtual void removeARImageTarget(std::shared_ptr<VROARImageTarget> target) = 0;
/*
Add or remove anchors from the session. These methods are used for
placing anchors that are *not* auto-detected. The AR session will
not keep these anchors up to date; that is the responsibility of the
system that added the anchor.
*/
virtual void addAnchor(std::shared_ptr<VROARAnchor> anchor) = 0;
virtual void removeAnchor(std::shared_ptr<VROARAnchor> anchor) = 0;
/*
Invoke to update the anchor's node with the latest transformation
data contained in the anchor, alerting delegates in the process.
*/
virtual void updateAnchor(std::shared_ptr<VROARAnchor> anchor) = 0;
/*
Invoke each rendering frame. Updates the AR session with the latest
AR data, and returns this in a VROARFrame. The camera background is
updated at this point as well.
*/
virtual std::unique_ptr<VROARFrame> &updateFrame() = 0;
/*
Get the last frame that was generated via updateFrame().
*/
virtual std::unique_ptr<VROARFrame> &getLastFrame() = 0;
/*
Get the background texture for this AR session. The contents of this
texture are updated after each call to updateFrame().
*/
virtual std::shared_ptr<VROTexture> getCameraBackgroundTexture() = 0;
/*
Invoke when the viewport changes. The AR engine may adjust its camera
background and projection matrices in response to a viewport change.
*/
virtual void setViewport(VROViewport viewport) = 0;
/*
Invoke when orientation changes, so the AR engine can make the
necessary adjustments.
*/
virtual void setOrientation(VROCameraOrientation orientation) = 0;
/*
Sets AR world origin to the given transform.
*/
virtual void setWorldOrigin(VROMatrix4f relativeTransform) = 0;
/*
Sets whether or not to enable autofocus.
*/
virtual void setAutofocus(bool enabled) = 0;
/*
Sets the video quality to use.
*/
virtual void setVideoQuality(VROVideoQuality quality) = 0;
private:
VROTrackingType _trackingType;
VROWorldAlignment _worldAlignment;
VROImageTrackingImpl _imageTrackingImpl;
std::shared_ptr<VROScene> _scene;
std::weak_ptr<VROARSessionDelegate> _delegate;
};
class VROARSessionDelegate {
public:
/*
Invoked whenever an anchor is detected by the AR session, or when an
anchor is manually added to the session via addAnchor(). The application
can choose to add a VROARNode to associate virtual content with this
anchor by setting a VROARNode on the anchor.
*/
virtual void anchorWasDetected(std::shared_ptr<VROARAnchor> anchor) = 0;
/*
Invoked just before and after the anchor's node's properties are updated
to match the current state of the anchor.
*/
virtual void anchorWillUpdate(std::shared_ptr<VROARAnchor> anchor) = 0;
virtual void anchorDidUpdate(std::shared_ptr<VROARAnchor> anchor) = 0;
/*
Invoked when an anchor is removed from the AR session, along with its
corresponding node (now detached from the scene).
*/
virtual void anchorWasRemoved(std::shared_ptr<VROARAnchor> anchor) = 0;
};
#endif /* VROARSession_h */

View File

@@ -0,0 +1,43 @@
//
// VROARTransparentShadow.h
// ViroKit
//
// Created by Raj Advani on 8/23/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROARTShadow_h
#define VROARTShadow_h
#include <memory>
class VROMaterial;
class VROShaderModifier;
/*
Apply this to any material to turn it into a "transparent shadow"
material. These materials are transparent but able to receive shadows
from the shadow-mapping system.
They achieve this through a combination of shader modifiers that:
1. Make the color of the surface black, with alpha 0,
2. Increase the alpha if the surface is in shadow.
This is used to cast virtual shadows on real-world scenes.
*/
class VROARShadow {
public:
static void apply(std::shared_ptr<VROMaterial> material);
static void remove(std::shared_ptr<VROMaterial> material);
private:
static std::shared_ptr<VROShaderModifier> createSurfaceModifier();
static std::shared_ptr<VROShaderModifier> createFragmentModifier();
static std::shared_ptr<VROShaderModifier> createLightingModifier();
};
#endif /* VROARShadow_h */

View File

@@ -0,0 +1,191 @@
//
// VROAction.h
// ViroRenderer
//
// Created by Raj Advani on 1/12/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROAction_h
#define VROAction_h
#include <stdio.h>
#include <functional>
#include "VROTime.h"
#include "VROTimingFunction.h"
class VRONode;
static const int VROActionRepeatForever = -1;
enum class VROActionType {
PerFrame,
Timed,
Animated
};
enum class VROActionDurationType {
Count,
Seconds
};
/*
Actions are callbacks that can be set to run on VRONodes. They can
be used to animate properties of nodes, or to set repeating actions.
*/
class VROAction : public std::enable_shared_from_this<VROAction> {
public:
/*
For per-frame actions, the given function will be run once per frame. These will
run either perpetually, or for the given number of frames or actions.
*/
static std::shared_ptr<VROAction> perpetualPerFrameAction(std::function<bool(VRONode *const, float)> action);
static std::shared_ptr<VROAction> repeatedPerFrameActionFrames(std::function<bool(VRONode *const, float)> action, int repeatCount);
static std::shared_ptr<VROAction> repeatedPerFrameActionSeconds(std::function<bool(VRONode *const, float)> action, float duration);
/*
For timed actions, the given function will be run each frame until the given number of
seconds. The function takes a variable t that runs from [0,1] over the course of the duration,
transformed by the provided timing function.
*/
static std::shared_ptr<VROAction> timedAction(std::function<void(VRONode *const, float)> action,
VROTimingFunctionType timingFunction,
float duration);
/*
For animated actions, the given function will be run once, within a VROTransaction configured
to use the given timing function and duration. These are merely helper functions that sit over
the VROTransaction animation framework.
*/
static std::shared_ptr<VROAction> perpetualAnimatedAction(std::function<void(VRONode *const)> action,
VROTimingFunctionType timingFunction,
float duration);
static std::shared_ptr<VROAction> repeatedAnimatedAction(std::function<void(VRONode *const)> action,
VROTimingFunctionType timingFunction,
float duration, int repeatCount);
VROAction(VROActionType type, VROActionDurationType durationType) :
_type(type),
_durationType(durationType),
_executed(false),
_aborted(false)
{}
virtual ~VROAction() {}
VROActionType getType() const {
return _type;
}
float getDuration() const {
return _duration;
}
bool shouldRepeat() const {
if (_aborted) {
return false;
}
else if (_durationType == VROActionDurationType::Count) {
return _repeatCount > 0 || _repeatCount == VROActionRepeatForever;
}
else {
return (VROTimeCurrentSeconds() - _startTime) < _duration;
}
}
/*
Internal: executes the action.
*/
virtual void execute(VRONode *node) = 0;
protected:
VROActionType _type;
VROActionDurationType _durationType;
/*
True after the action has been executed at least once.
*/
bool _executed;
/*
Duration of the action, in seconds. Only valid for animated actions,
defines the duration of *each* repetition of the animation.
*/
float _duration;
/*
The number of frames to repeat this action, or the number of seconds to
repeat the action.
*/
int _repeatCount;
float _repeatDuration;
/*
The time at which the action was first executed.
*/
float _startTime;
/*
True if the action was manually aborted by way of a callback returning
false.
*/
bool _aborted;
/*
Internal: called bfore and after executing the action. Decrements repeat count.
*/
void preExecute(VRONode *node);
void postExecute(VRONode *node);
};
class VROActionPerFrame : public VROAction {
public:
VROActionPerFrame(std::function<bool(VRONode *const, float)> action, VROActionDurationType durationType) :
VROAction(VROActionType::PerFrame, durationType),
_action(action)
{}
virtual ~VROActionPerFrame() {}
virtual void execute(VRONode *node);
private:
std::function<bool(VRONode *const, float)> _action;
};
class VROActionTimed : public VROAction {
public:
VROActionTimed(std::function<void(VRONode *const, float)> action, VROTimingFunctionType timingFunctionType) :
VROAction(VROActionType::Timed, VROActionDurationType::Seconds),
_action(action),
_timingFunction(VROTimingFunction::forType(timingFunctionType))
{}
virtual ~VROActionTimed() {}
virtual void execute(VRONode *node);
private:
std::function<void(VRONode *const, float)> _action;
std::unique_ptr<VROTimingFunction> _timingFunction;
};
class VROActionAnimated : public VROAction {
public:
VROActionAnimated(std::function<void(VRONode *const)> action, VROTimingFunctionType timingFunctionType) :
VROAction(VROActionType::Animated, VROActionDurationType::Count),
_action(action),
_timingFunctionType(timingFunctionType)
{}
virtual ~VROActionAnimated() {}
virtual void execute(VRONode *node);
private:
std::function<void(VRONode *const)> _action;
VROTimingFunctionType _timingFunctionType;
};
#endif /* VROAction_h */

View File

@@ -0,0 +1,72 @@
//
// VROAllocationTracker.h
// ViroRenderer
//
// Created by Raj Advani on 10/21/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef __VROAllocationTracker__
#define __VROAllocationTracker__
#include <iostream>
#define TRACK_MEMORY_ALLOCATIONS 0
#if TRACK_MEMORY_ALLOCATIONS
#define ALLOCATION_TRACKER_SET(x, bytes) VROAllocationTracker::set(VROAllocationBucket::x, bytes)
#define ALLOCATION_TRACKER_ADD(x, bytes) VROAllocationTracker::add(VROAllocationBucket::x, bytes)
#define ALLOCATION_TRACKER_SUB(x, bytes) VROAllocationTracker::subtract(VROAllocationBucket::x, bytes)
#define ALLOCATION_TRACKER_RESIZE(x, bytesOld, bytesNew) VROAllocationTracker::resize(VROAllocationBucket::x, bytesOld, bytesNew)
#define ALLOCATION_TRACKER_PRINT() VROAllocationTracker::print()
#define ALLOCATION_TRACKER_PRINT_NOW() VROAllocationTracker::printNow()
#define VRO_MALLOC(x, bytes) malloc(bytes), ALLOCATION_TRACKER_ADD(x, bytes)
#define VRO_FREE(x, ptr, bytes) free(ptr), ALLOCATION_TRACKER_SUB(x, bytes)
#define VRO_REALLOC(x, ptr, bytesOld, bytesNew) realloc(ptr, bytesNew), ALLOCATION_TRACKER_RESIZE(x, bytesOld, bytesNew)
#else
#define ALLOCATION_TRACKER_SET(x, bytes) ((void)0)
#define ALLOCATION_TRACKER_ADD(x, bytes) ((void)0)
#define ALLOCATION_TRACKER_SUB(x, bytes) ((void)0)
#define ALLOCATION_TRACKER_RESIZE(x, bytesOld, bytesNew) ((void)0)
#define ALLOCATION_TRACKER_PRINT() ((void)0)
#define ALLOCATION_TRACKER_PRINT_NOW() ((void)0)
#define VRO_MALLOC(x, bytes) malloc(bytes)
#define VRO_FREE(x, ptr, bytes) free(ptr)
#define VRO_REALLOC(x, ptr, bytesOld, bytesNew) realloc(ptr, bytesNew)
#endif
enum class VROAllocationBucket {
Scenes,
Nodes,
Geometry,
Materials,
MaterialSubstrates,
Textures,
TextureSubstrates,
Shaders,
ShaderModifiers,
VideoTextures,
VideoTextureCaches,
Typefaces,
Glyphs,
RenderTargets,
NUM_BUCKETS
};
enum class VROLayerType : int8_t;
class VROAllocationTracker {
public:
static void set(VROAllocationBucket bucket, uint32_t bytes);
static void add(VROAllocationBucket bucket, uint32_t bytes);
static void subtract(VROAllocationBucket bucket, uint32_t bytes);
static void resize(VROAllocationBucket bucket, uint32_t bytesOld, uint32_t bytesNew);
static void print();
static void printNow();
};
#endif /* defined(__VROAllocationTracker__) */

View File

@@ -0,0 +1,33 @@
//
// VROAnimatable.h
// ViroRenderer
//
// Created by Raj Advani on 12/17/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROAnimatable_h
#define VROAnimatable_h
#include <stdio.h>
#include <string>
#include "VROVector3f.h"
#include <functional>
#include <memory>
class VROAnimation;
/*
Marker class for objects that have animatable properties.
*/
class VROAnimatable : public std::enable_shared_from_this<VROAnimatable> {
public:
void animate(std::shared_ptr<VROAnimation> animation);
virtual void onAnimationFinished(){
//No-op
}
};
#endif /* VROAnimatable_hpp */

View File

@@ -0,0 +1,85 @@
//
// VROAnimation.h
// ViroRenderer
//
// Created by Raj Advani on 12/15/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROAnimation_h
#define VROAnimation_h
#include <stdio.h>
#include <memory>
#include <functional>
#include "VROAnimatable.h"
/*
Represents the animation of a property. Subclasses identify the type
of the property (e.g. animating a floating point value, animating a
VROVector3f, etc.).
*/
class VROAnimation {
public:
VROAnimation() {}
VROAnimation(std::function<void(VROAnimatable *const)> finishCallback) :
_finishCallback(finishCallback)
{}
virtual ~VROAnimation() {}
/*
Set the animatable. This is typically the object holding the
property to be animated. It is stored by a weak_ptr so we can
ensure it hasn't been deallocated before invoking the animation
each frame.
*/
void setAnimatable(std::shared_ptr<VROAnimatable> animatable) {
_animatable = animatable;
}
/*
Set a function to invoke when the animation completes.
*/
void setFinishCallback(std::function<void(VROAnimatable *const)> callback) {
_finishCallback = callback;
}
/*
Move the property to its value corresponding to t [0, 1].
*/
virtual void processAnimationFrame(float t) = 0;
/*
Immediately finish this animation by moving its value to the
end state.
*/
virtual void finish() = 0;
/*
Invoke after the animation is completed.
*/
void onTermination() {
finish();
std::shared_ptr<VROAnimatable> animatable = _animatable.lock();
if (animatable == nullptr){
return;
}
animatable->onAnimationFinished();
if (_finishCallback) {
_finishCallback(animatable.get());
}
}
protected:
std::weak_ptr<VROAnimatable> _animatable;
std::function<void(VROAnimatable *const)> _finishCallback;
};
#endif /* VROAnimation_h */

View File

@@ -0,0 +1,62 @@
//
// VROAnimationChain.h
// ViroRenderer
//
// Created by Raj Advani on 12/28/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROAnimationChain_h
#define VROAnimationChain_h
#include <vector>
#include "VROExecutableAnimation.h"
enum class VROAnimationChainExecution {
Serial,
Parallel
};
/*
An animation chain is a list of animation groups that execute
serially. This follows the composite pattern.
*/
class VROAnimationChain : public VROExecutableAnimation, public std::enable_shared_from_this<VROAnimationChain> {
public:
VROAnimationChain(std::vector<std::shared_ptr<VROExecutableAnimation>> &animations,
VROAnimationChainExecution execution) :
_animations(animations),
_execution(execution),
_numComplete(0) {}
virtual ~VROAnimationChain() {}
std::shared_ptr<VROExecutableAnimation> copy();
void execute(std::shared_ptr<VRONode> node,
std::function<void()> onFinished);
// This function adds an animation to the end of the chain.
void addAnimation(std::shared_ptr<VROExecutableAnimation> animation);
void pause();
void resume();
void terminate(bool jumpToEnd);
std::string toString() const;
private:
void executeSerial(std::shared_ptr<VRONode> node, int groupIndex,
std::function<void()> onFinished);
void executeParallel(std::shared_ptr<VRONode> node,
std::function<void()> onFinished);
void animateGroup(int groupIndex);
std::vector<std::shared_ptr<VROExecutableAnimation>> _animations;
VROAnimationChainExecution _execution;
int _numComplete;
};
#endif /* VROAnimationChain_h */

View File

@@ -0,0 +1,80 @@
//
// VROAnimationFloat.h
// ViroRenderer
//
// Created by Raj Advani on 12/17/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROAnimationFloat_h
#define VROAnimationFloat_h
#include "VROAnimation.h"
#include "VROAnimatable.h"
#include "VROMath.h"
class VROAnimationFloat : public VROAnimation {
public:
VROAnimationFloat(std::function<void(VROAnimatable *const, float)> method,
float start, float end) :
VROAnimation(),
_keyTimes({ 0, 1 }),
_keyValues({ start, end }),
_method(method)
{}
VROAnimationFloat(std::function<void(VROAnimatable *const, float)> method,
float start,
float end,
std::function<void(VROAnimatable *const)> finishCallback) :
VROAnimation(finishCallback),
_keyTimes({ 0, 1 }),
_keyValues({ start, end }),
_method(method)
{}
VROAnimationFloat(std::function<void(VROAnimatable *const, float)> method,
std::vector<float> keyTimes, std::vector<float> keyValues) :
VROAnimation(),
_keyTimes(keyTimes),
_keyValues(keyValues),
_method(method)
{}
VROAnimationFloat(std::function<void(VROAnimatable *const, float)> method,
std::vector<float> keyTimes,
std::vector<float> keyValues,
std::function<void(VROAnimatable *const)> finishCallback) :
VROAnimation(finishCallback),
_keyTimes(keyTimes),
_keyValues(keyValues),
_method(method)
{}
void processAnimationFrame(float t) {
float value = VROMathInterpolateKeyFrame(t, _keyTimes, _keyValues);
std::shared_ptr<VROAnimatable> animatable = _animatable.lock();
if (animatable) {
_method(animatable.get(), value);
}
}
void finish() {
std::shared_ptr<VROAnimatable> animatable = _animatable.lock();
if (animatable) {
_method(animatable.get(), _keyValues.back());
}
}
private:
std::vector<float> _keyTimes;
std::vector<float> _keyValues;
std::function<void(VROAnimatable *const, float)> _method;
};
#endif /* VROAnimationFloat_h */

View File

@@ -0,0 +1,78 @@
//
// VROAnimationGroup.h
// ViroRenderer
//
// Created by Raj Advani on 12/28/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROAnimationGroup_h
#define VROAnimationGroup_h
#include <stdio.h>
#include <vector>
#include <map>
#include "VROPropertyAnimation.h"
#include "VROMaterialAnimation.h"
#include "VROTimingFunction.h"
#include "VROExecutableAnimation.h"
class VRONode;
class VROLazyMaterial;
/*
An animation group is a set of property and material animations that
execute simultaneously.
*/
class VROAnimationGroup : public VROExecutableAnimation, public std::enable_shared_from_this<VROAnimationGroup> {
public:
static std::shared_ptr<VROAnimationGroup> parse(float duration, float delay, std::string functionName,
std::map<std::string, std::string> &properties,
std::vector<std::shared_ptr<VROLazyMaterial>> materials);
VROAnimationGroup(float durationSeconds, float delaySeconds,
VROTimingFunctionType timingFunction,
std::map<std::string, std::shared_ptr<VROPropertyAnimation>> &propertyAnimations,
std::vector<std::shared_ptr<VROMaterialAnimation>> &materialAnimations) :
_duration(durationSeconds),
_delay(delaySeconds),
_timingFunctionType(timingFunction),
_propertyAnimations(propertyAnimations),
_materialAnimations(materialAnimations) {}
virtual ~VROAnimationGroup() {}
std::shared_ptr<VROExecutableAnimation> copy();
void execute(std::shared_ptr<VRONode> node,
std::function<void()> onFinished);
void pause();
void resume();
void terminate(bool jumpToEnd);
std::string toString() const;
private:
static VROTimingFunctionType parseTimingFunction(std::string &name);
float _duration;
float _delay;
VROTimingFunctionType _timingFunctionType;
std::shared_ptr<VROTransaction> _transaction;
void animatePosition(std::shared_ptr<VRONode> &node);
void animateScale(std::shared_ptr<VRONode> &node);
void animateColor(std::shared_ptr<VRONode> &node);
void animateOpacity(std::shared_ptr<VRONode> &node);
void animateRotation(std::shared_ptr<VRONode> &node);
void animateMaterial(std::shared_ptr<VRONode> &node);
std::map<std::string, std::shared_ptr<VROPropertyAnimation>> _propertyAnimations;
std::vector<std::shared_ptr<VROMaterialAnimation>> _materialAnimations;
};
#endif /* VROAnimationGroup_h */

View File

@@ -0,0 +1,84 @@
//
// VROAnimationQuaternion.h
// ViroRenderer
//
// Created by Raj Advani on 12/28/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROAnimationQuaternion_h
#define VROAnimationQuaternion_h
#include <stdio.h>
#include "VROQuaternion.h"
#include "VROAnimation.h"
#include "VROAnimatable.h"
#include "VROMath.h"
class VROAnimationQuaternion : public VROAnimation {
public:
VROAnimationQuaternion(std::function<void(VROAnimatable *const, VROQuaternion)> method,
VROQuaternion start,
VROQuaternion end) :
VROAnimation(),
_keyTimes({ 0, 1 }),
_keyValues({ start, end }),
_method(method)
{}
VROAnimationQuaternion(std::function<void(VROAnimatable *const, VROQuaternion)> method,
VROQuaternion start,
VROQuaternion end,
std::function<void(VROAnimatable *const)> finishCallback) :
VROAnimation(finishCallback),
_keyTimes({ 0, 1 }),
_keyValues({ start, end }),
_method(method)
{}
VROAnimationQuaternion(std::function<void(VROAnimatable *const, VROQuaternion)> method,
std::vector<float> keyTimes,
std::vector<VROQuaternion> keyValues) :
VROAnimation(),
_keyTimes(keyTimes),
_keyValues(keyValues),
_method(method)
{}
VROAnimationQuaternion(std::function<void(VROAnimatable *const, VROQuaternion)> method,
std::vector<float> keyTimes,
std::vector<VROQuaternion> keyValues,
std::function<void(VROAnimatable *const)> finishCallback) :
VROAnimation(finishCallback),
_keyTimes(keyTimes),
_keyValues(keyValues),
_method(method)
{}
void processAnimationFrame(float t) {
VROQuaternion value = VROMathInterpolateKeyFrameQuaternion(t, _keyTimes, _keyValues);
std::shared_ptr<VROAnimatable> animatable = _animatable.lock();
if (animatable) {
_method(animatable.get(), value);
}
}
void finish() {
std::shared_ptr<VROAnimatable> animatable = _animatable.lock();
if (animatable) {
_method(animatable.get(), _keyValues.back());
}
}
private:
std::vector<float> _keyTimes;
std::vector<VROQuaternion> _keyValues;
std::function<void(VROAnimatable *const, VROQuaternion)> _method;
};
#endif /* VROAnimationQuaternion_h */

View File

@@ -0,0 +1,84 @@
//
// VROAnimationVector3f.h
// ViroRenderer
//
// Created by Raj Advani on 12/17/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROAnimationVector3f_h
#define VROAnimationVector3f_h
#include <stdio.h>
#include "VROVector3f.h"
#include "VROAnimation.h"
#include "VROAnimatable.h"
#include "VROMath.h"
class VROAnimationVector3f : public VROAnimation {
public:
VROAnimationVector3f(std::function<void(VROAnimatable *const, VROVector3f)> method,
VROVector3f start,
VROVector3f end) :
VROAnimation(),
_keyTimes({ 0, 1 }),
_keyValues({ start, end }),
_method(method)
{}
VROAnimationVector3f(std::function<void(VROAnimatable *const, VROVector3f)> method,
VROVector3f start,
VROVector3f end,
std::function<void(VROAnimatable *const)> finishCallback) :
VROAnimation(finishCallback),
_keyTimes({ 0, 1 }),
_keyValues({ start, end }),
_method(method)
{}
VROAnimationVector3f(std::function<void(VROAnimatable *const, VROVector3f)> method,
std::vector<float> keyTimes,
std::vector<VROVector3f> keyValues) :
VROAnimation(),
_keyTimes(keyTimes),
_keyValues(keyValues),
_method(method)
{}
VROAnimationVector3f(std::function<void(VROAnimatable *const, VROVector3f)> method,
std::vector<float> keyTimes,
std::vector<VROVector3f> keyValues,
std::function<void(VROAnimatable *const)> finishCallback) :
VROAnimation(finishCallback),
_keyTimes(keyTimes),
_keyValues(keyValues),
_method(method)
{}
void processAnimationFrame(float t) {
VROVector3f value = VROMathInterpolateKeyFrameVector3f(t, _keyTimes, _keyValues);
std::shared_ptr<VROAnimatable> animatable = _animatable.lock();
if (animatable) {
_method(animatable.get(), value);
}
}
void finish() {
std::shared_ptr<VROAnimatable> animatable = _animatable.lock();
if (animatable) {
_method(animatable.get(), _keyValues.back());
}
}
private:
std::vector<float> _keyTimes;
std::vector<VROVector3f> _keyValues;
std::function<void(VROAnimatable *const, VROVector3f)> _method;
};
#endif /* VROAnimationVector3f_h */

View File

@@ -0,0 +1,40 @@
//
// VROAudioPlayer.h
// ViroRenderer
//
// Created by Raj Advani on 3/22/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROAudioPlayer_h
#define VROAudioPlayer_h
#include <string>
#include <memory>
#include "VROSoundDelegateInternal.h"
class VROData;
class VROAudioPlayer {
public:
virtual ~VROAudioPlayer() {}
virtual void setup() = 0;
virtual void setDelegate(std::shared_ptr<VROSoundDelegateInternal> delegate) {
_delegate = delegate;
}
virtual void setLoop(bool loop) = 0;
virtual void play() = 0;
virtual void pause() = 0;
virtual void setVolume(float volume) = 0;
virtual void setMuted(bool muted) = 0;
virtual void seekToTime(float seconds) = 0;
protected:
std::shared_ptr<VROSoundDelegateInternal> _delegate;
};
#endif /* VROAudioPlayer_h */

View File

@@ -0,0 +1,89 @@
//
// VROAudioPlayeriOS.h
// ViroRenderer
//
// Created by Raj Advani on 11/6/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROAudioPlayeriOS_h
#define VROAudioPlayeriOS_h
#include "VROAudioPlayer.h"
#include "VROSoundDataDelegate.h"
#include "VROSoundData.h"
#include <AVFoundation/AVFoundation.h>
/*
Simple object that wraps a VROSoundDelegateInternal object and acts as a delegate for the AVAudioPlayer
*/
@interface VROAudioPlayerDelegate : NSObject <AVAudioPlayerDelegate>
- (id)initWithSoundDelegate:(std::shared_ptr<VROSoundDelegateInternal>)soundDelegate;
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag;
@end
class VROAudioPlayeriOS : public VROAudioPlayer, public VROSoundDataDelegate, public std::enable_shared_from_this<VROAudioPlayeriOS> {
public:
VROAudioPlayeriOS(std::string url, bool isLocalUrl);
VROAudioPlayeriOS(std::shared_ptr<VROData> data);
VROAudioPlayeriOS(std::shared_ptr<VROSoundData> data);
virtual ~VROAudioPlayeriOS();
/*
Must be invoke after construction, after setting the delegate.
*/
void setup();
void setDelegate(std::shared_ptr<VROSoundDelegateInternal> delegate);
void setLoop(bool loop);
void play();
void pause();
void setVolume(float volume);
void setMuted(bool muted);
void seekToTime(float seconds);
#pragma mark VROSoundDataDelegate Implementation
void dataIsReady();
void dataError(std::string error);
private:
/*
Underlying iOS audio player. The delegate is only kept here so that
it's retained.
*/
AVAudioPlayer *_player;
VROAudioPlayerDelegate *_audioDelegate;
/*
Generic settings.
*/
float _playVolume;
bool _muted;
bool _paused;
bool _loop;
bool _isLocal;
/*
Source audio.
*/
std::string _url;
std::shared_ptr<VROSoundData> _data;
/*
Update the underlying iOS player with the various properties set on this
player (e.g. muted, loop, volume, etc.)
*/
void updatePlayerProperties();
void doFadeThenPause();
void doFadeThenStop();
};
#endif /* VROAudioPlayeriOS_h */

View File

@@ -0,0 +1,40 @@
//
// VROBillboardConstraint.h
// ViroRenderer
//
// Created by Raj Advani on 3/9/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROBillboardConstraint_h
#define VROBillboardConstraint_h
#include "VROConstraint.h"
enum class VROBillboardAxis {
X,
Y,
Z,
All
};
class VROBillboardConstraint : public VROConstraint {
public:
VROBillboardConstraint(VROBillboardAxis freeAxis) :
_freeAxis(freeAxis) {}
VROMatrix4f getTransform(const VRORenderContext &context,
VROMatrix4f transform);
private:
VROBillboardAxis _freeAxis;
VROQuaternion computeAxisRotation(VROVector3f lookAt, VROVector3f defaultAxis,
VROVector3f objToCamProj);
};
#endif /* VROBillboardConstraint_h */

View File

@@ -0,0 +1,183 @@
//
// VROBoundingBox.h
// ViroRenderer
//
// Created by Raj Advani on 10/15/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROBOUNDINGBOX_H_
#define VROBOUNDINGBOX_H_
#include <stdlib.h>
#include <math.h>
#include "VROVector3f.h"
#include "VROMatrix4f.h"
#include <string>
#include <vector>
class VROFrustum;
enum VROBoxPlane {
VROBoxPlaneMinX = 0,
VROBoxPlaneMaxX = 1,
VROBoxPlaneMinY = 2,
VROBoxPlaneMaxY = 3,
VROBoxPlaneMinZ = 4,
VROBoxPlaneMaxZ = 5
};
class VROBoundingBox {
public:
/*
Constructors.
*/
VROBoundingBox() noexcept;
VROBoundingBox(float left, float right, float bottom, float top, float zmin, float zmax);
/*
Ray intersection. The intersection result will be stored in *intPt. If there are multiple intersection
points, only one will be returned.
*/
bool intersectsRay(const VROVector3f &ray, const VROVector3f &origin, VROVector3f *intPt);
/*
Point containment functions. The first function checks for full containment; the remaining functions
only check for containment along the indicated axes.
*/
bool containsPoint(const VROVector3f &point) const;
bool containsPointXY(const VROVector3f &point) const;
bool containsPointXZ(const VROVector3f &point) const;
bool containsPointYZ(const VROVector3f &point) const;
/*
Distance from the point to the bounding box.
*/
float getDistanceToPoint(VROVector3f p) const;
/*
Distance from the point to the furthest point on the bounding box.
*/
float getFurthestDistanceToPoint(VROVector3f p) const;
/*
Bounding-box to bounding-box containment and intersections.
*/
bool containsBox(const VROBoundingBox &box) const;
bool intersectsBox(const VROBoundingBox &box) const;
/*
Get the coordinates and extent of the bounding box.
*/
float getMinX() const {
return _planes[VROBoxPlaneMinX];
}
float getMaxX() const {
return _planes[VROBoxPlaneMaxX];
}
float getMaxY() const {
return _planes[VROBoxPlaneMaxY];
}
float getMinY() const {
return _planes[VROBoxPlaneMinY];
}
float getMaxZ() const {
return _planes[VROBoxPlaneMaxZ];
}
float getMinZ() const {
return _planes[VROBoxPlaneMinZ];
}
float getX() const {
return (_planes[VROBoxPlaneMaxX] + _planes[VROBoxPlaneMinX]) / 2;
}
float getY() const {
return (_planes[VROBoxPlaneMaxY] + _planes[VROBoxPlaneMinY]) / 2;
}
float getZ() const {
return (_planes[VROBoxPlaneMaxZ] + _planes[VROBoxPlaneMinZ]) / 2;
}
float getSpanX() const {
return _planes[VROBoxPlaneMaxX] - _planes[VROBoxPlaneMinX];
}
float getSpanY() const {
return _planes[VROBoxPlaneMaxY] - _planes[VROBoxPlaneMinY];
}
float getSpanZ() const {
return _planes[VROBoxPlaneMaxZ] - _planes[VROBoxPlaneMinZ];
}
VROVector3f getCenter() const {
return { getX(), getY(), getZ() };
}
VROVector3f getExtents() const {
return { getSpanX(), getSpanY(), getSpanZ() };
}
/*
Set the coordinates of the bounding box.
*/
void setMinX(float minX) {
_planes[VROBoxPlaneMinX] = minX;
}
void setMaxX(float maxX) {
_planes[VROBoxPlaneMaxX] = maxX;
}
void setMinY(float minY) {
_planes[VROBoxPlaneMinY] = minY;
}
void setMaxY(float maxY) {
_planes[VROBoxPlaneMaxY] = maxY;
}
void setMinZ(float minZ) {
_planes[VROBoxPlaneMinZ] = minZ;
}
void setMaxZ(float maxZ) {
_planes[VROBoxPlaneMaxZ] = maxZ;
}
const float *getPlanes() const {
return _planes;
}
/*
Scale by a relative amount (scaleBy) or an absolute amount (expandBy). Scales about the center of the
box.
*/
void scaleBy(float scale);
void expandBy(float amount);
/*
Transform this bounding box by the given matrix. Note that since this is
an AABB box, rotations can have significant impact on the size of the box.
*/
VROBoundingBox transform(VROMatrix4f transform) const;
/*
Optimized set functions.
*/
void set(const float *dimensions);
void set(float xMin, float xMax, float yMin, float yMax, float zMin, float zMax);
void copy(const VROBoundingBox &box);
VROBoundingBox unionWith(const VROBoundingBox &box);
/*
Union this bounding box with the supplied box, updating our member
variables to be a bounding box that contains all points we previously
contained, and any points the supplied box contains.
*/
void unionDestructive(const VROBoundingBox &box);
void center(float *center) const;
std::string toString() const;
private:
/*
The [xmin, xmax, ymin, ymax, zmin, zmax] extremities of this bounding-box.
*/
float _planes[6];
};
#endif /* VROBOUNDINGBOX_H_ */

View File

@@ -0,0 +1,39 @@
//
// VROBox.h
// ViroRenderer
//
// Created by Raj Advani on 12/7/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROBox_h
#define VROBox_h
#include "VROGeometry.h"
#include "VROShapeUtils.h"
#include <memory>
class VROBox : public VROGeometry {
public:
static std::shared_ptr<VROBox> createBox(float width, float height, float length);
virtual ~VROBox();
void setWidth(float width);
void setHeight(float height);
void setLength(float length);
virtual void setMaterials(std::vector<std::shared_ptr<VROMaterial>> materials);
private:
float _width, _height, _length;
VROBox(float width, float height, float length);
void updateBox();
void buildBoxVAR(VROShapeVertexLayout *vertexLayout);
};
#endif /* VROBox_h */

View File

@@ -0,0 +1,239 @@
//
// VROByteBuffer.h
// ViroRenderer
//
// Created by Raj Advani on 10/21/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROBYTEBUFFER_H_
#define VROBYTEBUFFER_H_
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <math.h>
#include <string>
class VROByteBuffer final {
public:
/*
Default writing constructor, creating a new byte array of default
length.
*/
VROByteBuffer();
/*
Writing constructor, creating a new byte array of the given length.
*/
VROByteBuffer(size_t capacity);
/*
Read constructor. Wrap the given array of bytes of the given length. Set copy to true
to copy the bytes into this VROByteBuffer. If false, then the bytes will continue to be
owned by the caller and will not be deleted when this VROByteBuffer is destroyed.
*/
VROByteBuffer(const void *bytes, size_t length, bool copy = true);
/*
Wrap the given string with a VROByteBuffer.
!!DANGER!!
The caller must ensure that the passed-in string stays in scope throughout the
lifetime of this buffer. The string is NOT copied into this object (for perf
reasons).
*/
VROByteBuffer(const std::string &byteString);
/*
Copy semantics
*/
VROByteBuffer(VROByteBuffer *toCopy);
VROByteBuffer(const VROByteBuffer& toCopy) = delete;
VROByteBuffer& operator=(const VROByteBuffer& rhs) = delete;
/*
Move semantics
*/
VROByteBuffer(VROByteBuffer&& moveFrom);
VROByteBuffer& operator=(VROByteBuffer&& moveFrom);
~VROByteBuffer();
size_t capacity() const {
return _capacity;
}
/*
Read methods.
*/
bool readBool();
float readHalf();
float readFloat();
double readDouble();
int readInt();
uint64_t readUInt64();
short readShort();
unsigned short readUnsignedShort();
signed char readByte();
unsigned char readUnsignedByte();
void * readPointer();
/*
Read strings, allocating new space.
*/
std::string readSTLStringUTF8NullTerm();
std::string readSTLString();
std::string readSTLStringUTF8();
std::string readSTLText();
std::string readSTLTextUTF8();
/*
Read the next null-terminated string.
*/
void readStringNullTerm(char *result);
std::string readStringNullTerm();
size_t getPosition() const {
return _pos;
}
void setPosition(size_t position);
void skip(size_t bytes);
/*
Underlying data manipulation and retrieval.
*/
char* getData();
char* getDataFromPosition(size_t position);
/*
Create a byte-buffer from a subrange of this byte-buffer, using absolute position and length.
The underlying bytes will be copied, and the resultant buffer will own said bytes.
*/
VROByteBuffer *split(size_t offset, size_t length);
/*
Peek methods.
*/
signed char peekByte();
int peekInt();
/*
Batch read methods.
*/
void copyBytes(void *dest, int numBytes);
void copyChars(char *dest, int numChars);
void copyShorts(short *dest, int numShorts);
void copyInts(int *dest, int numInts);
void copyFloats(float *dest, int numFloats);
void copyLongs(uint64_t *dest, int numLongs);
signed char *readNumChars(int numChars);
short *readNumShorts(int numShorts);
/*
Grow the byte-buffer to fit the given number of additional bytes PAST the
current position of the buffer. If the buffer has space remaining, do not
necesarily grow the buffer.
*/
void grow(size_t additionalBytesRequired);
/*
Shrink the buffer down to the given size.
*/
void shrink(size_t size);
/*
Fill the buffer with zeros.
*/
void clear();
/*
Set position to zero.
*/
void rewind();
/*
Invoke to make the ByteBuffer *not* delete its underlying bytes when
deallocated. This is useful when we want to move the data to another
container like VROData without performing a copy.
*/
void releaseBytes() {
_freeOnDealloc = false;
}
/*
Write methods.
*/
void writeBool(bool value);
void writeByte(char value);
void writeShort(short value);
void writeInt(int value);
void writeHalf(float value);
void writeFloat(float value);
void writeFloats(float *pValues, const int numFloats);
void writeDouble(double value);
void writeLong(uint64_t value);
void writeStringNullTerm(const char *value);
void writeBytes(const void *bytes, size_t length);
void writeBuffer(VROByteBuffer *src, size_t length);
void writeChars(const char *value);
void writePointer(void *pointer);
/*
Fill the buffer with the given value, repeated across the given number of bytes. Equivalent
to a memset. The buffer must be large enough to fit numBytes; it will not be automatically grown.
*/
void fill(unsigned char value, size_t numBytes);
/*
Write the given number of bytes from this buffer to the destination, incrementing
the position of both buffers.
*/
void writeToBuffer(VROByteBuffer *dest, size_t length);
/*
Write the given number of bytes from this buffer to the destination, incrementing
the position of the destination buffer and rewinding this buffer to it's position
before the call to this function.
*/
void writeToBufferAndRewind(VROByteBuffer *dest, size_t length) const;
/*
Write the entirety of the buffer (from position 0 to capacity) to the given file.
Create the file if it does not exist. The second function writes length bytes starting
at the given offset.
*/
void writeToFile(const char *path);
void writeToFile(const std::string &path);
void writeToFile(const char *path, size_t offset, size_t length);
void writeToFile(const std::string &path, size_t offset, size_t length);
private:
/*
The current position (in bytes) in the data. Incremented as we read.
*/
size_t _pos;
/*
The total capacity of the buffer (in bytes).
*/
size_t _capacity;
/*
The inner buffer containing the data.
*/
char *_buffer;
/*
True if the underlying bytes should be freed when this buffer is deallocated.
*/
bool _freeOnDealloc;
};
#endif /* VROBYTEBUFFER_H_ */

View File

@@ -0,0 +1,158 @@
//
// VROCamera.h
// ViroRenderer
//
// Created by Raj Advani on 11/13/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROCamera_h
#define VROCamera_h
#include "VROVector3f.h"
#include "VROQuaternion.h"
#include "VROMatrix4f.h"
#include "VROViewport.h"
#include "VROFrustum.h"
#include "VROFieldOfView.h"
enum class VROCameraRotationType {
Standard,
Orbit
};
/*
The default forward and up vectors. These are rotated by the base and head
rotation to derive the actual forward and up vectors.
*/
static const VROVector3f kBaseForward = { 0, 0, -1 };
static const VROVector3f kBaseUp = { 0, 1, 0 };
class VROCamera {
public:
VROCamera();
virtual ~VROCamera();
void setPosition(VROVector3f position);
void setHeadRotation(VROMatrix4f headRotation);
void setBaseRotation(VROMatrix4f baseRotation);
void setViewport(VROViewport viewport);
void setFOV(VROFieldOfView fov);
void setProjection(VROMatrix4f projection);
VROVector3f getPosition() const {
return _position;
}
VROVector3f getForward() const {
return _forward;
}
VROVector3f getUp() const {
return _up;
}
VROQuaternion getRotation() const {
return _rotation;
}
VROMatrix4f getLookAtMatrix() const {
return _lookAtMatrix;
}
VROMatrix4f getProjection() const {
return _projection;
}
const VROFrustum &getFrustum() const {
return _frustum;
}
VROFieldOfView getFieldOfView() const {
return _fov;
}
VROViewport getViewport() const {
return _viewport;
}
float getNCP() const {
return _ncp;
}
float getFCP() const {
return _fcp;
}
void computeLookAtMatrix();
void computeFrustum();
float getWorldPerScreen(float distance) const;
private:
VROVector3f _position;
/*
The camera forward vector. Normalized vector indicating where the camera
is pointing.
*/
VROVector3f _forward;
/*
The camera up vector. Normalized vector indicating which direction is 'up'.
*/
VROVector3f _up;
/*
The camera quaternion represents the rotation from (0, 0, -1) required to
achieve the camera's current orientation. This factors in both base
rotation and head rotation.
*/
VROQuaternion _rotation;
/*
The current head rotation. Head rotation is set by the user's HMD orientation.
Total rotation is head rotation plus base rotation.
*/
VROMatrix4f _headRotation;
/*
The base rotation. This is set by the application. Total rotation is head
rotation plus base rotation.
*/
VROMatrix4f _baseRotation;
/*
The last computed lookAt matrix for this camera. This matrix combines all rotation
and position information into one unified view matrix. Note like all matrices in
the VROCamera, this is eye-independent (the eyeFromHeadMatrix is not considered).
*/
VROMatrix4f _lookAtMatrix;
/*
The projection matrix associated with this camera.
*/
VROMatrix4f _projection;
/*
The frustum associated with this camera. Derived from the lookAtMatrix and the
projection matrix.
*/
VROFrustum _frustum;
/*
The current viewport and FOV.
*/
VROViewport _viewport;
VROFieldOfView _fov;
/*
The camera's near and far clipping planes.
*/
float _ncp, _fcp;
void onRotationChanged();
};
class VROCameraDelegate {
public:
VROCameraDelegate() {};
virtual ~VROCameraDelegate() {};
virtual void onCameraTransformationUpdate(VROVector3f pos,
VROVector3f rot,
VROVector3f forward) = 0;
};
#endif /* VROCamera_h */

View File

@@ -0,0 +1,69 @@
//
// VROCameraTexture.hpp
// ViroRenderer
//
// Created by Raj Advani on 3/22/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROCameraTexture_hpp
#define VROCameraTexture_hpp
#include "VROTexture.h"
#include <memory>
class VRORenderContext;
class VROFrameSynchronizer;
class VRODriver;
class VROVector3f;
enum class VROCameraPosition {
Front,
Back
};
enum class VROCameraOrientation {
Portrait,
PortraitUpsideDown,
LandscapeLeft,
LandscapeRight,
};
class VROCameraTexture : public VROTexture {
public:
VROCameraTexture(VROTextureType type) :
VROTexture(type, VROTextureInternalFormat::RGBA8) {}
virtual ~VROCameraTexture() {}
/*
Initialize this texture to display the contents of the camera.
The texture will not display until play() is invoked. Returns
true if successful, false on failure.
*/
virtual bool initCamera(VROCameraPosition position, VROCameraOrientation orientation,
std::shared_ptr<VRODriver> driver) = 0;
/*
Play and pause.
*/
virtual void pause() = 0;
virtual void play() = 0;
virtual bool isPaused() = 0;
/*
Get the horizontal FOV used by the camera. This should return the
FOV from edge to edge, in degrees.
*/
virtual float getHorizontalFOV() const = 0;
/*
Get the image size (width, height) for the camera. Stored in the
vector's x and y components.
*/
virtual VROVector3f getImageSize() const = 0;
};
#endif /* VROCameraTexture_hpp */

View File

@@ -0,0 +1,83 @@
//
// VROCameraTextureiOS.h
// ViroRenderer
//
// Created by Raj Advani on 3/22/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROCameraTextureiOS_h
#define VROCameraTextureiOS_h
#include "VROCameraTexture.h"
// #include "VROTrackingHelper.h"
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@class VROCameraCaptureDelegate;
@class VROCameraOrientationListener;
class VROVideoTextureCache;
class VROCameraTextureiOS : public VROCameraTexture {
public:
VROCameraTextureiOS(VROTextureType type);
virtual ~VROCameraTextureiOS();
bool initCamera(VROCameraPosition position, VROCameraOrientation orientation, std::shared_ptr<VRODriver> driver);
void pause();
void play();
bool isPaused();
float getHorizontalFOV() const;
VROVector3f getImageSize() const;
void displayPixelBuffer(std::unique_ptr<VROTextureSubstrate> substrate);
void updateOrientation(VROCameraOrientation orientation);
private:
/*
Capture session and delegate used for live video playback.
*/
AVCaptureSession *_captureSession;
VROCameraCaptureDelegate *_delegate;
VROCameraOrientationListener *_orientationListener;
/*
True if paused.
*/
bool _paused;
/*
Video texture cache used for transferring camera content to OpenGL.
*/
std::shared_ptr<VROVideoTextureCache> _videoTextureCache;
};
/*
Delegate for capturing video from cameras.
*/
@interface VROCameraCaptureDelegate : NSObject <AVCaptureVideoDataOutputSampleBufferDelegate>
// @property (nonatomic, strong) VROTrackingHelper* trackingHelper;
- (id)initWithCameraTexture:(std::shared_ptr<VROCameraTextureiOS>)texture
cache:(std::shared_ptr<VROVideoTextureCache>)cache
driver:(std::shared_ptr<VRODriver>)driver;
@end
/*
Delegate for listening to orientation changes.
*/
@interface VROCameraOrientationListener : NSObject
- (id)initWithCameraTexture:(std::shared_ptr<VROCameraTextureiOS>)texture;
- (void)orientationDidChange:(NSNotification *)notification;
@end
#endif /* VROCameraTextureiOS_h */

View File

@@ -0,0 +1,68 @@
//
// VROConcurrentBuffer.h
// ViroRenderer
//
// Created by Raj Advani on 2/3/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROConcurrentBuffer_h
#define VROConcurrentBuffer_h
#include "VRODefines.h"
#if VRO_METAL
#include <stdio.h>
#include "VROEye.h"
#include <Metal/Metal.h>
#include <MetalKit/MetalKit.h>
static const int kMaxBuffersInFlight = 3;
/*
Wraps a Metal buffer that's used by both the GPU and the CPU.
The section of the buffer being used (written to by the CPU) changes
with each frame, so that the CPU and GPU never collide.
*/
class VROConcurrentBuffer {
public:
VROConcurrentBuffer(int size, NSString *label, id <MTLDevice> device);
virtual ~VROConcurrentBuffer();
/*
Get the underlying MTLBuffer.
*/
id <MTLBuffer> getMTLBuffer(VROEyeType eye) {
return _buffer[(int)eye];
}
void *getWritableContents(VROEyeType eye, int frame) {
return (void *) ((char *)[_buffer[(int)eye] contents] + getWriteOffset(frame));
}
/*
Get the CPU write offset into the MTLBuffer, based on the current
frame.
*/
int getWriteOffset(int frame) {
return _size * (frame % kMaxBuffersInFlight);
}
private:
/*
The underlying Metal buffer for each eye.
*/
id <MTLBuffer> _buffer[2];
/*
The size of each section in the MTLBuffer.
*/
int _size;
};
#endif
#endif /* VROConcurrentBuffer_h */

View File

@@ -0,0 +1,30 @@
//
// VROConstraint.h
// ViroRenderer
//
// Created by Raj Advani on 3/9/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROConstraint_h
#define VROConstraint_h
#include <stdio.h>
#include <memory>
class VRONode;
class VROMatrix4f;
class VROQuaternion;
class VROVector3f;
class VRORenderContext;
class VROConstraint {
public:
virtual VROMatrix4f getTransform(const VRORenderContext &context,
VROMatrix4f transform) = 0;
};
#endif /* VROConstraint_h */

View File

@@ -0,0 +1,66 @@
//
// VROData.h
// ViroRenderer
//
// Created by Raj Advani on 11/17/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROData_h
#define VROData_h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
Defines how the VROData holds onto its underlying data.
Copy: data is copied on construction, freed on destruction
Move: data is assigned on construction, freed on destruction
Wrap: data is assigned on construction
*/
enum class VRODataOwnership {
Copy,
Move,
Wrap
};
/*
Holds onto an arbitrary block of bytes.
*/
class VROData {
public:
/*
Construct a new VROData. Default ownership semanatics are
Copy.
*/
VROData(void *data, int dataLength, VRODataOwnership ownership = VRODataOwnership::Copy);
/*
Construct a new VROData, copying the bytes into this object.
(allows for const data input).
*/
VROData(const void *data, int dataLength);
~VROData();
void *const getData() {
return _data;
}
int getDataLength() const {
return _dataLength;
}
private:
void *_data;
int _dataLength;
VRODataOwnership _ownership;
};
#endif /* VROData_h */

View File

@@ -0,0 +1,22 @@
//
// VRODefines.h
// ViroRenderer
//
// Created by Raj Advani on 11/1/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VRODefines_h
#define VRODefines_h
#ifndef __OBJC__
#define VRO_PLATFORM_ANDROID 1
#define VRO_PLATFORM_IOS 0
#else
#define VRO_PLATFORM_ANDROID 0
#define VRO_PLATFORM_IOS 1
#endif
#define VRO_METAL 0
#endif /* VRODefines_h */

View File

@@ -0,0 +1,192 @@
//
// VRODriver.h
// ViroRenderer
//
// Created by Raj Advani on 4/21/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VRODriver_h
#define VRODriver_h
#include <vector>
#include "VRODefines.h"
#include "VROSoundData.h"
class VROGeometry;
class VROMaterial;
class VROGeometrySubstrate;
class VROMaterialSubstrate;
class VROTextureSubstrate;
class VROData;
class VROImage;
class VROVideoTextureCache;
class VROSound;
class VROAudioPlayer;
class VROTypeface;
class VROFrameTimer;
class VRORenderTarget;
class VRORenderContext;
class VROShaderProgram;
class VROImagePostProcess;
enum class VROSoundType;
enum class VROTextureType;
enum class VROTextureFormat;
enum class VROTextureInternalFormat;
enum class VROWrapMode;
enum class VROFilterMode;
enum class VROMipmapMode;
enum class VRORenderTargetType;
enum class VROFace;
enum class VROCullMode;
enum class VROBlendMode;
enum class VROResourceType;
/*
The type of the GPU can be used to modify rendering for compatibility with older
GPUs, or it can be used to gate access to advanced rendering features that only
work with some subset of GPUs.
*/
enum class VROGPUType {
/*
Covers properly functioning GPUs.
*/
Normal,
/*
This type is used for GPUs that supposedly support OpenGL 3.0 but can't handle
simple 3D graphics without serious errors. This is primarily used for the Adreno 330
and earlier, which have issues with structs in GLSL programs. The inclusion of structs can
cause textures to corrupt (EGL textures gain a purple tint), and shaders to sporadically fail
compilation.
Since these GPUs are generally legacy and can't support AR and VR, instead of writing
an entirely new set of shaders to support them, we instead force these GPUs to always
use a simple constant shader, and modify the expand the Surface struct into separate
variables.
*/
Adreno330OrOlder,
};
/*
The color mode used when rendering.
NonLinear: textures are sampled in RGB (gamma-corrected) space, shader operations
are performed in this non-linear space, and rendered straight to the frame
buffer without conversion. In other words, inputs are gamma corrected and
output is gamma corrected. Less color accuracy.
Linear: textures are sampled as sRGB, meaning they are converted to a linear
colorspace by the underlying hardware. Colors remain in linear color space
until the *final* framebuffer render, at which point they are gamma
corrected by the hardware (by rendering into an sRGB-configured framebuffer)
LinearSoftware: textures are sampled as sRGB, as with Linear, but the final framebuffer
is gamma-corrected via shader code. This is typically used in situations
where we are unable to allocate an sRGB framebuffer for the final render.
*/
enum class VROColorRenderingMode {
NonLinear,
Linear,
LinearSoftware,
};
/*
The driver is used to interface with the rendering subsystem (OpenGL,
Metal, etc.).
*/
class VRODriver {
public:
virtual ~VRODriver() {}
/*
Provides the driver an opportunity to update any sub-components
with per-frame state. The willRenderFrame method is invoked just
prior to rendering, and didRenderFrame is invoked afterward. The
VROFrameTimer can be used by the driver to timebox its tasks so
as not to overrun frame time.
*/
virtual void willRenderFrame(const VRORenderContext &context) = 0;
virtual void didRenderFrame(const VROFrameTimer &timer, const VRORenderContext &context) = 0;
/*
Invoked when the renderer is paused and resumed.
*/
virtual void pause() = 0;
virtual void resume() = 0;
/*
Read the GPU type, which may be necessary to support old GPUs that are not to
specification, or to control whether or not to use advanced features only supported
by a subset of GPUs.
*/
virtual void readGPUType() = 0;
/*
Get the GPU type, after it has been read by the system.
*/
virtual VROGPUType getGPUType() = 0;
/*
Read the ID of the display's framebuffer. May not be required on all
platforms. This way we're able to re-bind to the display during a multi-pass
alogrithm.
*/
virtual void readDisplayFramebuffer() = 0;
/*
The driver controls context-wide state change. The implementation
should store a CPU copy of current state to avoid sending unnecessary
instructions to the GPU.
*/
virtual void setDepthWritingEnabled(bool enabled) = 0;
virtual void setDepthReadingEnabled(bool enabled) = 0;
virtual void setStencilTestEnabled(bool enabled) = 0;
virtual void setCullMode(VROCullMode cullMode) = 0;
virtual void setColorWritingEnabled(bool enabled) = 0;
virtual void bindShader(std::shared_ptr<VROShaderProgram> program) = 0;
virtual void unbindShader() = 0;
virtual void bindRenderTarget(std::shared_ptr<VRORenderTarget> target) = 0;
virtual void unbindRenderTarget() = 0;
/*
Indicates how we handle linear rendering and gamma-correction for this device
and platform. Features like HDR are only enabled in linear space.
*/
virtual VROColorRenderingMode getColorRenderingMode() = 0;
/*
Return true if bloom rendering is enabled. If so, materials that exceed their
bloom threshold will glow.
*/
virtual bool isBloomSupported() = 0;
virtual VROGeometrySubstrate *newGeometrySubstrate(const VROGeometry &geometry) = 0;
virtual VROMaterialSubstrate *newMaterialSubstrate(VROMaterial &material) = 0;
virtual VROTextureSubstrate *newTextureSubstrate(VROTextureType type,
VROTextureFormat format,
VROTextureInternalFormat internalFormat, bool sRGB,
VROMipmapMode mipmapMode,
std::vector<std::shared_ptr<VROData>> &data,
int width, int height, std::vector<uint32_t> mipSizes,
VROWrapMode wrapS, VROWrapMode wrapT,
VROFilterMode minFilter, VROFilterMode magFilter, VROFilterMode mipFilter) = 0;
virtual std::shared_ptr<VRORenderTarget> newRenderTarget(VRORenderTargetType type, int numAttachments, int numImages,
bool enableMipmaps) = 0;
virtual std::shared_ptr<VRORenderTarget> getDisplay() = 0;
virtual std::shared_ptr<VROImagePostProcess> newImagePostProcess(std::shared_ptr<VROShaderProgram> shader) = 0;
virtual std::shared_ptr<VROVideoTextureCache> newVideoTextureCache() = 0;
virtual std::shared_ptr<VROSound> newSound(std::shared_ptr<VROSoundData> data, VROSoundType type) = 0;
virtual std::shared_ptr<VROSound> newSound(std::string resource, VROResourceType resourceType, VROSoundType type) = 0;
virtual std::shared_ptr<VROAudioPlayer> newAudioPlayer(std::shared_ptr<VROSoundData> data) = 0;
virtual std::shared_ptr<VROAudioPlayer> newAudioPlayer(std::string path, bool isLocal) = 0;
virtual std::shared_ptr<VROTypeface> newTypeface(std::string typeface, int size) = 0;
virtual void setSoundRoom(float sizeX, float sizeY, float sizeZ, std::string wallMaterial,
std::string ceilingMaterial, std::string floorMaterial) = 0;
virtual void setBlendingMode(VROBlendMode mode) = 0;
};
#endif /* VRODriver_hpp */

View File

@@ -0,0 +1,215 @@
//
// VROEventDelegate.h
// ViroRenderer
//
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROEventDelegate_h
#define VROEventDelegate_h
#include <stdio.h>
#include <vector>
#include <string>
#include <memory>
#include <set>
#include <map>
#include "VROVector3f.h"
#include "VROHitTestResult.h"
#include <limits>
class VROARHitTestResult;
class VROARPointCloud;
static const float kOnFuseReset = std::numeric_limits<float>::max();
/*
Class for both registering for and implementing event delegate callbacks.
*/
class VROEventDelegate {
public:
/*
Enum EventAction types that are supported by this delegate, used for
describing InputSources from InputTypes.h. For example, an OnClick
action may originate from a ViroDayDream AppButton inputSource.
IMPORTANT: Enum values should match EventAction within EventDelegateJni.java
as the standard format to be passed through the JNI layer.
Do Not change the Enum Values!!! Simply add additional event types as need be.
*/
enum EventAction {
OnHover = 1,
OnClick = 2,
OnTouch = 3,
OnMove = 4,
OnControllerStatus = 5,
OnSwipe = 6,
OnScroll = 7,
OnDrag = 8,
OnFuse = 9,
OnPinch = 10,
OnRotate = 11,
OnCameraARHitTest = 12,
OnARPointCloudUpdate = 13,
};
/*
ClickState enum describing the OnClick Event action.
*/
enum ClickState {
ClickDown = 1,
ClickUp = 2,
Clicked = 3
};
/*
TouchState enum describing the OnTouch Event action.
*/
enum TouchState {
TouchDown = 1,
TouchDownMove = 2,
TouchUp = 3,
};
enum PinchState {
PinchStart = 1,
PinchMove = 2,
PinchEnd = 3,
};
enum RotateState {
RotateStart = 1,
RotateMove = 2,
RotateEnd = 3,
};
enum SwipeState {
SwipeUp = 1,
SwipeDown = 2,
SwipeLeft = 3,
SwipeRight = 4
};
/*
Enum ControllerStatus types describing the availability status of the
current input controller.
IMPORTANT: Enum values should match EventSource within EventDelegateJni.java
as the standard format to be passed through the JNI layer.
Do Not change the Enum Values!!! Simply add additional event types as need be.
*/
enum ControllerStatus {
Unknown = 1,
Connecting = 2,
Connected = 3,
Disconnected = 4,
Error = 5
};
// Disable all event callbacks by default
VROEventDelegate() {
_enabledEventMap[VROEventDelegate::EventAction::OnHover] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnClick] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnTouch] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnMove] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnControllerStatus] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnSwipe] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnScroll] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnDrag] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnFuse] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnPinch] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnRotate] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnCameraARHitTest] = false;
_enabledEventMap[VROEventDelegate::EventAction::OnARPointCloudUpdate] = false;
}
/*
Informs the renderer to enable / disable the triggering of
specific EventSource delegate callbacks.
*/
void setEnabledEvent(VROEventDelegate::EventAction type, bool enabled) {
_enabledEventMap[type] = enabled;
}
bool isEventEnabled(VROEventDelegate::EventAction type) {
return _enabledEventMap[type];
}
/*
Delegate events triggered by the VROInputControllerBase.
*/
virtual void onHover(int source, std::shared_ptr<VRONode> node, bool isHovering, std::vector<float> position) {
//No-op
}
virtual void onClick(int source, std::shared_ptr<VRONode> node, ClickState clickState, std::vector<float> position) {
//No-op
}
virtual void onTouch(int source, std::shared_ptr<VRONode> node, TouchState touchState, float x, float y) {
//No-op
}
virtual void onMove(int source, std::shared_ptr<VRONode> node, VROVector3f rotation, VROVector3f position, VROVector3f forwardVec) {
//No-op
}
virtual void onControllerStatus(int source, ControllerStatus status) {
//No-op
}
virtual void onGazeHit(int source, std::shared_ptr<VRONode> node, const VROHitTestResult &hit) {
//No-op
}
virtual void onSwipe(int source, std::shared_ptr<VRONode> node, SwipeState swipeState) {
//No-op
}
virtual void onScroll(int source, std::shared_ptr<VRONode> node, float x, float y) {
//No-op
}
virtual void onDrag(int source, std::shared_ptr<VRONode> node, VROVector3f newPosition) {
//No-op
}
virtual void onFuse(int source, std::shared_ptr<VRONode> node, float timeToFuseRatio) {
//No-op
}
virtual void onPinch(int source, std::shared_ptr<VRONode> node, float scaleFactor, PinchState pinchState) {
//No-op
}
virtual void onRotate(int source, std::shared_ptr<VRONode> node, float rotationRadians, RotateState rotateState) {
//No-op
}
virtual void onCameraARHitTest(std::vector<VROARHitTestResult> results) {
//No-op
}
virtual void onARPointCloudUpdate(std::shared_ptr<VROARPointCloud> pointCloud) {
//No-op
}
void setTimeToFuse(float durationInMillis){
_timeToFuseDuration = durationInMillis;
}
float getTimeToFuse(){
return _timeToFuseDuration;
}
private:
std::map<VROEventDelegate::EventAction , bool> _enabledEventMap;
/*
Duration used to count down from for triggering onFuse events, in milliseconds.
Defaults to 2000 milliseconds.
*/
float _timeToFuseDuration = 2000;
};
#endif

View File

@@ -0,0 +1,90 @@
//
// VRORenderDelegateiOS.h
// ViroRenderer
//
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROEventDelegateiOS_h
#define VROEventDelegateiOS_h
#import "VROEventDelegate.h"
#import <Foundation/Foundation.h>
#import "VROARPointCloud.h"
/*
Protocol to be implemented by objective C controls to be
set on VROEventDelegateiOS for the notification of
input events.
*/
@protocol VROEventDelegateProtocol<NSObject>
@required
- (void)onHover:(int)source node:(std::shared_ptr<VRONode>)node isHovering:(bool)isHovering hoverLocation:(std::vector<float>)location;
- (void)onClick:(int)source node:(std::shared_ptr<VRONode>)node clickState:(VROEventDelegate::ClickState)clickState clickLocation:(std::vector<float>)location;
- (void)onFuse:(int)source node:(std::shared_ptr<VRONode>)node;
- (void)onDrag:(int)source node:(std::shared_ptr<VRONode>)node posX:(float)x posY:(float)y posZ:(float)y;
- (void)onPinch:(int)source node:(std::shared_ptr<VRONode>)node scaleFactor:(float)scale pinchState:(VROEventDelegate::PinchState)pinchState;
- (void)onRotate:(int)source node:(std::shared_ptr<VRONode>)node rotationRadians:(float)rotationRadians rotateState:(VROEventDelegate::RotateState)rotateState;
- (void)onCameraARHitTest:(std::vector<VROARHitTestResult>) results;
- (void)onARPointCloudUpdate:(std::shared_ptr<VROARPointCloud>) pointCloud;
@end
/*
iOS implementation of VROEventDelegate for the notification
of delegate events across the bridge.
*/
class VROEventDelegateiOS : public VROEventDelegate {
public:
VROEventDelegateiOS(id<VROEventDelegateProtocol> delegate) :
_delegate(delegate) {}
virtual ~VROEventDelegateiOS() {}
/*
Delegate events triggered by the EventManager.
*/
virtual void onHover(int source, std::shared_ptr<VRONode> node, bool isHovering, std::vector<float> location) {
[_delegate onHover:source node:node isHovering:isHovering hoverLocation:location];
}
virtual void onClick(int source, std::shared_ptr<VRONode> node, ClickState clickState, std::vector<float> location) {
[_delegate onClick:source node:node clickState:clickState clickLocation:location];
}
virtual void onFuse(int source, std::shared_ptr<VRONode> node, float timeToFuseRatio) {
/*
As onFuse is also used by internal components to update ui based
on timeToFuse ratio, we only want to notify our bridge components
if we have successfully fused (if timeToFuseRatio has counted down to 0).
*/
if (timeToFuseRatio > 0.0f){
return;
}
[_delegate onFuse:source node:node];
}
virtual void onCameraARHitTest(std::vector<VROARHitTestResult> results) {
[_delegate onCameraARHitTest:results];
}
virtual void onDrag(int source, std::shared_ptr<VRONode> node, VROVector3f position) {
[_delegate onDrag:source node:node posX:position.x posY:position.y posZ:position.z];
}
virtual void onPinch(int source, std::shared_ptr<VRONode> node, float scale, PinchState pinchState) {
[_delegate onPinch:source node:node scaleFactor:scale pinchState:pinchState];
}
virtual void onRotate(int source, std::shared_ptr<VRONode> node, float rotationRadians, RotateState rotateState) {
[_delegate onRotate:source node:node rotationRadians:rotationRadians rotateState:rotateState];
}
virtual void onARPointCloudUpdate(std::shared_ptr<VROARPointCloud> pointCloud) {
[_delegate onARPointCloudUpdate:pointCloud];
}
private:
__weak id<VROEventDelegateProtocol> _delegate;
};
#endif /* VROEventDelegateiOS_h */

View File

@@ -0,0 +1,44 @@
//
// VROExecutableAnimation.h
// ViroRenderer
//
// Created by Raj Advani on 1/4/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROExecutableAnimation_h
#define VROExecutableAnimation_h
#include <memory>
#include <functional>
class VRONode;
class VROTransaction;
class VROExecutableAnimation {
public:
VROExecutableAnimation() {}
virtual ~VROExecutableAnimation() {}
/*
Produce a copy of this animation.
*/
virtual std::shared_ptr<VROExecutableAnimation> copy() = 0;
/*
Execute this animation. The onFinished() callback will be invoked when the
animation is fully executed (if it has children, this is when the last child
finishes executing).
*/
virtual void execute(std::shared_ptr<VRONode> node,
std::function<void()> onFinished) = 0;
virtual void pause() = 0;
virtual void resume() = 0;
virtual void terminate(bool jumpToEnd) = 0;
virtual std::string toString() const = 0;
};
#endif /* VROExecutableAnimation_h */

View File

@@ -0,0 +1,101 @@
//
// VROFBXLoader.h
// ViroRenderer
//
// Created by Raj Advani on 5/1/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROFBXLoader_h
#define VROFBXLoader_h
#include <vector>
#include <string>
#include <memory>
#include <map>
#include <functional>
#include "VROGeometrySource.h"
#include "VROGeometryElement.h"
#include "VROMaterial.h"
#include "VROModelIOUtil.h"
class VRONode;
class VROTexture;
class VROGeometry;
class VROSkinner;
class VROSkeleton;
class VROSkeletalAnimation;
class VROKeyframeAnimation;
namespace viro {
class Node;
class Node_Geometry;
class Node_Skeleton;
class Node_Geometry_Skin;
class Node_SkeletalAnimation;
class Node_KeyframeAnimation;
}
class VROFBXLoader {
public:
/*
Load the FBX node subgraph at the given resource, into the given node.
For all dependent resources (e.g. textures) found, locate them in the
parent folder of the resource.
If async is true, the FBX is loaded in the background. Afterward, the
geometry and child-nodes are injected into the node on the main (rendering)
thread, and the given callback is invoked.
If async is false, the callback is still executed.
*/
static void loadFBXFromResource(std::string file, VROResourceType type, std::shared_ptr<VRONode> destination,
bool async = false, std::function<void(std::shared_ptr<VRONode> node, bool success)> onFinish = nullptr);
static void loadFBXFromResources(std::string file, VROResourceType type, std::shared_ptr<VRONode> destination,
std::map<std::string, std::string> resourceMap,
bool async = false, std::function<void(std::shared_ptr<VRONode> node, bool success)> onFinish = nullptr);
private:
static void injectFBX(std::shared_ptr<VRONode> fbxNode, std::shared_ptr<VRONode> node,
std::function<void(std::shared_ptr<VRONode> node, bool success)> onFinish);
/*
Load the FBX subgraph for the given file. The top-level node returned here is a dummy; all the
data is stored in its children.
*/
static std::shared_ptr<VRONode> loadFBX(std::string file, std::string base, VROResourceType type,
const std::map<std::string, std::string> *resourceMap);
static std::shared_ptr<VRONode> loadFBXNode(const viro::Node &node_pb,
std::shared_ptr<VROSkeleton> skeleton,
std::string base, VROResourceType type,
const std::map<std::string, std::string> *resourceMap,
std::map<std::string, std::shared_ptr<VROTexture>> &textureCache);
static std::shared_ptr<VROGeometry> loadFBXGeometry(const viro::Node_Geometry &geo_pb,
std::string base, VROResourceType type,
const std::map<std::string, std::string> *resourceMap,
std::map<std::string, std::shared_ptr<VROTexture>> &textureCache);
static std::shared_ptr<VROSkeleton> loadFBXSkeleton(const viro::Node_Skeleton &skeleton_pb);
static std::unique_ptr<VROSkinner> loadFBXSkinner(const viro::Node_Geometry_Skin &skin_pb,
std::shared_ptr<VROSkeleton> skeleton);
static std::shared_ptr<VROSkeletalAnimation> loadFBXSkeletalAnimation(const viro::Node_SkeletalAnimation &animation_pb,
std::shared_ptr<VROSkeleton> skeleton);
static std::shared_ptr<VROKeyframeAnimation> loadFBXKeyframeAnimation(const viro::Node_KeyframeAnimation &animation_pb);
/*
Remove nodes that do not have any geometry in their sub-graph. These nodes
are empty cruft that do not need to be loaded into the renderer (in fact if
they are loaded in, they can cause significant CPU churn as we recurse down
them each frame).
*/
static void trimEmptyNodes(std::shared_ptr<VRONode> node);
static bool nodeHasGeometryRecursive(std::shared_ptr<VRONode> node);
};
#endif /* VROFBXLoader_h */

View File

@@ -0,0 +1,107 @@
//
// VROFieldOfView.cpp
// ViroRenderer
//
// Created by Raj Advani on 10/23/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROFieldOfView_h
#define VROFieldOfView_h
#include "VROMath.h"
enum class VROFieldOfViewAxis {
X, Y
};
/*
Represents the field of view in each direction, in degrees.
*/
class VROFieldOfView {
public:
VROFieldOfView() :
_left(s_defaultViewAngle),
_right(s_defaultViewAngle),
_bottom(s_defaultViewAngle),
_top(s_defaultViewAngle)
{}
VROFieldOfView(float left, float right, float bottom, float top) :
_left(left),
_right(right),
_bottom(bottom),
_top(top)
{}
VROFieldOfView(const VROFieldOfView *other) :
_left(other->_left),
_right(other->_right),
_bottom(other->_bottom),
_top(other->_top)
{}
void setLeft(float left) {
_left = left;
}
float getLeft() const {
return _left;
}
void setRight(float right) {
_right = right;
}
float getRight() const {
return _right;
}
void setBottom(float bottom) {
_bottom = bottom;
}
float getBottom() const {
return _bottom;
}
void setTop(float top) {
_top = top;
}
float getTop() const {
return _top;
}
VROMatrix4f toPerspectiveProjection(float near, float far) {
float left = -tanf(degrees_to_radians(_left)) * near;
float right = tanf(degrees_to_radians(_right)) * near;
float bottom = -tanf(degrees_to_radians(_bottom)) * near;
float top = tanf(degrees_to_radians(_top)) * near;
return VROMathComputeFrustum(left, right, bottom, top, near, far);
}
bool equals(const VROFieldOfView *other) const {
if (other == nullptr) {
return false;
}
else if (other == this) {
return true;
}
return (_left == other->_left) &&
(_right == other->_right) &&
(_bottom == other->_bottom) &&
(_top == other->_top);
}
private:
constexpr static float s_defaultViewAngle = 40.0f;
float _left;
float _right;
float _bottom;
float _top;
};
#endif

View File

@@ -0,0 +1,29 @@
//
// VROFrameListener.h
// ViroRenderer
//
// Created by Raj Advani on 1/7/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROFrameListener_h
#define VROFrameListener_h
#include <stdio.h>
class VRORenderContext;
/*
Interface for responding to frame begin and end events.
*/
class VROFrameListener {
public:
virtual ~VROFrameListener() {}
virtual void onFrameWillRender(const VRORenderContext &context) = 0;
virtual void onFrameDidRender(const VRORenderContext &context) = 0;
};
#endif /* VROFrameListener_h */

View File

@@ -0,0 +1,77 @@
//
// VROFrameScheduler.h
// ViroRenderer
//
// Created by Raj Advani on 4/5/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROFrameScheduler_h
#define VROFrameScheduler_h
#include "VROFrameTimer.h"
#include <functional>
#include <queue>
#include <mutex>
#include <string>
#include <set>
struct VROFrameTask {
std::string key;
std::function<void()> functor;
};
/*
Schedules tasks to be run on the rendering thread. Unlike
VROPlatformDispatchRenderer, these tasks are run in a time-limited
queue; they are scheduled to run only when time is available in
the current frame. Time remaining in a frame is determined by a
set milliseconds-per-frame (mpf) target.
*/
class VROFrameScheduler {
public:
VROFrameScheduler();
virtual ~VROFrameScheduler();
/*
Schedule a new task to be completed in the time-limited
queue. The key should uniquely identify the task, and is used
to de-dupe tasks that are scheduled multiple times.
*/
void scheduleTask(std::string key, std::function<void()> task);
/*
Process as many tasks as allowed given the remaining frame
time.
*/
void processTasks(const VROFrameTimer &timer);
private:
/*
The number of frames that have passed, during which we had at
lease one task to process but no time to process any.
*/
int _starvationFrameCount;
/*
Guards the _taskQueue and _queuedTasks set.
*/
std::recursive_mutex _taskQueueMutex;
/*
The actual queue we use to process tasks in FIFO order.
*/
std::queue<VROFrameTask> _taskQueue;
/*
Set used to prevent the same task from being queued
multiple times, based on its ID.
*/
std::set<std::string> _queuedTasks;
};
#endif /* VROFrameScheduler_h */

View File

@@ -0,0 +1,27 @@
//
// VROFrameSynchronizer.h
// ViroRenderer
//
// Created by Raj Advani on 4/27/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROFrameSynchronizer_h
#define VROFrameSynchronizer_h
#include <memory>
class VROFrameListener;
class VROFrameSynchronizer {
public:
virtual ~VROFrameSynchronizer() {}
virtual void addFrameListener(std::shared_ptr<VROFrameListener> listener) = 0;
virtual void removeFrameListener(std::shared_ptr<VROFrameListener> listener) = 0;
};
#endif /* VROFrameSynchronizer_h */

View File

@@ -0,0 +1,70 @@
//
// VROFrameTimer.h
// ViroRenderer
//
// Created by Raj Advani on 4/5/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROFrameTimer_h
#define VROFrameTimer_h
#include "VROTime.h"
/*
Startup frames have unlimited processing time; process-only
frames are frames in which we only process and do not render.
*/
enum class VROFrameType {
Normal,
Startup,
ProcessOnly
};
/*
Tracks how much time remains in the current frame for processing
tasks.
*/
class VROFrameTimer {
public:
VROFrameTimer(VROFrameType frameType, double timeForProcessing, double lastFrameEndTime) :
_frameType(frameType),
_timeForProcessing(timeForProcessing),
_lastFrameEndTime(lastFrameEndTime) {
}
/*
Returns true if there is time remaining for any processing operations in the
current frame.
*/
bool isTimeRemainingInFrame() const {
return _frameType == VROFrameType::Startup || getTimeRemainingInFrame() > 0;
}
double getTimeRemainingInFrame() const {
return _timeForProcessing - (VROTimeCurrentMillis() - _lastFrameEndTime);
}
private:
/*
The frame 'type'. Startup frames have unlimited processing time; process-only
frames are frames in which we only process() and do not render().
*/
const VROFrameType _frameType;
/*
The time available for processing this frame, in ms.
*/
const double _timeForProcessing;
/*
The end time of the last frame, in ms.
*/
const double _lastFrameEndTime;
};
#endif /* VROFrameTimer_h */

View File

@@ -0,0 +1,96 @@
//
// VROFrustum.h
// ViroRenderer
//
// Created by Raj Advani on 10/15/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROFRUSTUM_H_
#define VROFRUSTUM_H_
#include "VROFrustumPlane.h"
#include "VROVector3f.h"
#include "VROFrustumBoxIntersectionMetadata.h"
/*
Plane identifiers.
*/
enum class VROFrustumSide : int {
Left = 0,
Right = 1,
Bottom = 2,
Top = 3,
Near = 4,
Far = 5
};
/*
Enum for intersection testing results.
*/
enum class VROFrustumResult {
Inside,
Intersects,
Outside
};
class VROFrustum {
public:
/*
Create a new frustum.
*/
explicit VROFrustum();
virtual ~VROFrustum();
/*
Generic initialization.
*/
void fitToModelView(const float *view, const float *projection,
const float bufferSides, const float bufferNear, const float bufferFar);
/*
Intersection testing (automatically chooses best method).
*/
VROFrustumResult intersect(const VROBoundingBox &box, VROFrustumBoxIntersectionMetadata *metadata) const;
/*
Intersect this frustum with a bounding box, utilizing the far points optimization and
temporal coherency optimizations.
*/
VROFrustumResult intersectAllOpt(const VROBoundingBox &box, VROFrustumBoxIntersectionMetadata *metadata) const;
/*
Frustum intersection using the "far point" optimization. The far point optimization enables us
to determine if there's an intersection between a frustum and an AABB using only two plane->point
distance calculations per frustum plane.
*/
VROFrustumResult intersectWithFarPointsOpt(const VROBoundingBox &box) const;
/*
Robust frustum intersection, using no optimizations.
*/
VROFrustumResult intersectNoOpt(const VROBoundingBox &box) const;
/*
Check if the given point is contained by this frustum.
*/
bool containsPoint(const VROVector3f &point) const;
/*
Get the distance of the given point from the near or far clipping plane of this
frustum.
*/
float distanceFromFCP(VROVector3f pt) const;
float distanceFromNCP(VROVector3f pt) const;
private:
/*
The planes composing this frustum: left, right, bottom, top, near, far.
*/
VROFrustumPlane _planes[6];
};
#endif /* VROFRUSTUM_H_ */

View File

@@ -0,0 +1,46 @@
//
// VROFrustumBoxIntersectionMetadata.hpp
// ViroRenderer
//
// Created by Raj Advani on 4/17/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROFrustumBoxIntersectionMetadata_h
#define VROFrustumBoxIntersectionMetadata_h
#include <math.h>
#include <stdint.h>
class VROFrustum;
/*
Stores metadata about the intersection between a given VROFrustum
and VROBoundingBox, which can be utilized to accelerate intersection
computations between the same frustum and box in subsequent
frames.
*/
class VROFrustumBoxIntersectionMetadata {
public:
VROFrustumBoxIntersectionMetadata();
~VROFrustumBoxIntersectionMetadata();
uint8_t getPlaneLastOutside() const {
return _planeLastOutside;
}
void setPlaneLastOutside(uint8_t plane) {
_planeLastOutside = plane;
}
private:
/*
The plane of the frustum the bounding-box was last outside.
*/
uint8_t _planeLastOutside;
};
#endif /* VROFrustumBoxIntersectionMetadata_h */

View File

@@ -0,0 +1,36 @@
//
// VROFrustumPlane.h
// ViroRenderer
//
// Created by Raj Advani on 10/15/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROFRUSTUMPLANE_H_
#define VROFRUSTUMPLANE_H_
#include "VROPlane.h"
#include "VROBoundingBox.h"
typedef enum {
VROFarPointPosX = 0,
VROFarPointPosY = 1,
VROFarPointPosZ = 2,
VROFarPointNegX = 3,
VROFarPointNegY = 4,
VROFarPointNegZ = 5
} VROFarPoint;
class VROFrustumPlane : public VROPlane {
public:
VROBoxPlane farPoints[6];
VROFrustumPlane();
virtual ~VROFrustumPlane();
void refreshFarPoints();
};
#endif /* VROFRUSTUMPLANE_H_ */

View File

@@ -0,0 +1,287 @@
//
// VROGeometry.h
// ViroRenderer
//
// Created by Raj Advani on 11/17/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROGeometry_h
#define VROGeometry_h
#include <stdio.h>
#include <vector>
#include <string>
#include <memory>
#include "VRORenderContext.h"
#include "VRODriver.h"
#include "VROSortKey.h"
#include "VROBoundingBox.h"
#include "VROAnimatable.h"
#include "VROSkinner.h"
#include "VROAllocationTracker.h"
class VRONode;
class VROLight;
class VROSortKey;
class VROMaterial;
class VROTexture;
class VROGeometryElement;
class VROGeometrySource;
class VROGeometrySubstrate;
class VROMatrix4f;
class VROInstancedUBO;
class VRORenderMetadata;
enum class VROGeometrySourceSemantic;
/*
Represents a three-dimensional shape, a collection of vertices, normals and texture coordinates
that define a surface, also known as a model or mesh. Geometries attached to VRONode objects form
the visible elements of a scene, and VROMaterial objects attached to a geometry determine its
appearance.
*/
class VROGeometry : public VROAnimatable {
public:
/*
Construct a new geometry with the given sources and elements.
*/
VROGeometry(std::vector<std::shared_ptr<VROGeometrySource>> sources,
std::vector<std::shared_ptr<VROGeometryElement>> elements) :
_geometrySources(sources),
_geometryElements(elements),
_cameraEnclosure(false),
_screenSpace(false),
_bounds(nullptr),
_substrate(nullptr),
_instancedUBO(nullptr){
ALLOCATION_TRACKER_ADD(Geometry, 1);
}
/*
Construct a new geometry with no sources or elements. These are expected
to be set by the subclass.
*/
VROGeometry() :
_cameraEnclosure(false),
_screenSpace(false),
_bounds(nullptr),
_substrate(nullptr) {
ALLOCATION_TRACKER_ADD(Geometry, 1);
}
/*
Copy the given geometry. The materials will *not* be copied, and the
underlying immutable geometry data will be shared.
*/
VROGeometry(std::shared_ptr<VROGeometry> geometry) :
_geometrySources(geometry->_geometrySources),
_geometryElements(geometry->_geometryElements) {
ALLOCATION_TRACKER_ADD(Geometry, 1);
}
virtual ~VROGeometry();
/*
Delete any rendering resources. Invoked prior to destruction, on the
rendering thread.
*/
void deleteGL();
/*
Get the geometry ready for usage now, in advance of when it's visible. If not invoked,
the geometry will be initialized when it is made visible.
*/
void prewarm(std::shared_ptr<VRODriver> driver);
/*
Render the given element of the geometry with full texturing and
lighting. Assumes the material's shader and geometry-independent
properties have already been bound.
*/
void render(int elementIndex,
const std::shared_ptr<VROMaterial> &material,
VROMatrix4f transform,
VROMatrix4f normalMatrix,
float opacity,
const VRORenderContext &context,
std::shared_ptr<VRODriver> &driver);
/*
Render the silhouette of the entire geometry (all elements). Renders
using the given material, which is assumed to already be bound, ignoring
texturing and lighting. Typically this is used for rendering to a stencil
buffer or shadow map.
*/
void renderSilhouette(VROMatrix4f transform,
std::shared_ptr<VROMaterial> &material,
const VRORenderContext &context,
std::shared_ptr<VRODriver> &driver);
/*
Render the silhouette of the given element of the given geometry.
Renders using the provided material, which is assumed to already be
bound, and binds its associated texture.
*/
void renderSilhouetteTextured(int element,
VROMatrix4f transform,
std::shared_ptr<VROMaterial> &material,
const VRORenderContext &context,
std::shared_ptr<VRODriver> &driver);
void updateSortKeys(VRONode *node, uint32_t hierarchyId, uint32_t hierarchyDepth,
uint32_t lightsHash, const std::vector<std::shared_ptr<VROLight>> &lights,
float opacity, float distanceFromCamera, float zFar,
std::shared_ptr<VRORenderMetadata> &metadata,
const VRORenderContext &context,
std::shared_ptr<VRODriver> &driver);
void getSortKeys(std::vector<VROSortKey> *outKeys);
std::shared_ptr<VROMaterial> &getMaterialForElement(int elementIndex) {
return _materials[elementIndex % _materials.size()];
}
virtual void setMaterials(std::vector<std::shared_ptr<VROMaterial>> materials) {
_materials = materials;
}
const std::vector<std::shared_ptr<VROMaterial>> &getMaterials() {
return _materials;
}
const std::vector<std::shared_ptr<VROGeometrySource>> &getGeometrySources() const {
return _geometrySources;
}
const std::vector<std::shared_ptr<VROGeometryElement>> &getGeometryElements() const {
return _geometryElements;
}
const VROBoundingBox &getBoundingBox();
void updateBoundingBox();
VROVector3f getCenter();
bool isCameraEnclosure() const {
return _cameraEnclosure;
}
void setCameraEnclosure(bool enabled) {
_cameraEnclosure = enabled;
}
bool isScreenSpace() const {
return _screenSpace;
}
void setScreenSpace(bool screenSpace) {
_screenSpace = screenSpace;
}
std::string getName() const {
return _name;
}
void setName(std::string name) {
_name = name;
}
const std::unique_ptr<VROSkinner> &getSkinner() const {
return _skinner;
}
void setSkinner(std::unique_ptr<VROSkinner> skinner) {
_skinner = std::move(skinner);
}
std::vector<std::shared_ptr<VROGeometrySource>> getGeometrySourcesForSemantic(VROGeometrySourceSemantic semantic) const;
void setInstancedUBO(std::shared_ptr<VROInstancedUBO> instancedUBO) {
_instancedUBO = instancedUBO;
}
const std::shared_ptr<VROInstancedUBO> &getInstancedUBO() const{
return _instancedUBO;
}
protected:
void setSources(std::vector<std::shared_ptr<VROGeometrySource>> sources) {
_geometrySources = sources;
updateSubstrate();
}
void setElements(std::vector<std::shared_ptr<VROGeometryElement>> elements) {
_geometryElements = elements;
updateSubstrate();
}
private:
/*
User-assigned name of this geometry.
*/
std::string _name;
/*
The materials, which define the surface appearance (color, lighting, texture, and effects)
of each geometry element.
If a geometry has the same number of materials as it has geometry elements, the material
index corresponds to the element index. For geometries with fewer materials than elements,
the material index for each element is determined by calculating the index of that element
modulo the number of materials. For example, in a geometry with six elements and three materials,
the element at index 5 is rendered using the material at index 5 % 3 = 2.
*/
std::vector<std::shared_ptr<VROMaterial>> _materials;
std::vector<std::shared_ptr<VROGeometrySource>> _geometrySources;
std::vector<std::shared_ptr<VROGeometryElement>> _geometryElements;
/*
Used for sorting the elements prior to rendering.
*/
std::vector<VROSortKey> _sortKeys;
/*
True if this geometry is a camera enclosure, e.g. a skybox. Camera enclosures follow
the camera and ignore interlens distance (since they generally simulate far away objects).
*/
bool _cameraEnclosure;
/*
True if this geometry's coordinates are specified in screen space; e.g., the coordinates of
the viewport. If true, then the geometry will be rendered orthographically (ignoring perspective)
and with an identity view matrix (ignoring the camera). The geometry may still have
node transforms.
*/
bool _screenSpace;
/*
The bounding box of this geometry. Created on demand, then cached.
*/
VROBoundingBox *_bounds;
/*
Representation of this geometry in the underlying graphics library.
*/
VROGeometrySubstrate *_substrate;
/*
The skinner ties this geometry to a skeleton, enabling skeletal animation.
*/
std::unique_ptr<VROSkinner> _skinner;
/*
If this geometry has no source data installed (_geometrySources and _geometryElements),
then returns false.
*/
bool isRenderable() const;
/*
Invoke when the substrate needs to be refreshed (typically when underlying
geometry sources or elements change).
*/
void updateSubstrate();
/*
If set, this geometry is instanced rendered with the configurations set by this
instancedUBO.
*/
std::shared_ptr<VROInstancedUBO> _instancedUBO;
};
#endif /* VROGeometry_h */

View File

@@ -0,0 +1,94 @@
//
// VROGeometryElement.h
// ViroRenderer
//
// Created by Raj Advani on 11/17/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROGeometryElement_h
#define VROGeometryElement_h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory>
#include <functional>
#include "VROData.h"
#include "VROTriangle.h"
class VROGeometrySource;
enum class VROGeometryPrimitiveType {
Triangle,
TriangleStrip,
Line,
Point
};
/*
Describes how vertices are connected to form the surface of a three-dimensional object, or geometry.
Used in conjunction with VROGeometrySource.
*/
class VROGeometryElement {
public:
VROGeometryElement(std::shared_ptr<VROData> data,
VROGeometryPrimitiveType primitiveType,
int primitiveCount,
int bytesPerIndex) :
_primitiveType(primitiveType),
_primitiveCount(primitiveCount),
_data(data),
_bytesPerIndex(bytesPerIndex)
{}
std::shared_ptr<VROData> getData() const {
return _data;
}
VROGeometryPrimitiveType getPrimitiveType() const {
return _primitiveType;
}
int getPrimitiveCount() const {
return _primitiveCount;
}
int getBytesPerIndex() const {
return _bytesPerIndex;
}
/*
Read through the indices in this element, read the corresponding vertices
from the given geometry source, and invoke the provided function once per
triangle.
*/
void processTriangles(std::function<void(int index, VROTriangle triangle)> function,
std::shared_ptr<VROGeometrySource> geometrySource) const;
/*
Read the indexes in this element, one by one.
*/
void processIndices(std::function<void(int index, int indexRead)> function) const;
private:
/*
The type of the primitives we should create from the associated geometry
source using the indices in this element.
*/
VROGeometryPrimitiveType _primitiveType;
/*
The number of triangles, triangle strips, etc.
*/
const int _primitiveCount;
/*
The index data, and the size of each index.
*/
std::shared_ptr<VROData> _data;
const int _bytesPerIndex;
};
#endif /* VROGeometryElement_h */

View File

@@ -0,0 +1,158 @@
//
// VROGeometrySource.h
// ViroRenderer
//
// Created by Raj Advani on 11/17/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROGeometrySource_h
#define VROGeometrySource_h
#include <stdio.h>
#include <memory>
#include <functional>
#include "VROData.h"
#include "VROBoundingBox.h"
enum class VROGeometrySourceSemantic {
Vertex,
Normal,
Color,
Texcoord,
Tangent,
VertexCrease,
EdgeCrease,
BoneWeights,
BoneIndices,
Invalid
};
/*
Specifies per-vertex data for the set of vertices forming the surface of a three-dimensional
object, or geometry. Used together with VROGeometryElement objects to define custom VROGeometry objects
or to inspect the data that composes an existing geometry.
*/
class VROGeometrySource {
public:
VROGeometrySource(std::shared_ptr<VROData> data,
VROGeometrySourceSemantic semantic,
int vertexCount,
bool floatComponents,
int componentsPerVertex,
int bytesPerComponent,
int dataOffset,
int dataStride) :
_data(data),
_semantic(semantic),
_vertexCount(vertexCount),
_floatComponents(floatComponents),
_componentsPerVertex(componentsPerVertex),
_bytesPerComponent(bytesPerComponent),
_dataOffset(dataOffset),
_dataStride(dataStride)
{}
VROGeometrySource(std::shared_ptr<VROData> data,
std::shared_ptr<VROGeometrySource> templateSource) :
_data(data),
_semantic(templateSource->getSemantic()),
_vertexCount(templateSource->getVertexCount()),
_floatComponents(templateSource->isFloatComponents()),
_componentsPerVertex(templateSource->getComponentsPerVertex()),
_bytesPerComponent(templateSource->getBytesPerComponent()),
_dataOffset(templateSource->getDataOffset()),
_dataStride(templateSource->getDataStride())
{}
std::shared_ptr<VROData> getData() const {
return _data;
}
VROGeometrySourceSemantic getSemantic() const {
return _semantic;
}
int getVertexCount() const {
return _vertexCount;
}
int getComponentsPerVertex() const {
return _componentsPerVertex;
}
int getBytesPerComponent() const {
return _bytesPerComponent;
}
int getDataOffset() const {
return _dataOffset;
}
int getDataStride() const {
return _dataStride;
}
bool isFloatComponents() const {
return _floatComponents;
}
/*
Read through all the vertices in this data source and invoke the provided
callback for each.
*/
void processVertices(std::function<void(int index, VROVector3f vertex)> function) const;
/*
Read through all vertices in this data source and modify them.
*/
void modifyVertices(std::function<VROVector3f(int index, VROVector3f vertex)> function) const;
/*
Retrieves the bounding box for the values associated with this
geometry source. Generally only makes sense to invoke this method
for VROGeometrySourceSemantic::Vertex.
*/
VROBoundingBox getBoundingBox() const;
private:
/*
The interleaved raw vertex data.
*/
std::shared_ptr<VROData> _data;
/*
The attribute the geometry source is describing for each vertex.
*/
VROGeometrySourceSemantic _semantic;
/*
The number of vertices described in the _data array.
*/
int _vertexCount;
/*
True if the components are floating point. False if integer.
*/
bool _floatComponents;
/*
The number of scalar components per vertex (i.e. x, y, z for position).
*/
int _componentsPerVertex;
/*
The number of bytes per scalar component (i.e. 4 for floats).
*/
int _bytesPerComponent;
/*
The offset in the data array at which point this source's data begins. Used
for interleaving a vertex array.
*/
int _dataOffset;
/*
The number of bytes from one vertex in the data to the next.
*/
int _dataStride;
};
#endif /* VROGeometrySource_h */

View File

@@ -0,0 +1,52 @@
//
// VROGeometryUtil.h
// ViroRenderer
//
// Created by Raj Advani on 3/2/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROGeometryUtil_h
#define VROGeometryUtil_h
#include <stdio.h>
#include <memory>
#include <vector>
class VROData;
class VROVector3f;
class VROGeometryElement;
class VROGeometrySource;
class VRONode;
enum class VROGeometrySourceSemantic;
enum class VROGeometryPrimitiveType;
/*
Return one VRONode per VROGeometryElement. The position of the node will be set
to the center of each element's vertices.
*/
std::vector<std::shared_ptr<VRONode>> VROGeometryUtilSplitNodeByGeometryElements(std::shared_ptr<VRONode> node);
/*
Find the vertices used by the geometry element in the given source and center them.
Return the newly allocated, centered vertex data. Store the center in the given out
variable.
*/
std::shared_ptr<VROData> VROGeometryUtilExtractAndCenter(std::shared_ptr<VROGeometryElement> element,
std::shared_ptr<VROGeometrySource> geometrySource,
VROVector3f *outCenter);
/*
Get how many indices are required to render the given number of primitives of the
given type, and vice-versa.
*/
int VROGeometryUtilGetIndicesCount(int primitiveCount, VROGeometryPrimitiveType primitiveType);
int VROGeometryUtilGetPrimitiveCount(int indicesCount, VROGeometryPrimitiveType primitiveType);
/*
Parse the attribute index for the given semantic.
*/
int VROGeometryUtilParseAttributeIndex(VROGeometrySourceSemantic semantic);
#endif /* VROGeometryUtil_h */

View File

@@ -0,0 +1,38 @@
//
// VROHDRLoader.h
// ViroKit
//
// Created by Raj Advani on 1/22/18.
// Copyright © 2018 Viro Media. All rights reserved.
//
#ifndef VROHDRLoader_h
#define VROHDRLoader_h
#include <stdio.h>
#include <string>
#include <memory>
class VROTexture;
enum class VROTextureInternalFormat;
/*
Converts HDR images to RGB9_E5 format so that they can be read by OpenGL ES.
*/
class VROHDRLoader {
public:
/*
Loads the Radiance HDR texture (.hdr) at the given path. The data will
be internally stored in RGB9_E5 format.
*/
static std::shared_ptr<VROTexture> loadRadianceHDRTexture(std::string hdrPath);
private:
static std::shared_ptr<VROTexture> loadTexture(float *data, int width, int height,
int componentsPerPixel);
};
#endif /* VROHDRLoader_h */

View File

@@ -0,0 +1,63 @@
//
// VROHitTestResult.h
// ViroRenderer
//
// Created by Raj Advani on 1/13/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROHitTestResult_h
#define VROHitTestResult_h
#include "VROVector3f.h"
#include "VROCamera.h"
#include <memory>
class VRONode;
class VROHitTestResult {
public:
VROHitTestResult(std::shared_ptr<VRONode> node, VROVector3f location, float distance, bool background,
const VROCamera &camera) :
_node(node),
_location(location),
_distance(distance),
_background(background),
_camera(camera)
{}
~VROHitTestResult() {}
std::shared_ptr<VRONode> getNode() const {
return _node;
}
VROVector3f getLocation() const {
return _location;
}
float getDistance() const {
return _distance;
}
bool isBackgroundHit() const {
return _background;
}
const VROCamera &getCamera() const {
return _camera;
}
private:
std::shared_ptr<VRONode> _node;
VROVector3f _location;
float _distance;
bool _background;
VROCamera _camera;
};
#endif /* VROHitTestResult_h */

View File

@@ -0,0 +1,27 @@
//
// VROHoverDistanceListener.h
// ViroRenderer
//
// Created by Raj Advani on 4/1/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROHoverDistanceListener_h
#define VROHoverDistanceListener_h
#include <stdio.h>
/*
Attaches to a VROHoverController and receives a notification each
time the hover distance changes (the distance of the point on the object
hovered from the camera).
*/
class VROHoverDistanceListener {
public:
virtual void onHoverDistanceChanged(float distance, const VRORenderContext &context) = 0;
};
#endif /* VROHoverDistanceListener_h */

View File

@@ -0,0 +1,52 @@
//
// VROImage.hpp
// ViroRenderer
//
// Created by Raj Advani on 11/3/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROImage_h
#define VROImage_h
#include <stdio.h>
#include "VRODefines.h"
#include "VROTexture.h"
class VROImage {
public:
VROImage() {}
virtual ~VROImage() {}
virtual int getWidth() const = 0;
virtual int getHeight() const = 0;
/*
The data returned must be compatible with (convertible to) _format,
as per the table in the OpenGL ES spec:
https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glTexImage2D.xhtml
E.g., if internal format is RGB565, the data returned should be RGB8 or
RGB565. If internal format is RGBA8 or RGBA4, the data returned should be
RGBA8, etc.
*/
virtual unsigned char *getData(size_t *length) = 0;
VROTextureFormat getFormat() {
return _format;
}
protected:
/*
The format of the data returned by getData.
*/
VROTextureFormat _format;
};
#endif /* VROImage_h */

View File

@@ -0,0 +1,29 @@
//
// VROImageUtil.h
// ViroRenderer
//
// Created by Raj Advani on 10/21/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROImageUtil_h
#define VROImageUtil_h
#include <stdio.h>
#include <memory>
#include "VRODefines.h"
#if VRO_PLATFORM_IOS
#import <UIKit/UIKit.h>
#endif
class VRORenderContext;
class VROTexture;
void initBlankTexture(const VRORenderContext &context);
std::shared_ptr<VROTexture> getBlankTexture();
void initPointCloudTexture();
std::shared_ptr<VROTexture> getPointCloudTexture();
#endif /* VROImageUtil_h */

View File

@@ -0,0 +1,45 @@
//
// VROImageiOS.h
// ViroRenderer
//
// Created by Raj Advani on 11/3/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROImageiOS_h
#define VROImageiOS_h
#import "VROImage.h"
#import <UIKit/UIKit.h>
class VROImageiOS : public VROImage {
public:
/*
Construct a new VROImage from the given UIImage. The data will
be extracted from the UIImage into a format compatible with the
given target internal format.
*/
VROImageiOS(UIImage *image, VROTextureInternalFormat format);
virtual ~VROImageiOS();
int getWidth() const {
return _width;
}
int getHeight() const {
return _height;
}
unsigned char *getData(size_t *length);
private:
bool hasAlpha(UIImage *image);
int _width, _height;
int _dataLength;
unsigned char *_data;
};
#endif /* VROImageiOS_h */

View File

@@ -0,0 +1,296 @@
//
// VROInputControllerBase.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROInputControllerBase_h
#define VROInputControllerBase_h
#include <stdio.h>
#include <vector>
#include <string>
#include <memory>
#include <set>
#include <float.h>
#include "VROInputPresenter.h"
#include "VROScene.h"
#include "VRORenderContext.h"
#include "VROEventDelegate.h"
#include "VROHitTestResult.h"
#include "VRONode.h"
#include "VROGeometry.h"
static const float ON_DRAG_DISTANCE_THRESHOLD = 0.01;
static const float ON_PINCH_SCALE_THRESHOLD = 0.02;
static const float ON_ROTATE_THRESHOLD = 0.01; // in radians (~.5729 degrees)
static float kSceneBackgroundDistance = 8;
/*
Responsible for mapping generalized input data from a controller, to a unified
set of VROEventDelegate.EventTypes. It then notifies corresponding VROEventDelegates
in the current scene about the event type that has been triggered.
For example, VROInputControllerDaydream maps the onTouchPadClick event onto
a Viro onPrimaryClick event type within VROInputControllerBase, of which then notifies all
VROEventDelegates about such an event.
*/
class VROInputControllerBase {
public:
VROInputControllerBase();
virtual ~VROInputControllerBase(){}
/*
For testing background reticle distance.
*/
void debugMoveReticle();
/*
onProcess is to be implemented by derived classes to drive the processing
of platform-specific input events and map them to viro-specific input events.
*/
virtual void onProcess(const VROCamera &camera) {
//No-op
}
/*
Called when the renderer is about to be backgrounded within Android's lifecycle.
*/
virtual void onPause() {
// No-op
}
/*
Called when the renderer is about to be foregrounded within Android's lifecycle.
*/
virtual void onResume() {
// No-op
}
void attachScene(std::shared_ptr<VROScene> scene) {
_scene = scene;
}
void detachScene() {
_scene = nullptr;
}
/*
Set the current view and projection matrices.
*/
void setView(VROMatrix4f view);
void setProjection(VROMatrix4f projection);
/*
Get the presenter, creating it if it does not yet exist. Must be invoked on the
rendering thread.
*/
std::shared_ptr<VROInputPresenter> getPresenter() {
if (!_controllerPresenter) {
_controllerPresenter = createPresenter();
registerEventDelegate(_controllerPresenter);
}
return _controllerPresenter;
}
virtual std::string getHeadset() = 0;
virtual std::string getController() = 0;
/*
For notifying components outside the scene tree, we specifically register
them here to be tracked by the VROEventManager. Calling registerEventDelegate
twice with the same delegate will only have callbacks be triggered once.
*/
void registerEventDelegate(std::shared_ptr<VROEventDelegate> delegate){
_delegates.insert(delegate);
}
void removeEventDelegate(std::shared_ptr<VROEventDelegate> delegate){
_delegates.erase(delegate);
}
/*
Below are Viro-specific input events to be trigged by derived Input Controller
classes; these are the Viro-sepcific events that platform-specific events
are mapped to.
*/
void onControllerStatus(int source, VROEventDelegate::ControllerStatus status);
void onButtonEvent(int source, VROEventDelegate::ClickState clickAction);
void onTouchpadEvent(int source, VROEventDelegate::TouchState touchAction, float lastKnownX, float lastKnownY);
/*
The following position, rotation and forward are all in world coordinates.
*/
void onMove(int source, VROVector3f position, VROQuaternion rotation, VROVector3f forward);
void onSwipe(int source, VROEventDelegate::SwipeState swipeState);
void onScroll(int source, float x, float y);
/*
Pinch event that passes scale factor indicting the change in the pinch ratio
since the pinch started. Scale factor begins at 1 when pinch starts with
PinchState::PinchStart.
*/
void onPinch(int source, float scaleFactor, VROEventDelegate::PinchState pinchState);
void onRotate(int source, float rotationRadians, VROEventDelegate::RotateState rotateState);
protected:
virtual std::shared_ptr<VROInputPresenter> createPresenter(){
perror("Error: Derived class should create a presenter for BaseInputController to consume!");
return nullptr;
}
/*
This function returns the forward offset used in drag
*/
virtual VROVector3f getDragForwardOffset() = 0;
/*
Status of the current controller, for example if it's Connected / Disconnected.
*/
VROEventDelegate::ControllerStatus _currentControllerStatus;
/*
Update the hit node, performing an intersection from the camera's position
toward the given direction.
*/
void updateHitNode(const VROCamera &camera, VROVector3f origin, VROVector3f ray);
/*
VRODraggedObject encapsulates all the information that needs to be tracked
and processed for onDrag events for a given dragged node.
*/
struct VRODraggedObject{
std::shared_ptr<VRONode> _draggedNode;
VROVector3f _originalHitLocation;
VROVector3f _originalDraggedNodePosition;
VROVector3f _forwardOffset;
float _draggedDistanceFromController;
};
/*
Last hit result that we are performing a drag event on.
*/
std::shared_ptr<VRODraggedObject> _lastDraggedNode;
/*
This function is meant to be called to run the dragging logic after onMove
deals with other events, etc. This allows for the dragging logic to be overridden.
*/
virtual void processDragging(int source);
/*
Last result that was returned from the hit test.
*/
std::shared_ptr<VROHitTestResult> _hitResult;
/*
Last known posiiton of the controller.
*/
VROVector3f _lastKnownPosition;
/*
Last known position of the node that was dragged previously by this controller.
*/
VROVector3f _lastDraggedNodePosition;
/*
The pointer's normalized forward vector indicating where the controller
is pointing.
*/
VROVector3f _lastKnownForward;
/*
Last known pinch scale value.
*/
float _lastPinchScale;
/*
Last known rotation value in radians.
*/
float _lastRotation;
/*
The view and projection matrices, updated each render cycle.
*/
VROMatrix4f _view, _projection;
/*
Delegates registered within the manager to be notified of events
to an element that is outside the scene tree.
*/
std::set<std::shared_ptr<VROEventDelegate>> _delegates;
std::shared_ptr<VROScene> _scene;
/*
Returns the hit test result for the closest node that was hit.
*/
VROHitTestResult hitTest(const VROCamera &camera, VROVector3f origin, VROVector3f ray, bool boundsOnly);
virtual void processGazeEvent(int source);
private:
/*
UI presenter for this input controller.
*/
std::shared_ptr<VROInputPresenter> _controllerPresenter;
/*
Last known position that a TouchEvent occured on.
*/
VROVector3f _lastTouchedPosition;
/*
The controller's quaternion that represents the rotation from (0, 0, -1) required to
achieve the controller's current orientation.
*/
VROQuaternion _lastKnownRotation;
/*
Last node that we have clicked down on.
*/
std::shared_ptr<VRONode> _lastClickedNode;
/*
Last known that was successfully hovered upon.
*/
std::shared_ptr<VRONode> _lastHoveredNode;
/*
Returns the first node that is able to handle the event action by bubbling it up.
If nothing is able to handle the event, nullptr is returned.
*/
std::shared_ptr<VRONode> getNodeToHandleEvent(VROEventDelegate::EventAction action,
std::shared_ptr<VRONode> startingNode);
/*
Current node that we are fusing on.
*/
std::shared_ptr<VRONode> _currentFusedNode;
/*
Current node that we are pinching on.
*/
std::shared_ptr<VRONode> _currentPinchedNode;
/*
Current node that we are rotating on.
*/
std::shared_ptr<VRONode> _currentRotateNode;
/*
Time at which the onFuse event is triggered, in milliseconds.
*/
double _fuseTriggerAtMillis = -1;
/*
True if we have already notified delegates about the onFuse event.
*/
bool _haveNotifiedOnFuseTriggered;
void processOnFuseEvent(int source, std::shared_ptr<VRONode> node);
void notifyOnFuseEvent(int source, float timeToFuseRatio);
};
#endif

View File

@@ -0,0 +1,37 @@
//
// VROInputControllerCardboardiOS.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROInputControllerCardboardiOS_H
#define VROInputControllerCardboardiOS_H
#include <memory>
#include "VRORenderContext.h"
#include "VROInputControllerBase.h"
#include "VROInputPresenterCardboardiOS.h"
class VROInputControllerCardboardiOS : public VROInputControllerBase {
public:
VROInputControllerCardboardiOS(){}
virtual ~VROInputControllerCardboardiOS(){}
virtual VROVector3f getDragForwardOffset();
void onProcess(const VROCamera &camera);
void onScreenClicked();
std::string getHeadset();
std::string getController();
protected:
std::shared_ptr<VROInputPresenter> createPresenter() {
return std::make_shared<VROInputPresenterCardboardiOS>();
}
private:
void updateOrientation(const VROCamera &camera);
};
#endif

View File

@@ -0,0 +1,226 @@
//
// VROInputPresenter.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROInputPresenter_H
#define VROInputPresenter_H
#include <memory>
#include <atomic>
#include "VROEventDelegate.h"
#include "VRORenderContext.h"
#include "VROReticle.h"
#include "VRONode.h"
#include "VROMath.h"
#include "VROInputType.h"
#include "VROThreadRestricted.h"
static const float kReticleSizeMultiple = 3;
static const bool kDebugSceneBackgroundDistance = false;
/*
VROInputPresenter contains all UI view implementations to be displayed for a given
VROInputController.
*/
class VROInputPresenter : public VROEventDelegate, public VROThreadRestricted {
public:
VROInputPresenter() : VROThreadRestricted(VROThreadName::Renderer) {
_reticle = nullptr;
_rootNode = std::make_shared<VRONode>();
}
~VROInputPresenter() {}
std::shared_ptr<VRONode> getRootNode(){
return _rootNode;
}
void setEventDelegate(std::shared_ptr<VROEventDelegate> delegate){
_eventDelegateWeak = delegate;
}
virtual void onHover(int source, std::shared_ptr<VRONode> node, bool isHovering, std::vector<float> position) {
passert_thread();
std::shared_ptr<VROEventDelegate> delegate = getDelegate();
if (delegate != nullptr && delegate->isEventEnabled(VROEventDelegate::EventAction::OnHover)){
delegate->onHover(source, node, isHovering, position);
}
}
virtual void onClick(int source, std::shared_ptr<VRONode> node, ClickState clickState, std::vector<float> position) {
passert_thread();
std::shared_ptr<VROEventDelegate> delegate = getDelegate();
if (delegate != nullptr && delegate->isEventEnabled(VROEventDelegate::EventAction::OnClick)){
delegate->onClick(source, node, clickState, position);
}
}
virtual void onTouch(int source, std::shared_ptr<VRONode> node, TouchState state, float x, float y){
passert_thread();
std::shared_ptr<VROEventDelegate> delegate = getDelegate();
if (delegate != nullptr && delegate->isEventEnabled(VROEventDelegate::EventAction::OnTouch)){
delegate->onTouch(source, node, state, x, y);
}
}
virtual void onMove(int source, std::shared_ptr<VRONode> node,
VROVector3f rotation, VROVector3f position, VROVector3f forwardVec) {
passert_thread();
_lastKnownForward.store(forwardVec);
std::shared_ptr<VROEventDelegate> delegate = getDelegate();
if (delegate != nullptr && delegate->isEventEnabled(VROEventDelegate::EventAction::OnMove)){
delegate->onMove(source, node, rotation, position, forwardVec);
}
}
virtual void onControllerStatus(int source, ControllerStatus status) {
passert_thread();
std::shared_ptr<VROEventDelegate> delegate = getDelegate();
if (delegate != nullptr && delegate->isEventEnabled(VROEventDelegate::EventAction::OnControllerStatus)){
delegate->onControllerStatus(source, status);
}
}
virtual void onSwipe(int source, std::shared_ptr<VRONode> node, SwipeState swipeState) {
passert_thread();
std::shared_ptr<VROEventDelegate> delegate = getDelegate();
if (delegate != nullptr && delegate->isEventEnabled(VROEventDelegate::EventAction::OnSwipe)){
delegate->onSwipe(source, node, swipeState);
}
}
virtual void onScroll(int source, std::shared_ptr<VRONode> node, float x, float y) {
passert_thread();
std::shared_ptr<VROEventDelegate> delegate = getDelegate();
if (delegate != nullptr && delegate->isEventEnabled(VROEventDelegate::EventAction::OnScroll)){
delegate->onScroll(source, node, x, y);
}
}
virtual void onGazeHit(int source, std::shared_ptr<VRONode> node, const VROHitTestResult &hit) {
//No-op
}
virtual void onDrag(int source, std::shared_ptr<VRONode> node, VROVector3f newPosition) {
passert_thread();
std::shared_ptr<VROEventDelegate> delegate = getDelegate();
if (delegate != nullptr && delegate->isEventEnabled(VROEventDelegate::EventAction::OnDrag)){
delegate->onDrag(source, node, newPosition);
}
}
virtual void onFuse(int source, std::shared_ptr<VRONode> node, float timeToFuseRatio) {
passert_thread();
if (_reticle == nullptr) {
return;
}
std::shared_ptr<VROEventDelegate> delegate = getDelegate();
if (delegate != nullptr && delegate->isEventEnabled(VROEventDelegate::EventAction::OnFuse)) {
delegate->onFuse(source, node, timeToFuseRatio);
}
// TimeToFuseRatio is (time that has passed since fuse began) / (total time to fuse).
// When the timeToFuseRatio reaches 1, it is an indication that the node has been "onFused".
if (timeToFuseRatio == kOnFuseReset) {
_reticle->stopFuseAnimation();
} else {
_reticle->animateFuse(1 - timeToFuseRatio);
}
}
std::shared_ptr<VROReticle> getReticle() {
return _reticle;
}
void setReticle(std::shared_ptr<VROReticle> reticle){
_reticle = reticle;
_reticleInitialPositionSet = false;
}
VROVector3f getLastKnownForward(){
return _lastKnownForward.load();
}
void updateLastKnownForward(VROVector3f forward) {
_lastKnownForward.store(forward);
}
protected:
std::shared_ptr<VRONode> _rootNode;
void onReticleGazeHit(const VROHitTestResult &hit) {
passert_thread();
if (_reticle == nullptr) {
return;
}
float depth = -hit.getDistance();
if (!_reticle->isHeadlocked()) {
_reticle->setPosition(hit.getLocation());
float worldPerScreen = hit.getCamera().getWorldPerScreen(depth);
float radius = fabs(worldPerScreen) * kReticleSizeMultiple;
_reticle->setRadius(radius);
}
else {
// Lock the Reticle's position to the center of the screen
// for fixed pointer mode (usually Cardboard). The reticle is
// rendered as HUD object, with view matrix identity (e.g. it
// always follows the headset)
// Set the 'depth' of the reticle to the object it is hovering
// over, then set the radius to compensate for that distance so
// that the reticle stays the same size. The depth effectively
// determines the difference in reticle position between the two
// eyes.
// Only use the background depth if this is our first time
// positioning the reticle. Otherwise we maintain the current
// reticle depth, to avoid reticle 'popping' that occurs when
// the user moves from an actual focused object to the background.
// The background has no 'actual' depth so this is ok.
if (!_reticleInitialPositionSet || !hit.isBackgroundHit() || kDebugSceneBackgroundDistance) {
_reticle->setPosition(VROVector3f(0, 0, depth));
_reticleInitialPositionSet = true;
float worldPerScreen = hit.getCamera().getWorldPerScreen(depth);
float radius = fabs(worldPerScreen) * kReticleSizeMultiple;
_reticle->setRadius(radius);
}
}
}
private:
std::weak_ptr<VROEventDelegate> _eventDelegateWeak;
std::shared_ptr<VROReticle> _reticle;
bool _reticleInitialPositionSet;
std::atomic<VROVector3f> _lastKnownForward;
/*
Event delegate for triggering calls back to Controller_JNI.
*/
std::shared_ptr<VROEventDelegate> getDelegate(){
if (_eventDelegateWeak.expired()){
return nullptr;
}
return _eventDelegateWeak.lock();
}
};
#endif

View File

@@ -0,0 +1,40 @@
//
// VROControllerPresenterCardboard.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROControllerPresenterCardboardiOS_H
#define VROControllerPresenterCardboardiOS_H
#include <memory>
#include <string>
#include <vector>
#include "VRORenderContext.h"
#include "VROInputControllerBase.h"
#include "VROEventDelegate.h"
#include "VROHitTestResult.h"
class VROInputPresenterCardboardiOS : public VROInputPresenter {
public:
VROInputPresenterCardboardiOS() {
setReticle(std::make_shared<VROReticle>(nullptr));
getReticle()->setPointerFixed(true);
}
virtual ~VROInputPresenterCardboardiOS() {}
void onClick(int source, std::shared_ptr<VRONode> node, ClickState clickState, std::vector<float> clickedPosition) {
VROInputPresenter::onClick(source, node, clickState, clickedPosition);
if (clickState == ClickState::ClickUp){
getReticle()->trigger();
}
}
void onGazeHit(int source, std::shared_ptr<VRONode> node, const VROHitTestResult &hit) {
VROInputPresenter::onReticleGazeHit(hit);
}
};
#endif

View File

@@ -0,0 +1,47 @@
//
// VROControllerInputType.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROInputType_h
#define VROInputType_h
#include <stdio.h>
#include <vector>
#include <string>
#include <memory>
#include <set>
#include <float.h>
/**
* Header file containing sets of input sources that are grouped to
* a VR platform.
*/
namespace ViroDayDream{
enum InputSource{
Controller = 1,
TouchPad = 2,
AppButton = 3,
HomeButton = 4,
VolUpButton = 5,
VolDownButton = 6
};
}
namespace ViroCardBoard{
enum InputSource{
Controller=1,
ViewerButton = 2
};
}
namespace ViroOculus{
enum InputSource{
Controller = 1,
TouchPad = 2,
BackButton = 3
};
}
#endif

View File

@@ -0,0 +1,28 @@
//
// VROLazyMaterial.h
// ViroRenderer
//
// Created by Raj Advani on 2/14/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROLazyMaterial_h
#define VROLazyMaterial_h
#include <memory>
class VROMaterial;
/*
Interface for a lazy-loading material. Enables the animation system
to retrieve target materials lazily at the start of material animations.
*/
class VROLazyMaterial {
public:
virtual std::shared_ptr<VROMaterial> get() = 0;
};
#endif /* VROLazyMaterial_h */

View File

@@ -0,0 +1,372 @@
//
// VROLight.h
// ViroRenderer
//
// Created by Raj Advani on 12/7/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROLight_h
#define VROLight_h
#include <string>
#include <vector>
#include <atomic>
#include <memory>
#include <limits>
#include "VROVector3f.h"
#include "VROVector4f.h"
#include "VROMatrix4f.h"
#include "VROAnimatable.h"
static std::atomic_int sLightId;
class VROTexture;
class VROPencil;
class VROLightingUBO;
enum class VROLightType {
Ambient,
Directional,
Omni,
Spot
};
enum class VROShadowMode {
Forward,
Deferred,
Modulated
};
class VROLight : public VROAnimatable {
public:
static uint32_t hashLights(const std::vector<std::shared_ptr<VROLight>> &lights);
VROLight(VROLightType type);
~VROLight() {}
uint32_t getLightId() const {
return _lightId;
}
VROLightType getType() const {
return _type;
}
#pragma mark - Light Properties
void setColor(VROVector3f color);
VROVector3f getColor() const {
return _color;
}
void setIntensity(float intensity);
float getIntensity() const {
return _intensity;
}
void setTemperature(float temperature);
float getTemperature() const {
return _temperature;
}
VROVector3f getColorFromTemperature() const {
return _colorFromTemperature;
}
void setName(std::string name) {
this->_name = name;
}
std::string getName() const {
return _name;
}
void setPosition(VROVector3f position);
VROVector3f getPosition() const {
return _position;
}
void setDirection(VROVector3f direction);
VROVector3f getDirection() const {
return _direction;
}
void setAttenuationStartDistance(float attenuationStartDistance);
float getAttenuationStartDistance() const {
return _attenuationStartDistance;
}
void setAttenuationEndDistance(float attenuationEndDistance);
float getAttenuationEndDistance() const {
return _attenuationEndDistance;
}
void setAttenuationFalloffExponent(float attenuationFalloffExponent);
float getAttenuationFalloffExponent() const {
return _attenuationFalloffExponent;
}
void setSpotInnerAngle(float spotInnerAngle);
float getSpotInnerAngle() const {
return _spotInnerAngle;
}
void setSpotOuterAngle(float spotOuterAngle);
float getSpotOuterAngle() const {
return _spotOuterAngle;
}
void setInfluenceBitMask(int influenceBitMask) {
_influenceBitMask = influenceBitMask;
}
int getInfluenceBitMask() const {
return _influenceBitMask;
}
#pragma mark - Shadow Properties
void setCastsShadow(bool castsShadow);
bool getCastsShadow() const {
return _castsShadow;
}
void setShadowOpacity(float shadowOpacity);
float getShadowOpacity() const {
return _shadowOpacity;
}
void setShadowMapSize(int shadowMapSize) {
_shadowMapSize = shadowMapSize;
}
int getShadowMapSize() const {
return _shadowMapSize;
}
void setShadowBias(float shadowBias) {
_updatedFragmentData = true;
_shadowBias = shadowBias;
}
float getShadowBias() const {
return _shadowBias;
}
void setShadowOrthographicSize(float size) {
_shadowOrthographicSize = size;
}
float getShadowOrthographicSize() const {
return _shadowOrthographicSize;
}
void setShadowNearZ(float nearZ) {
_shadowNearZ = nearZ;
}
float getShadowNearZ() const {
return _shadowNearZ;
}
void setShadowFarZ(float farZ) {
_shadowFarZ = farZ;
}
float getShadowFarZ() const {
return _shadowFarZ;
}
#pragma mark - Light Implementation
/*
Lights hold onto their UBOs so that they can propagate their
updates to them. Each time a light is updated, it pushes the
update to all of its parent UBOs.
*/
void addUBO(std::shared_ptr<VROLightingUBO> ubo) {
_ubos.push_back(ubo);
}
void propagateFragmentUpdates();
void propagateVertexUpdates();
void setTransformedPosition(VROVector3f position);
VROVector3f getTransformedPosition() const {
return _transformedPosition;
}
#pragma mark - Shadow Implementation
int getShadowMapIndex() const {
return _shadowMapIndex;
}
void setShadowMapIndex(int shadowMapIndex) {
_updatedFragmentData = true;
_shadowMapIndex = shadowMapIndex;
}
VROMatrix4f getShadowViewMatrix() const {
return _shadowViewMatrix;
}
VROMatrix4f getShadowProjectionMatrix() const {
return _shadowProjectionMatrix;
}
void setShadowViewMatrix(VROMatrix4f shadowViewMatrix) {
_updatedVertexData = true;
_shadowViewMatrix = shadowViewMatrix;
}
void setShadowProjectionMatrix(VROMatrix4f shadowProjectionMatrix) {
_updatedVertexData = true;
_shadowProjectionMatrix = shadowProjectionMatrix;
}
#pragma mark - Debugging
void drawLightFrustum(std::shared_ptr<VROPencil> pencil);
private:
uint32_t _lightId;
VROLightType _type;
/*
RGB color of the light.
*/
VROVector3f _color;
/*
Luminous flux of the light, ranging from 0 to 1000. Modulates the color of the
light.
*/
float _intensity;
/*
The temperature of the light, in Kelvin. Viro will derive a hue from this temperature
and multiply it by _color. To model a physical light, you can leave _color set to
(1.0, 1.0, 1.0) and set the temperature only. The default value is 6500K, which
represents pure white light.
*/
float _temperature;
/*
The color as derived from _temperature.
*/
VROVector3f _colorFromTemperature;
std::string _name;
bool _updatedFragmentData;
bool _updatedVertexData;
/*
The position of the light. For omnidirectional and spotlights, this represents
the position from which the light emanates. For directional lights there is no
position, but we still use this field to indicate where the directional light's
shadow map should be centered.
*/
VROVector3f _position;
/*
Attenuation parameters for omni and spot lights.
*/
float _attenuationStartDistance;
float _attenuationEndDistance;
float _attenuationFalloffExponent;
/*
Diffuse parameters.
*/
VROVector3f _direction;
/*
Spot parameters. The inner angle is the angle from edge to edge of
the 'full strength' light cone. The lighting is at maximum intensity
within this cone, and begins to attenuate outside of it.
The outer angle is the angle from edge to edge of the "attenuated"
light cone. The lighting declines in strength betewen the inner angle
and outer angle. Outside of the outer angle the light attenuates to
zero, resulting in no light.
Both of these are specified in degrees.
*/
float _spotInnerAngle;
float _spotOuterAngle;
/*
Internal. The position of the light after all its supernode
transforms have been applied.
*/
VROVector3f _transformedPosition;
/*
Weak refs to all UBOs that use this light. Needed so that when this
light is updated, we can flag the UBO as a whole as requiring an
update.
*/
std::vector<std::weak_ptr<VROLightingUBO>> _ubos;
/*
True if this light casts shadows.
*/
bool _castsShadow;
/*
The opacity of the shadow. 1.0 implies a pitch black shadow.
*/
float _shadowOpacity;
/*
The size of the depth map to use to render shadows. Larger sizes produce
more detailed shadows at higher cost to rendering performance. Lower sizes
are faster but result in pixelation at the edges.
*/
int _shadowMapSize;
/*
The amount of bias to apply to the Z coordinate when performing the shadow
depth comparison. This reduces shadow acne, but large biases can increase
"peter panning".
*/
float _shadowBias;
/*
This property only applies to directional lights, where an orthographic
projection is used to render the shadow map. The orthographic size determines
the width and height of the area, centered at _position, that should be rendered
to the shadow map.
A larger value means more of the scene will be shadowed, but
at lower resolution.
*/
float _shadowOrthographicSize;
/*
The near and far clipping planes to use when rendering shadows. Shadows are
only cast by surfaces within these planes.
*/
float _shadowNearZ, _shadowFarZ;
/*
The index into the shadow render target's texture array where we can find this
light's shadow map.
*/
int _shadowMapIndex;
/*
Bit mask that is ANDed with each node's lightReceivingBitMask and shadowCastingBitMask
to determine what objects are illuminated by, and cast shadows from, this light.
Default is 1.
*/
int _influenceBitMask;
/*
The view and projection matrices used to transform any point in world
space into its corresponding texcoord in the light's shadow depth map.
*/
VROMatrix4f _shadowViewMatrix;
VROMatrix4f _shadowProjectionMatrix;
/*
Derive the RGB color (hue) from the given temperature in Kelvin.
*/
VROVector3f deriveRGBFromTemperature(float temperature);
};
#endif /* VROLight_h */

View File

@@ -0,0 +1,231 @@
//
// VROTriangle.h
// ViroRenderer
//
// Created by Raj Advani on 10/12/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROLINESEGMENT_H_
#define VROLINESEGMENT_H_
#include "VROVector3f.h"
enum class VROOrientation {
Colinear = 0,
Left = 1,
Right = -1
};
class VROLineSegment {
public:
/*
Construct a new {@link LineSegment}.
@param A
First point.
@param B
Second point.
*/
VROLineSegment(VROVector3f A, VROVector3f B);
/*
Get the start and end of this segment.
*/
VROVector3f getA() const;
VROVector3f getB() const;
/*
Get a ray representation of the segment, the midpoint or the length.
*/
VROVector3f ray() const;
VROVector3f midpoint() const;
float length() const;
float lengthApprox() const;
/*
Flip the orientation of this segment (set A to B and vice-versa).
*/
VROLineSegment flip() const;
/*
Returns the orientation (as a VROOrientation) of the direction of the point p relative
to this segment.
*/
VROOrientation orientationOfPoint(VROVector3f q) const;
/*
Test if this segment intersects the given 2D segment or 2D box.
*/
bool intersectsSegment2D(VROLineSegment other) const;
bool intersectsSegment2D(VROLineSegment other, VROVector3f *result) const;
bool intersectsBox2D(float left, float right, float bottom, float top) const;
/*
Test if the line represented by this segment intersects the line represented by the
given segment. This function treats both segments as infinitely extending lines.
*/
bool intersectsLine(VROLineSegment other, VROVector3f *result) const;
/*
Test if this line segment intersects plane defined by the given point and normal.
Return true if so, storing the intersection point in the given out vector.
*/
bool intersectsPlane(VROVector3f point, VROVector3f normal, VROVector3f *outIntersectionPoint) const;
/*
Get the angle this segment makes with the given other line-segment,
normalized to the range [0, PI/2]. Note that this method ignores the
<i>direction</i> of the line-segment (we do not treat line-segments like
rays).
*/
float angleWithSegment(VROLineSegment other) const;
float angle2DWithSegment(VROLineSegment other) const;
/*
Get the angle this segment makes with the given other line-segment,
normalized to the range [-PI, PI]. Note that this method takes into
account the <i>direction</i> of the line-segment. A positive angle is
taken to mean the other segment is that many radians
<i>counter-clockwise</i> from this segment. Likewise, a negative angle
implies <i>clockwise</i> rotation.
For example, the angle between the segment [(0, -1) -> (0, 0)] and [(0,
0) -> (1,1)] is -45 degrees, as the latter is 45 degrees clockwise from
the former.
*/
float directedAngleWithSegment(VROLineSegment other) const;
/*
Compute the angle, in the same manner as directedAngleWithSegment, that this
segment makes with the given ray.
*/
float directedAngleWithRay(VROVector3f ray) const;
/*
Translate the segment by the given amount.
*/
VROLineSegment translate(VROVector3f translation) const;
/*
Rotate this line segment counter-clockwise about its center by the given
amount and return the result. Does not mutate this segment.
*/
VROLineSegment rotate(float radians) const;
/*
Rotate this line segment counter-clockwise about its start point, by the
given number of radians, and store the result. Does not mutate this
segment.
*/
VROLineSegment pivot(float radians) const;
/*
Scale this segment out by the given factor. This will essentially just
grow the segment, keeping its angle and midpoint the same.
*/
VROLineSegment scale(float scale) const;
/*
Get the normal unit vector in the positive or negative
direction for this line segment. This is a 2D calculation,
so the z-values in the line segment are ignored and the
z-value in the returned vector will be zero.
The returned vector will be <0, 0, 0> if this line
segment has an 2D-length of 0.
*/
VROVector3f normal2DUnitVector(bool positive) const;
/*
Extend this segment out by the given amount. This
essentially just pushes out the B endpoint in the direction of the segment.
The second function will push out the A endpoint in the reverse direction
of the segment, and the third does both.
*/
VROLineSegment extend(float amount) const;
VROLineSegment extendBackwards(float amount) const;
VROLineSegment extendForwardAndBackward(float amount) const;
/*
Shift the line segment by the given amount. This pushes out the A
and B endpoints in the direction of the segment.
*/
VROLineSegment shift(float amount) const;
/*
Traverse the line-segment by the given distance from the start-point and
return the result. If we overshoot either endpoint of the segment, just
interpolate away. The distance may be negative to go backward (from B to A
instead of A to B).
*/
VROVector3f traverseFromStart(float distance) const;
VROVector3f traverseFromEnd(float distance) const;
/*
Returns the 't' that gives the closest point on this line to
the given point 'p' for the vector operation 'AB * t + A', note
that this may be off of the actual line segment if t is not in
[0, 1]
see: * http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html
*/
float parameterOfClosestPoint(VROVector3f p) const;
/*
Find the point on the line segment defined that is closest to
the given point. Call the closest point on the line P. Observe
that the vector formed by P and the given point is orthogonal
to the line defined by p1 and p2. Thus the dot product of these
two vectors is zero. From there we can calculate the x, y, and
z of the point P (after a lot of hairy algebra).
*/
VROVector3f pointOnLineSegmentClosestTo(VROVector3f p) const;
float distanceToPoint(VROVector3f v) const;
float distanceToPointSigned(VROVector3f v) const;
/*
Find the point on the infinite line given by this line segment
that is closest to the given point 'p'.
*/
VROVector3f pointOnLineClosestTo(VROVector3f p) const;
/*
Offset this line-segment by the given amount, and store the result in the
given segment. Positive distance offsets to the left, negative to the right.
*/
void offsetByDistance(double distance, VROLineSegment *result) const;
/*
Return a string representation of this segment.
*/
std::string toString() const;
inline bool operator==(const VROLineSegment &other) const {
return other.__A == __A && other.__B == __B;
}
private:
// Note: we use double underscores here (__A, __B, etc.) because _B is a
// reserved macro on some platforms (Android NDK)
/*
The two points joined by this segment.
*/
VROVector3f __A, __B;
/*
Useful values for intermediate calculations.
*/
float __ABx, __ABy, __ABz;
/*
Square of the length.
*/
float _lengthSq;
};
#endif /* VROLINESEGMENT_H_ */

View File

@@ -0,0 +1,741 @@
//
// VROLog.h
// ViroRenderer
//
// Created by Raj Advani on 10/21/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#include "VRODefines.h"
#pragma once
//// Test debug defines
//#ifdef NDEBUG
//#pragma message "NDEBUG is #defined."
//#else
//#pragma message "NDEBUG is not #defined."
//#endif
#undef PASSERT_INNERLOOPS_ENABLED // Do not define, unless you want passert_innerloop() asserts
// to run, which are passert_msg() calls that are made inside inner loops, which would slow down
// the app massively if on. Used for debugging those particular loops only, and left off to not slow
// the app down for other developers.
/////////////////////////////////////////////////////////////////////////////////
//
// Android: Logging
//
/////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Android Logging
#if VRO_PLATFORM_ANDROID
#include <android/log.h>
#include <jni.h>
#include <sys/system_properties.h>
// --------------------------------
// Escape sequences for logging color:
// 16-color = 4-bits = [highlight][blue][green][red]
// These are #defines instead of const char [] so they can be used more easily in perr() and pfatal().
// http://en.wikipedia.org/wiki/ANSI_escape_code
// --------
// special
#define ANSINoColor "\e[0m" // reset / normal
#define ANSIBold "\e[1m" // bold
// NOTE: the following uses 0 (reset) and 1 (bold) for intensities,
// which is used by BOTH foreground and background,
// and 0 will reset BOTH the foreground and background,
// thus this doesn't work: ANSIBackBlue ANSICyan
// since the "0" in Cyan is a reset, which resets the background.
// --------
// foreground
// light colors
#define ANSIBlack "\e[0;30m"
#define ANSIRed "\e[0;31m"
#define ANSIGreen "\e[0;32m"
#define ANSIBrown "\e[0;33m"
#define ANSIDarkYellow "\e[0;33m"
#define ANSIBlue "\e[0;34m"
#define ANSIMagenta "\e[0;35m"
#define ANSICyan "\e[0;36m"
#define ANSILightGray "\e[0;37m"
// bright colors
#define ANSIDarkGray "\e[1;30m"
#define ANSILightRed "\e[1;31m"
#define ANSILightGreen "\e[1;32m"
#define ANSIYellow "\e[1;33m"
#define ANSILightBlue "\e[1;34m"
#define ANSILightMagenta "\e[1;35m"
#define ANSILightCyan "\e[1;36m"
#define ANSIWhite "\e[1;37m"
// default text color
#define ANSIDefault "\e[1;39m"
// --------
// background
// light colors
#define ANSIBackBlack "\e[0;40m"
#define ANSIBackRed "\e[0;41m"
#define ANSIBackGreen "\e[0;42m"
#define ANSIBackBrown "\e[0;43m"
#define ANSIBackBlue "\e[0;44m"
#define ANSIBackMagenta "\e[0;45m"
#define ANSIBackCyan "\e[0;46m"
#define ANSIBackLightGray "\e[0;47m"
// bright colors
#define ANSIBackDarkGray "\e[1;40m"
#define ANSIBackLightRed "\e[1;41m"
#define ANSIBackLightGreen "\e[1;42m"
#define ANSIBackYellow "\e[1;43m"
#define ANSIBackLightBlue "\e[1;44m"
#define ANSIBackLightMagenta "\e[1;45m"
#define ANSIBackLightCyan "\e[1;46m"
#define ANSIBackWhite "\e[1;47m"
// default background color
#define ANSIBackDefault "\e[1;49m"
#elif VRO_PLATFORM_IOS
#include "VROOpenGL.h" // For pglpush and pglpop implementations
/*
ANSI colors don't resolve on the iOS debug console, so we
deactivate them.
*/
#define ANSINoColor ""
#define ANSIBold ""
#define ANSIBlack ""
#define ANSIRed ""
#define ANSIGreen ""
#define ANSIBrown ""
#define ANSIDarkYellow ""
#define ANSIBlue ""
#define ANSIMagenta ""
#define ANSICyan ""
#define ANSILightGray ""
#define ANSIDarkGray ""
#define ANSILightRed ""
#define ANSILightGreen ""
#define ANSIYellow ""
#define ANSILightBlue ""
#define ANSILightMagenta ""
#define ANSILightCyan ""
#define ANSIWhite ""
#define ANSIDefault ""
#define ANSIBackBlack ""
#define ANSIBackRed ""
#define ANSIBackGreen ""
#define ANSIBackBrown ""
#define ANSIBackBlue ""
#define ANSIBackMagenta ""
#define ANSIBackCyan ""
#define ANSIBackLightGray ""
#define ANSIBackDarkGray ""
#define ANSIBackLightRed ""
#define ANSIBackLightGreen ""
#define ANSIBackYellow ""
#define ANSIBackLightBlue ""
#define ANSIBackLightMagenta ""
#define ANSIBackLightCyan ""
#define ANSIBackWhite ""
#define ANSIBackDefault ""
#endif
/////////////////////////////////////////////////////////////////////////////////
//
// Android: Logging
//
/////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Android Logging
// define LOG_TAG, if not already defined
#ifndef LOG_TAG
#define LOG_TAG "Viro"
#endif
#if VRO_PLATFORM_ANDROID
// Why do-while(0)?
// --------------------
// It allows this:
// 1. protects against multiple statements when the #define, when it is called like a single-statement.
// 2. the while loop doesn't have a ; at the end, so that it doesn't end an if-statement with the #define called inside.
// 3. it also allows local variables to not interfere with ones on the outside.
// https://www.securecoding.cert.org/confluence/display/seccode/PRE10-C.+Wrap+multistatement+macros+in+a+do-while+loop
#if NDEBUG
// Release build
#define pverbose(...) ((void)0)
#define cpverbose(tag, ...) ((void)0)
#define pdebug(...) ((void)0)
#define cpdebug(tag, ...) ((void)0)
#else
// Debug build
// verbose:
#define pverbose(...) \
do { \
__android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__); \
} while (0)
#define cpverbose(tag, ...) \
do { \
__android_log_print(ANDROID_LOG_VERBOSE, tag, __VA_ARGS__); \
} while (0)
// debug:
#define pdebug(...) \
do { \
__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__); \
} while (0)
#define cpdebug(tag, ...) \
do { \
__android_log_print(ANDROID_LOG_DEBUG, tag, __VA_ARGS__); \
} while (0)
#endif
// info:
#define pinfo(...) \
do { \
__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__); \
} while (0)
#define cpinfo(tag, ...) \
do { \
__android_log_print(ANDROID_LOG_INFO, tag, __VA_ARGS__); \
} while (0)
// warn:
#define pwarn(...) \
do { \
__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__); \
} while (0)
#define cpwarn(tag, ...) \
do { \
__android_log_print(ANDROID_LOG_WARN, tag, __VA_ARGS__); \
} while (0)
// error:
#define perr(message, ...) \
do { \
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, \
ANSILightRed "ERROR: [%s: %s(), line %d]%s\n%sERROR: %s%s" message ANSINoColor, \
__FILE__, __FUNCTION__, __LINE__, ANSINoColor, ANSILightRed, ANSINoColor, ANSIYellow, \
##__VA_ARGS__); \
} while (0)
#define cperr(tag, message, ...) \
do { \
__android_log_print(ANDROID_LOG_ERROR, tag, \
ANSILightRed "ERROR: [%s: %s(), line %d]%s\n%sERROR: %s%s" message ANSINoColor, \
__FILE__, __FUNCTION__, __LINE__, ANSINoColor, ANSILightRed, ANSINoColor, ANSIYellow, \
##__VA_ARGS__); \
} while (0)
// fatal:
#define pfatal(message, ...) \
do { \
__android_log_print(ANDROID_LOG_FATAL, LOG_TAG, \
ANSILightRed "FATAL ERROR: [%s:%d]%s\n%sFATAL ERROR: %s%s" message ANSINoColor, \
__FILE__, __LINE__, ANSINoColor, ANSILightRed, ANSINoColor, ANSIYellow, \
##__VA_ARGS__); \
abort(); \
} while (0)
#define cpfatal(tag, message, ...) \
do { \
__android_log_print(ANDROID_LOG_FATAL, tag, \
ANSILightRed "FATAL ERROR: [%s:%d]%s\n%sFATAL ERROR: %s%s" message ANSINoColor, \
__FILE__, __LINE__, ANSINoColor, ANSILightRed, ANSINoColor, ANSIYellow, \
##__VA_ARGS__); \
abort(); \
} while (0)
#define pgllabel(message,...) ((void)0)
#define pglpush(message,...) ((void)0)
#define pglpop() ((void)0)
// __android_log_assert():
// Log an assertion failure and SIGTRAP the process to have a chance
// to inspect it. This uses the FATAL priority.
#define passert(condition) \
do \
{ \
if (!(condition)) { \
_pabort(__FILE__, __LINE__, __func__, \
"ASSERTION FAILED\n" \
" Expression: %s", \
#condition); \
} \
} while (0)
#if VRO_THREADPOOL_LOG
#define pthreadpool(message,...) \
do { \
__android_log_print(ANDROID_LOG_VERBOSE, threadPoolName.c_str(), "%s%s(): "#message" %s", ANSILightMagenta, __FUNCTION__, ##__VA_ARGS__, ANSINoColor); \
} while (0)
#define pthreadtask(message,...) \
do { \
__android_log_print(ANDROID_LOG_VERBOSE, threadIdentifier.c_str(), " %s%s(): "#message" %s", ANSILightCyan, __FUNCTION__, ##__VA_ARGS__, ANSINoColor); \
} while (0)
#define pthreadtaskexe(message,...) \
do { \
__android_log_print(ANDROID_LOG_VERBOSE, threadIdentifier.c_str(), " %s%s(): "#message" %s", ANSILightBlue, __FUNCTION__, ##__VA_ARGS__, ANSINoColor); \
} while(0)
#define pthreadtaskerror(message,...) \
do { \
__android_log_print(ANDROID_LOG_VERBOSE, threadIdentifier.c_str(), " %s%s(): "#message" %s", ANSIRed, __FUNCTION__, ##__VA_ARGS__, ANSINoColor); \
} while(0)
#else
#define pthreadpool(message,...) ((void)0)
#define pthreadtask(message,...) ((void)0)
#define pthreadtaskexe(message,...) ((void)0)
#define pthreadtaskerror(message,...) ((void)0)
#endif
#define VERBOSE_LOGGING 0 // turn this on during development as needed
#if NDEBUG
// Release build
#define DEBUG_LOGGING 0
#else
// Debug build
#define DEBUG_LOGGING 1
#endif
static inline int
toLevel(const char* value) {
switch (value[0]) {
case 'V': return ANDROID_LOG_VERBOSE;
case 'D': return ANDROID_LOG_DEBUG;
case 'I': return ANDROID_LOG_INFO;
case 'W': return ANDROID_LOG_WARN;
case 'E': return ANDROID_LOG_ERROR;
case 'A': return ANDROID_LOG_FATAL;
case 'S': return ANDROID_LOG_SILENT;
}
return ANDROID_LOG_INFO;
}
#define isLoggable(tag, level) \
({ \
char value[PROP_VALUE_MAX]; \
__system_property_get("log.tag." tag, value); \
int logLevel = toLevel(value); \
logLevel != ANDROID_LOG_SILENT && level >= logLevel; \
})
#elif VRO_PLATFORM_IOS
/////////////////////////////////////////////////////////////////////////////////
//
// iOS: Logging
//
/////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark iOS Logging
#include <assert.h>
#include <Foundation/Foundation.h>
#define passert(condition) (assert(condition))
#define cpverbose(tag, ...) ((void)0)
#define cpdebug(tag, ...) ((void)0)
#define pverbose(message,...) ((void)0)
#define pdebug(message,...) \
do { \
\
} while (0)
#define pinfo(message,...) \
do { \
NSLog(@#message, ##__VA_ARGS__); \
} while (0)
#define pwarn(message,...) \
do { \
NSLog(@#message, ##__VA_ARGS__); \
} while (0)
#define perr(message,...) \
do { \
NSLog(@"Error: "#message, ##__VA_ARGS__); \
} while (0)
#define pfatal(message,...) \
do { \
NSLog(@"Fatal Error: "#message, ##__VA_ARGS__); \
} while (0)
#if VRO_THREADPOOL_LOG
#define pthreadpool(message,...) \
do { \
NSLog(@"[%s]%s(): "#message, threadPoolName.c_str(), __FUNCTION__, ##__VA_ARGS__); \
} while (0)
#define pthreadtask(message,...) \
do { \
NSLog(@"[%s]%s(): "#message, threadIdentifier.c_str(), __FUNCTION__, ##__VA_ARGS__); \
} while (0)
#define pthreadtaskexe(message,...) \
do { \
NSLog(@"[%s]%s(): "#message, threadIdentifier.c_str(), __FUNCTION__, ##__VA_ARGS__); \
} while (0)
#define pthreadtaskerror(message,...) \
do { \
NSLog(@"[%s]%s(): "#message, threadIdentifier.c_str(), __FUNCTION__, ##__VA_ARGS__); \
} while (0)
#else
#define pthreadpool(message,...) ((void)0)
#define pthreadtask(message,...) ((void)0)
#define pthreadtaskexe(message,...) ((void)0)
#define pthreadtaskerror(message,...) ((void)0)
#endif
#define pgllabel(message,...) \
do { \
char str[1024]; \
sprintf(str, #message, ##__VA_ARGS__); \
glInsertEventMarkerEXT(0, str); \
} while (0)
#define pglpush(message,...) \
do { \
char str[1024]; \
sprintf(str, #message, ##__VA_ARGS__); \
glPushGroupMarkerEXT(0, str); \
} while (0)
#define pglpop() \
do { \
glPopGroupMarkerEXT(); \
} while (0)
#define cpinfo(tag, ...) \
do { \
\
} while (0)
#endif
/////////////////////////////////////////////////////////////////////////////////
//
// Common: Logging
//
/////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Common (Android & iOS) Logging
// --------------------------------
// variables:
#define pStringifyBool(boolExpression) ((boolExpression) ? "true" : "false")
#define pStringifyNull(stringExpression) ((stringExpression) ? stringExpression : "null")
#define pbool(b) pinfo("%s%s()%s: "#b" = %s%s%s.", ANSILightMagenta, __FUNCTION__, ANSINoColor, ANSILightBlue, pStringifyBool(b), ANSINoColor);
#define pboolean(b) pbool(b);
#define pbyte(b) pinfo("%s%s()%s: "#b" = %s%d = 0x%02X = %d%d%d%d%d%d%d%d%s.", \
ANSILightMagenta, __FUNCTION__, ANSINoColor, ANSILightBlue, b, b, \
static_cast<int>((b&(1<<7))!=0), \
static_cast<int>((b&(1<<6))!=0), \
static_cast<int>((b&(1<<5))!=0), \
static_cast<int>((b&(1<<4))!=0), \
static_cast<int>((b&(1<<3))!=0), \
static_cast<int>((b&(1<<2))!=0), \
static_cast<int>((b&(1<<1))!=0), \
static_cast<int>((b&(1<<0))!=0), ANSINoColor)
#define pint(i) pinfo("%s%s()%s: "#i" = %s%d%s.", ANSILightMagenta, __FUNCTION__, ANSINoColor, ANSILightBlue, i, ANSINoColor)
#define puint(i) pinfo("%s%s()%s: "#i" = %s%u%s.", ANSILightMagenta, __FUNCTION__, ANSINoColor, ANSILightBlue, i, ANSINoColor)
#define pbits(bitfield) pinfo("%s%s()%s: "#bitfield \
" = %s%d = 0x%08X = %d%d%d%d%d%d%d%d-%d%d%d%d%d%d%d%d-%d%d%d%d%d%d%d%d-%d%d%d%d%d%d%d%d%s.", \
ANSILightMagenta, __FUNCTION__, ANSINoColor, ANSILightBlue, bitfield, bitfield, \
static_cast<int>((bitfield&(1<<31))!=0), \
static_cast<int>((bitfield&(1<<30))!=0), \
static_cast<int>((bitfield&(1<<29))!=0), \
static_cast<int>((bitfield&(1<<28))!=0), \
static_cast<int>((bitfield&(1<<27))!=0), \
static_cast<int>((bitfield&(1<<26))!=0), \
static_cast<int>((bitfield&(1<<25))!=0), \
static_cast<int>((bitfield&(1<<24))!=0), \
static_cast<int>((bitfield&(1<<23))!=0), \
static_cast<int>((bitfield&(1<<22))!=0), \
static_cast<int>((bitfield&(1<<21))!=0), \
static_cast<int>((bitfield&(1<<20))!=0), \
static_cast<int>((bitfield&(1<<19))!=0), \
static_cast<int>((bitfield&(1<<18))!=0), \
static_cast<int>((bitfield&(1<<17))!=0), \
static_cast<int>((bitfield&(1<<16))!=0), \
static_cast<int>((bitfield&(1<<15))!=0), \
static_cast<int>((bitfield&(1<<14))!=0), \
static_cast<int>((bitfield&(1<<13))!=0), \
static_cast<int>((bitfield&(1<<12))!=0), \
static_cast<int>((bitfield&(1<<11))!=0), \
static_cast<int>((bitfield&(1<<10))!=0), \
static_cast<int>((bitfield&(1<<9))!=0), \
static_cast<int>((bitfield&(1<<8))!=0), \
static_cast<int>((bitfield&(1<<7))!=0), \
static_cast<int>((bitfield&(1<<6))!=0), \
static_cast<int>((bitfield&(1<<5))!=0), \
static_cast<int>((bitfield&(1<<4))!=0), \
static_cast<int>((bitfield&(1<<3))!=0), \
static_cast<int>((bitfield&(1<<2))!=0), \
static_cast<int>((bitfield&(1<<1))!=0), \
static_cast<int>((bitfield&(1<<0))!=0), ANSINoColor)
#define pfloat(f) pinfo("%s%s()%s: "#f" = %s%f%s.", ANSILightMagenta, __FUNCTION__, ANSINoColor, ANSILightBlue, f, ANSINoColor)
#define pdouble(d) pinfo("%s%s()%s: "#d" = %s%f%s.", ANSILightMagenta, __FUNCTION__, ANSINoColor, ANSILightBlue, d, ANSINoColor)
#define ppointer(p) pinfo("%s%s()%s: "#p" = %s%p%s", ANSILightMagenta, __FUNCTION__, ANSINoColor, ANSILightBlue, (void*)p, ANSINoColor)
// Note: cannot use pptr(), as it is used in boost.
// --------------------------------
// complex types or combos:
#define pxy(x,y) pinfo("%s%s()%s: ("#x", "#y") = (%s%f, %f%s).", ANSILightMagenta, __FUNCTION__, ANSINoColor, ANSILightBlue, x, y, ANSINoColor)
#define pintxy(x,y) pinfo("%s%s()%s: ("#x", "#y") = (%s%d, %d%s).", ANSILightMagenta, __FUNCTION__, ANSINoColor, ANSILightBlue, x, y, ANSINoColor)
/*
Logs an init array.
13 characters per float = 11 for "+1000111222", 2 for ", ".
Note the length of the arary is +1, so that snprintf() has
room to write the NULL terminater, though we adjust it
for the last index anyway.
*/
#define pintarray(pIntArray, size) \
do \
{ \
int const numCharsPerInt = 13; \
char str[size * numCharsPerInt + 1]; \
for (int i=0; i<size; i++) snprintf(&str[i * numCharsPerInt], numCharsPerInt + 1, "%11d, ", pIntArray[i]); \
str[size * numCharsPerInt - 2] = '\0'; \
pinfo("%s%s()%s: "#pIntArray"[%d] = %s{%s}%s", \
ANSILightMagenta, __FUNCTION__, ANSINoColor, size, \
ANSILightBlue, str, ANSINoColor); \
} while (0)
/*
Logs a float array.
8 characters per float = 6 for "+9.999", 2 for ", ".
Note the length of the arary is +1, so that snprintf() has
room to write the NULL terminater, though we adjust it
for the last index anyway.
*/
#define pfloatarray(pFloatArray, size) \
do \
{ \
int const numCharsPerFloat = 8; \
char str[size * numCharsPerFloat + 1]; \
for (int i=0; i<size; i++) snprintf(&str[i * numCharsPerFloat], numCharsPerFloat + 1, "%6.3f, ", pFloatArray[i]); \
str[size * numCharsPerFloat - 2] = '\0'; \
pinfo("%s%s()%s: "#pFloatArray"[%d] = %s{%s}%s", \
ANSILightMagenta, __FUNCTION__, ANSINoColor, size, \
ANSILightBlue, str, ANSINoColor); \
} while (0)
/*
Logs a VROVector3f.
*/
#define pvec3(vec) \
do \
{ \
pinfo("%s%s()%s: "#vec" = %s%s%s", \
ANSILightMagenta, __FUNCTION__, ANSINoColor, \
ANSILightBlue, (vec).toString().c_str(), ANSINoColor); \
} while (0)
/*
Logs a pointer to VROVector3f.
*/
#define ppvec3(pVec) \
do \
{ \
pinfo("%s%s()%s: *"#pVec" = %s%s%s", \
ANSILightMagenta, __FUNCTION__, ANSINoColor, \
ANSILightBlue, pVec->toString().c_str(), ANSINoColor); \
} while (0)
/*
Logs a 4X4 matrix.
*/
#define pmatrix(m) \
do \
{ \
pinfo("%s%s()%s: "#m"[] =", ANSILightMagenta, __FUNCTION__, ANSINoColor); \
pinfo("%s[%6.3f, %6.3f, %6.3f, %6.3f,%s", ANSILightBlue, m[0], m[4], m[8], m[12], ANSINoColor); \
pinfo("%s %6.3f, %6.3f, %6.3f, %6.3f,%s", ANSILightBlue, m[1], m[5], m[9], m[13], ANSINoColor); \
pinfo("%s %6.3f, %6.3f, %6.3f, %6.3f,%s", ANSILightBlue, m[2], m[6], m[10], m[14], ANSINoColor); \
pinfo("%s %6.3f, %6.3f, %6.3f, %6.3f]%s", ANSILightBlue, m[3], m[7], m[11], m[15], ANSINoColor); \
} while (0)
/*
Logs a VROBoundingBox.
*/
#define pbb(bb) \
do \
{ \
pinfo("%s%s()%s: "#bb" = %s%s%s", \
ANSILightMagenta, __FUNCTION__, ANSINoColor, \
ANSILightBlue, (bb).toString().c_str(), ANSINoColor); \
} while (0)
// --------------------------------
// markers
#define plocation() pinfo("[%s%s:%s %s%s()%s, %sline %d%s]", \
ANSILightCyan, __FILE__, ANSINoColor, \
ANSILightMagenta, __FUNCTION__, ANSINoColor, \
ANSILightBlue, __LINE__, ANSINoColor)
#define pcr() pinfo(" ")
#define pline() pline1()
#define cpline(tag) cpinfo(tag, "----------------------------------------------------------------")
#define pline1() pinfo("----------------------------------------------------------------")
#define pline2() pinfo("================================================================")
#define predline() pinfo("%s################################################################%s", ANSILightRed, ANSINoColor);
#define pyellowline() pinfo("%s################################################################%s", ANSIYellow, ANSINoColor);
#define phighlight(color) pinfo("%s****************************************************************%s", color, ANSINoColor)
#define pfunc() \
do \
{ \
pinfo("%s%s()----------------------------------------------------------------%s", ANSILightMagenta, __FUNCTION__, ANSINoColor); \
} while (0)
#define pfuncfull() \
do \
{ \
pinfo("%s%s ----------------------------------------------------------------%s", ANSILightMagenta, __func__, ANSINoColor); \
} while (0)
#define pfunction() \
do \
{ \
pinfo("%s%s:%s():%s%d%s", ANSILightMagenta, __FILE__, __FUNCTION__, ANSIMagenta, __LINE__, ANSINoColor); \
} while (0)
#define pfuncstart() \
do \
{ \
pinfo("%s%s() starting...%s", ANSILightMagenta, __FUNCTION__, ANSILightGreen, ANSINoColor); \
} while (0)
#define pfuncend() \
do \
{ \
pinfo("%s%s() %sending.%s", ANSILightMagenta, __FUNCTION__, ANSILightGreen, ANSINoColor); \
} while (0)
#define pmarker() \
do \
{ \
pinfo("%s%s(): %sLine %d.%s", ANSILightMagenta, __FUNCTION__, ANSILightGreen, __LINE__, ANSINoColor); \
} while (0)
#if VRO_SECURITY_LOG
#define psecurityinfo(message,...) pinfo("Viro-Security:: "#message, ##__VA_ARGS__)
#define psecurityerr(message,...) perr("Viro-Security:: "#message, ##__VA_ARGS__)
#else
#define psecurityinfo(message,...) ((void)0)
#define psecurityerr(message,...) ((void)0)
#endif
/////////////////////////////////////////////////////////////////////////////////
//
// Common: Stack Trace
//
/////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark (Common) Stack Trace
/*
Print out a message and a stacktrace, including the current stackframe
*/
void pstack(const char *fmt, ...)
__attribute__ ((format(printf, 1, 2)));
/*
Print out a stacktrace, including the current stackframe
*/
void pstack();
/////////////////////////////////////////////////////////////////////////////////
//
// Common: Abort
//
/////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Common: Abort
/*
Abort the program.
Print out a stacktrace; then cause a SEG fault to halt execution.
SEG fault will be at 0xdecafbad.
*/
#define pabort(...) _pabort(__FILE__, __LINE__, __func__, ## __VA_ARGS__)
void _pabort(const char *file, int line, const char *func) __attribute__((noreturn));
void _pabort(const char* file, int line, const char *func, const char *fmt, ...)
__attribute__ ((format(printf, 4, 5), noreturn));
/////////////////////////////////////////////////////////////////////////////////
//
// Common: Assert with Message
//
/////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark Common: Assert with Message
/*
Abort the program if 'condition' is false.
Print out a stacktrace and formatted message; then cause a SEG fault to halt execution.
SEG fault will be at 0xdecafbad.
*/
# define passert_msg(condition, ...) \
do { \
if (! (condition)) \
_pabort(__FILE__, __LINE__, __func__, ## __VA_ARGS__); \
} while (false)
/*
Only defined, *even in DEBUG builds*, if the follow is #defined: PASSERT_INNERLOOPS
*/
#if (PASSERT_INNERLOOPS_ENABLED && !NDEBUG)
// Debug build with inner loop assert enabled.
/*
Defined for Debug mode, and if we want inner loop assertions.
*/
# define passert_innerloop(condition, ...) \
do { \
if (! (condition)) \
_pabort(__FILE__, __LINE__, __func__, ## __VA_ARGS__); \
} while (false)
#else
/*
Prevent any code generation.
*/
# define passert_innerloop(...) ((void)(0))
#endif
/*
Dev only passert_msg. Asserts using this will not run in release builds.
Meant for cases where in development we want to abort, but in production we
want to continue (and there is code to handle that case).
*/
#if !NDEBUG
# define passert_msg_dev(condition, ...) \
do { \
if (! (condition)) \
_pabort(__FILE__, __LINE__, __func__, ## __VA_ARGS__); \
} while (false)
#else
/*
Prevent any code generation.
*/
# define passert_msg_dev(...) ((void)(0))
#endif

View File

@@ -0,0 +1,421 @@
//
// VROMaterial.h
// ViroRenderer
//
// Created by Raj Advani on 11/17/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROMaterial_h
#define VROMaterial_h
#include <memory>
#include "VROMaterialVisual.h"
#include "VROAnimatable.h"
#include "VROStringUtil.h"
enum class VROFace {
Front,
Back,
FrontAndBack
};
enum class VROCullMode {
Back,
Front,
None
};
enum class VROBlendMode {
None,
Alpha,
Add,
Multiply, // Note: Unimplemented mode
Subtract, // Note: Unimplemented mode
Screen, // Note: Unimplemented mode
};
enum class VROTransparencyMode {
AOne,
RGBZero
};
enum class VROLightingModel {
Phong,
Blinn,
Lambert,
Constant,
PhysicallyBased
};
class VROLight;
class VRODriver;
class VROSortKey;
class VROMaterialSubstrate;
class VROShaderModifier;
/*
Manages the lighting and shading attributes associated with the surface of a geometry that
define its appearance when rendered. When you create a material, you define a collection of
visual attributes and their options, which you can then reuse for multiple geometries
in a scene.
*/
class VROMaterial : public VROAnimatable {
public:
VROMaterial();
virtual ~VROMaterial();
/*
Delete any rendering resources. Invoked prior to destruction, on the
rendering thread.
*/
void deleteGL();
/*
Copy constructor for this material. Texture contents use shared references.
*/
VROMaterial(std::shared_ptr<VROMaterial> material);
/*
Copy function, to write over all properties of this material with the
properties of the given material.
*/
void copyFrom(std::shared_ptr<VROMaterial> material);
/*
Set a name for this material. No functionality, only used for
debugging.
*/
void setName(std::string name) {
_name = name;
}
std::string getName() const {
return _name;
}
uint32_t getMaterialId() const {
return _materialId;
}
/*
Bind shader and properties. These must be called in order: material properties
cannot be bound until the shader is bound.
Lights are passed into bindShader because the shader used by a material
is a function both of that material's properties and of the desired lighting
configuration.
*/
void bindShader(int lightsHash,
const std::vector<std::shared_ptr<VROLight>> &lights,
const VRORenderContext &context,
std::shared_ptr<VRODriver> &driver);
void bindProperties(std::shared_ptr<VRODriver> &driver);
VROMaterialVisual &getDiffuse() const {
return *_diffuse;
}
VROMaterialVisual &getRoughness() const {
return *_roughness;
}
VROMaterialVisual &getMetalness() const {
return *_metalness;
}
VROMaterialVisual &getSpecular() const {
return *_specular;
}
VROMaterialVisual &getNormal() const {
return *_normal;
}
VROMaterialVisual &getReflective() const {
return *_reflective;
}
VROMaterialVisual &getEmission() const {
return *_emission;
}
VROMaterialVisual &getMultiply() const {
return *_multiply;
}
VROMaterialVisual &getAmbientOcclusion() const {
return *_ambientOcclusion;
}
VROMaterialVisual &getSelfIllumination() const {
return *_selfIllumination;
}
void setShininess(float shininess);
float getShininess() const {
return _shininess;
}
void setFresnelExponent(float fresnelExponent);
float getFresnelExponent() const {
return _fresnelExponent;
}
void setTransparency(float transparency);
float getTransparency() const {
return _transparency;
}
void setTransparencyMode(VROTransparencyMode mode) {
_transparencyMode = mode;
}
VROTransparencyMode getTransparencyMode() const {
return _transparencyMode;
}
void setLightingModel(VROLightingModel model) {
_lightingModel = model;
}
VROLightingModel getLightingModel() const {
return _lightingModel;
}
void setCullMode(VROCullMode cullMode) {
_cullMode = cullMode;
}
VROCullMode getCullMode() const {
return _cullMode;
}
bool isLitPerPixel() const {
return _litPerPixel;
}
VROBlendMode getBlendMode() const {
return _blendMode;
}
void setBlendMode(VROBlendMode mode){
_blendMode = mode;
}
bool getWritesToDepthBuffer() const {
return _writesToDepthBuffer;
}
bool getReadsFromDepthBuffer() const {
return _readsFromDepthBuffer;
}
void setWritesToDepthBuffer(bool writesToDepthBuffer) {
_writesToDepthBuffer = writesToDepthBuffer;
updateSubstrate();
}
void setReadsFromDepthBuffer(bool readsFromDepthBuffer) {
_readsFromDepthBuffer = readsFromDepthBuffer;
updateSubstrate();
}
void setBloomThreshold(float threshold) {
bool needsSubstrateUpdate = (_bloomThreshold >= 0 && threshold < 0) || (_bloomThreshold < 0 && threshold >= 0);
_bloomThreshold = threshold;
if (needsSubstrateUpdate) {
updateSubstrate();
}
}
float getBloomThreshold() const {
return _bloomThreshold;
}
bool isBloomSupported() const {
return _bloomThreshold >= 0;
}
void setReceivesShadows(bool receivesShadows) {
_receivesShadows = receivesShadows;
updateSubstrate();
}
bool getReceivesShadows() const {
return _receivesShadows;
}
void addShaderModifier(std::shared_ptr<VROShaderModifier> modifier);
void removeShaderModifier(std::shared_ptr<VROShaderModifier> modifier);
bool hasShaderModifier(std::shared_ptr<VROShaderModifier> modifier);
const std::vector<std::shared_ptr<VROShaderModifier>> &getShaderModifiers() const {
return _shaderModifiers;
}
void removeAllShaderModifiers() {
_shaderModifiers.clear();
}
/*
Make a snapshot of this material and cross-fade that snapshot out,
bringing in the current material. Used to animate material changes.
No effect if there is no active animation transaction.
*/
void fadeSnapshot();
std::shared_ptr<VROMaterial> getOutgoing() const {
return _outgoing;
}
/*
Check if the material has been updated since the last substrate was
created.
*/
bool isUpdated() {
return _substrate == nullptr;
}
/*
Force the substrate of this material to update on the next render cycle.
*/
void updateSubstrate();
/*
Faster than updateSubstrate(), used only when the textures of this material are
updated.
*/
void updateSubstrateTextures();
/*
Get the representation of this material in the underlying graphics
technology.
*/
VROMaterialSubstrate *const getSubstrate(std::shared_ptr<VRODriver> &driver);
/*
Update the given sort key with fields from this material, if the given
lights are used in the render.
*/
void updateSortKey(VROSortKey &key, const std::vector<std::shared_ptr<VROLight>> &lights,
const VRORenderContext &context,
std::shared_ptr<VRODriver> &driver);
/*
Returns a VROBlendMode for the given string. If no matching blend modes were found,
VROBlendMode::None is returned.
*/
static VROBlendMode getBlendModeFromString(std::string strType) {
if (VROStringUtil::strcmpinsensitive(strType, "Alpha")) {
return VROBlendMode::Alpha;
} else if (VROStringUtil::strcmpinsensitive(strType, "Add")) {
return VROBlendMode::Add;
} else if (VROStringUtil::strcmpinsensitive(strType, "Multiply")) {
return VROBlendMode::Multiply;
} else if (VROStringUtil::strcmpinsensitive(strType, "Subtract")) {
return VROBlendMode::Subtract;
} else if (VROStringUtil::strcmpinsensitive(strType, "Screen")) {
return VROBlendMode::Screen;
} else if (VROStringUtil::strcmpinsensitive(strType, "None")) {
return VROBlendMode::None;
}
return VROBlendMode::None;
}
private:
uint32_t _materialId;
/*
Properties used for PBR.
*/
VROMaterialVisual *_diffuse;
VROMaterialVisual *_roughness;
VROMaterialVisual *_metalness;
VROMaterialVisual *_ambientOcclusion;
/*
Properties used for standard lighting.
*/
VROMaterialVisual *_specular;
VROMaterialVisual *_reflective;
/*
Properties used for special effects.
*/
VROMaterialVisual *_normal;
VROMaterialVisual *_emission; // Unsupported (TODO VIRO-1188)
VROMaterialVisual *_multiply; // Unsupported (TODO VIRO-1190)
/*
Currently unsupported. This will be used to override the Scene's overall environment
map with a material-specific environment map.
*/
VROMaterialVisual *_selfIllumination;
/*
User-provided name of the material.
*/
std::string _name;
/*
The sharpness of specular highlights.
*/
float _shininess;
/*
Factor affecting material reflectivity.
*/
float _fresnelExponent;
/*
Uniform transparency of the material.
*/
float _transparency;
/*
The mode used to calculate transparency.
*/
VROTransparencyMode _transparencyMode;
/*
The lighting model to use to compute the interaction between
the lights in the scene and this material's visual properties.
*/
VROLightingModel _lightingModel;
/*
True means use per-pixel lighting, false means use per-vertex lighting.
*/
bool _litPerPixel;
/*
Set to cull back faces, front faces, or none.
*/
VROCullMode _cullMode;
/*
Determines how pixel colors rendered using this material blend with
pixel colors already in the render target.
*/
VROBlendMode _blendMode;
/*
Depth write and read settings.
*/
bool _writesToDepthBuffer, _readsFromDepthBuffer;
/*
Version of this material that's being animated away. Populated with the current
values of this material whenever this material is changed.
*/
std::shared_ptr<VROMaterial> _outgoing;
/*
Modifiers to alter the shader code.
*/
std::vector<std::shared_ptr<VROShaderModifier>> _shaderModifiers;
/*
If fragments of this material exceed this value, then those fragments will
glow. If less than 0, bloom will be disabled. Defaults to -1.
*/
float _bloomThreshold;
/*
True if this material receives shadows. Defaults to true.
*/
bool _receivesShadows;
/*
Representation of this material in the underlying graphics hardware.
*/
VROMaterialSubstrate *_substrate;
void removeOutgoingMaterial();
};
#endif /* VROMaterial_h */

View File

@@ -0,0 +1,39 @@
//
// VROMaterialAnimation.hpp
// ViroRenderer
//
// Created by Raj Advani on 2/14/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROMaterialAnimation_h
#define VROMaterialAnimation_h
#include <memory>
#include "VROLazyMaterial.h"
class VROMaterial;
/*
Represents a single material animation.
*/
class VROMaterialAnimation {
public:
VROMaterialAnimation(int index, std::shared_ptr<VROLazyMaterial> lazyMaterial) :
_index(index),
_lazyMaterial(lazyMaterial) {}
virtual ~VROMaterialAnimation() {}
int getIndex() const { return _index; }
std::shared_ptr<VROMaterial> getMaterial() const { return _lazyMaterial->get(); }
private:
const int _index;
std::shared_ptr<VROLazyMaterial> _lazyMaterial;
};
#endif /* VROMaterialAnimation_h */

View File

@@ -0,0 +1,81 @@
//
// VROMaterialSubstrate.h
// ViroRenderer
//
// Created by Raj Advani on 12/29/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROMaterialSubstrate_h
#define VROMaterialSubstrate_h
#include <stdio.h>
#include <vector>
#include <memory>
class VROSortKey;
class VROLight;
class VRORenderContext;
class VRODriver;
class VROGeometry;
class VROVector3f;
class VROMatrix4f;
enum class VROEyeType;
class VROMaterialSubstrate {
public:
virtual ~VROMaterialSubstrate() {}
/*
Update the textures used by this substrate. Invoked when the material's
textures are updated, in lieu of regenerating the entire substrate.
*/
virtual void updateTextures() = 0;
/*
Update the given sort key with the properties in this material, if the
given lights are used.
*/
virtual void updateSortKey(VROSortKey &key, const std::vector<std::shared_ptr<VROLight>> &lights,
const VRORenderContext &context,
std::shared_ptr<VRODriver> driver) = 0;
/*
Bind the shader used in this material to the active rendering context.
This is kept independent of the bindProperties() function because shader changes
are expensive, so we want to manage them independent of materials in the
render loop.
The shader used is a function both of the underlying material properties
and of the desired lighting configuration.
*/
virtual void bindShader(int lightsHash,
const std::vector<std::shared_ptr<VROLight>> &lights,
const VRORenderContext &context,
std::shared_ptr<VRODriver> &driver) = 0;
/*
Bind the properties of this material to the active rendering context.
These properties should be node and geometry independent. The shader
should always be bound first (via bindShader()).
*/
virtual void bindProperties() = 0;
/*
Bind the properties of the given geometry to the active rendering context.
These are material properties (e.g. shader uniforms) that are dependent
on properties of the geometry.
*/
virtual void bindGeometry(float opacity, const VROGeometry &geometry) = 0;
/*
Bind the properties of the view and projection to the active rendering
context.
*/
virtual void bindView(VROMatrix4f modelMatrix, VROMatrix4f viewMatrix,
VROMatrix4f projectionMatrix, VROMatrix4f normalMatrix,
VROVector3f cameraPosition, VROEyeType eyeType) = 0;
};
#endif /* VROMaterialSubstrate_h */

View File

@@ -0,0 +1,124 @@
//
// VROMaterialVisual.hpp
// ViroRenderer
//
// Created by Raj Advani on 11/17/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROMaterialVisual_h
#define VROMaterialVisual_h
#include "VROVector4f.h"
#include "VROMatrix4f.h"
#include "VROTexture.h"
#include "VROImageUtil.h"
#include "VROAnimatable.h"
#include <vector>
class VROMaterial;
class VROMaterialVisual {
public:
VROMaterialVisual(VROMaterial &material, int permissibleContentsMask) :
_material(material),
_permissibleContentsMask(permissibleContentsMask),
_contentsColor({ 1.0, 1.0, 1.0, 1.0 }),
_intensity(1.0)
{}
/*
Copy constructor. Texture references are shared.
*/
VROMaterialVisual(const VROMaterialVisual &visual);
/*
Delete any rendering resources. Invoked prior to destruction, on the
rendering thread.
*/
void deleteGL();
/*
Copy from the given visual to this one. Does NOT copy the
parent material, however.
*/
void copyFrom(const VROMaterialVisual &visual);
void clear();
void setColor(VROVector4f contents);
void setTexture(std::shared_ptr<VROTexture> texture);
/*
Used to replace a texture quickly without regenerating the
entire substrate. If this is the first time adding a texture,
then the substrate must be replaced. In this case we return
true.
*/
bool swapTexture(std::shared_ptr<VROTexture> texture);
VROTextureType getTextureType() const {
if (_contentsTexture) {
return _contentsTexture->getType();
}
else {
return VROTextureType::None;
}
}
VROVector4f getColor() const {
return _contentsColor;
}
std::shared_ptr<VROTexture> getTexture() const {
if (_contentsTexture) {
return _contentsTexture;
}
else {
return getBlankTexture();
}
}
void setIntensity(float intensity);
float getIntensity() const {
return _intensity;
}
private:
/*
Parent material.
*/
VROMaterial &_material;
/*
Bit mask of VROContentsType that indicates which contents types are
permissible to be set for this visual.
*/
int _permissibleContentsMask;
/*
The color component of the visual.
*/
VROVector4f _contentsColor;
/*
The texture component of the visual.
*/
std::shared_ptr<VROTexture> _contentsTexture;
/*
Modulates the impact of this visual on the overall material appearance.
*/
float _intensity;
/*
Transformation applied to the texture coordinates provided by the geometry object
the material is attached to.
*/
VROMatrix4f _contentsTransform;
};
#endif /* VROMaterialVisual_h */

View File

@@ -0,0 +1,181 @@
//
// VROMath.h
// ViroRenderer
//
// Created by Raj Advani on 10/15/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROMath_h
#define VROMath_h
#include <stdio.h>
#include <vector>
#include <cstdlib>
#include "VROVector3f.h"
#include "VROVector4f.h"
#include "VROMatrix4f.h"
#include "VROQuaternion.h"
#include "VROBoundingBox.h"
#include "VRODefines.h"
static float kRoundingErrorFloat = 0.00001;
static float kEpsilon = 0.00000001;
VROMatrix4f matrix_from_scale(float sx, float sy, float sz);
VROMatrix4f matrix_from_translation(float x, float y, float z);
VROMatrix4f matrix_from_perspective_fov_aspectLH(const float fovY, const float aspect,
const float nearZ, const float farZ);
/*
Compute a look-at matrix for a right handed coordinate system.
*/
VROMatrix4f VROMathComputeLookAtMatrix(VROVector3f eye, VROVector3f forward, VROVector3f up);
/*
Compute a frustum or perspective projection for a right handed coordinate system.
*/
VROMatrix4f VROMathComputeFrustum(float left, float right, float bottom, float top,
float znear, float zfar);
VROMatrix4f VROMathComputePerspectiveProjection(float fovyInDegrees, float aspectRatio,
float znear, float zfar);
/*
Compute an orthographic projection for a right handed coordinate system.
*/
VROMatrix4f VROMathComputeOrthographicProjection(float left, float right, float bottom, float top,
float near, float far);
double degrees_to_radians(double degrees);
double radians_to_degrees(double radians);
float clamp(float val, float min, float max);
float random(float min, float max);
VROVector3f random(VROVector3f min, VROVector3f max);
/*
4x4 column-major matrix operations.
*/
void VROMathMultVectorByMatrix(const float *matrix, const float *input, float *output);
void VROMathMultVectorByMatrix_d(const double *matrix, const double *input, double *output);
void VROMathMultVectorByMatrix_fd(const float *matrix, const double *input, double *output);
void VROMathMultMatrices(const float *a, const float *b, float *r);
void VROMathMultMatrices_d(const double *a, const double *b, double *r);
void VROMathMultMatrices_dff(const double *a, const float *b, float *r);
void VROMathMultMatrices_ddf(const double *a, const double *b, float *r);
void VROMathMultMatrices_fdf(const float *a, const double *b, float *r);
void VROMathMultMatrices_dfd(const double *a, const float *b, double *r);
void VROMathMultMatrices_fdd(const float *a, const double *b, double *r);
void VROMathMultMatrices_ffd(const float *a, const float *b, double *r);
void VROMathMakeIdentity(float *m);
void VROMathMakeIdentity_d(double *m);
void VROMathTransposeMatrix(const float *src, float *transpose);
bool VROMathInvertMatrix(const float *src, float *inverse);
bool VROMathInvertMatrix_d(const double *src, double *inverse);
/*
4x4 special matrix ops.
*/
void VROMathMultMatricesOptScale(const float *m1, const float *m0, float *d);
void VROMathMultMVP(const float *m1, const float *m0, float *d);
void VROMathMultVX(const float *vx, const float *m0, float *d);
/*
Interpolation functions.
*/
float VROMathInterpolate(float input, float inMin, float inMax, float outMin, float outMax);
double VROMathInterpolate_d(double input, double inMin, double inMax, double outMin, double outMax);
float VROMathInterpolateKeyFrame(float input, const std::vector<float> &inputs, const std::vector<float> &outputs);
VROVector3f VROMathInterpolateKeyFrameVector3f(float input, const std::vector<float> &inputs, const std::vector<VROVector3f> &outputs);
VROQuaternion VROMathInterpolateKeyFrameQuaternion(float input, const std::vector<float> &inputs, const std::vector<VROQuaternion> &outputs);
VROMatrix4f VROMathInterpolateKeyFrameMatrix4f(float input, const std::vector<float> &inputs, const std::vector<VROMatrix4f> &outputs);
void VROMathInterpolatePoint(const float *bottom, const float *top, float amount, int size, float *result);
/*
* Clamps input between min and max
*/
double VROMathClamp(double input, double min, double max);
/*
Array math
*/
float VROMathMin(const float values[], int count);
float VROMathMax(const float values[], int count);
/*
Angle conversion.
*/
float toRadians(float degrees);
float toDegrees(float radians);
/*
Rotation.
*/
void VROMathRotateAroundX(const VROVector3f &vector, float radians, VROVector3f *result);
void VROMathRotateAroundZ(const VROVector3f &vector, float radians, VROVector3f *result);
/*
Normalize the given angle between [0,2PI] or [-PI,PI], and find the distance between two angles.
*/
float VROMathNormalizeAngle2PI(float rad);
float VROMathNormalizeAnglePI(float rad);
float VROMathAngleDistance(float radA, float radB);
/*
Normalize the angles in the given vector between [0, 2PI].
*/
VROVector3f VROMathNormalizeAngles2PI(VROVector3f vector);
/*
Take the fast (inverse) square root of the given number.
*/
float VROMathFastSquareRoot(float x);
/*
Fast sin/cos methods. An input angle between [-PI, PI] will skip a
range reduction step, and may perform slightly faster, but is
unnessisary.
*/
void VROMathFastSinCos(float x, float r[2]);
void VROMathFastSinCos2x(const float *angles, float * r);
/**
Determine whether point (x,y) is within polygon (x1,y1 to x2,y2 to x3,y3 to x4,y4 to x1,y1)
Point on edge is considered within.
Only for use with convex polygons.
*/
bool VROMathPointIsInPolygon(float x, float y, float x1, float y1,
float x2, float y2, float x3, float y3,
float x4, float y4);
/*
Get the point on segment AB that is closest to p.
*/
VROVector3f VROMathGetClosestPointOnSegment(const VROVector3f A, const VROVector3f B, const VROVector3f p);
/* return the power of 2 that is equal or greater to the given value */
static inline uint32_t
power2_ceil(const uint32_t v) {
return (v < 2) ? v + 1 : 1 << (sizeof(uint32_t) * 8 - __builtin_clz(v - 1));
}
float VROMathReciprocal(float value);
float VROMathReciprocalSquareRoot(float value);
bool VROMathIsZero(const float a, const float tolerance = kRoundingErrorFloat);
bool VROMathEquals(const float a, const float b, const float tolerance = kRoundingErrorFloat);
float VROFloat16ToFloat(short fltInt16);
short VROFloatToFloat16(float value);
VROVector3f VROMathGetCenter(std::vector<VROVector3f> &vertices);
VROBoundingBox VROMathGetBoundingBox(std::vector<VROVector3f> &vertices);
uint32_t VROMathRoundUpToNextPow2(uint32_t v);
#endif /* VROMath_h */

View File

@@ -0,0 +1,100 @@
//
// VROMatrix4f.h
// ViroRenderer
//
// Created by Raj Advani on 10/15/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROMATRIX_H_
#define VROMATRIX_H_
#include <stdlib.h>
#include <math.h>
#include <string>
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
class VROVector3f;
class VROVector4f;
class VROQuaternion;
class VROMatrix4f {
public:
static VROMatrix4f identity();
float &operator[] (const int index) {
return _mtx[index];
}
float const &operator[](int index) const {
return _mtx[index];
}
VROMatrix4f() noexcept;
VROMatrix4f(const float *matrix);
VROMatrix4f(const glm::mat4x4 mat);
void toIdentity();
void copy(const VROMatrix4f &copy);
/*
Scale.
*/
void scale(float x, float y, float z);
/*
Rotation.
*/
void rotateX(float angleRad);
void rotateY(float angleRad);
void rotateZ(float angleRad);
void rotate(float angleRad, const VROVector3f &origin, const VROVector3f &dir);
void setRotationCenter(const VROVector3f &center, const VROVector3f &translation);
/*
Translation.
*/
void translate(float x, float y, float z);
void translate(const VROVector3f &vector);
/*
Multiplication.
*/
VROMatrix4f multiply(const VROMatrix4f &matrix) const;
VROVector3f multiply(const VROVector3f &vector) const;
VROVector4f multiply(const VROVector4f &vector) const;
/*
Decomposition into affine transforms. These methods only work on affine
matrices. To extract rotation, the scale factors are required.
*/
VROVector3f extractScale() const;
VROQuaternion extractRotation(VROVector3f scale) const;
VROVector3f extractTranslation() const;
/*
Other operations.
*/
VROMatrix4f transpose() const;
VROMatrix4f invert() const;
const float *getArray() const {
return _mtx;
}
std::string toString() const;
private:
/*
The 16-float data for this matrix.
*/
float _mtx[16];
};
inline VROMatrix4f operator*(const VROMatrix4f &lhs, const VROMatrix4f &rhs) {
return lhs.multiply(rhs);
}
#endif /* VROMATRIX_H_ */

View File

@@ -0,0 +1,61 @@
//
// VROModelIOUtil.h
// ViroRenderer
//
// Created by Raj Advani on 5/2/17.
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROModelIOUtil_h
#define VROModelIOUtil_h
#include <string>
#include <map>
#include <memory>
class VROTexture;
/*
The type of file within which the model is stored. On Android, use URL with file:///android-asset/
to load assets.
*/
enum class VROResourceType {
LocalFile, // Local file path
URL, // URL (remote or local)
BundledResource, // App-bundled resource
};
/*
Static utilities for Model IO.
*/
class VROModelIOUtil {
public:
/*
Load the texture with the given name, from the given base path (or base URL). First check
if the texture exists in the provided resourceMap or cache. If the texture could not be
loaded, returns an empty shared_ptr.
Set sRGB to true to gamma-uncorrect the texture into linear RGB when sampling. This should
only be used for color (diffuse) textures, and not for textures that are *already* linear
(e.g. specular, normal, etc.).
*/
static std::shared_ptr<VROTexture> loadTexture(const std::string &name, std::string &base, VROResourceType type, bool sRGB,
const std::map<std::string, std::string> *resourceMap,
std::map<std::string, std::shared_ptr<VROTexture>> &cache);
/*
Copy the resource or map of resources into a location where they can be loaded by the model
loader, and return the new paths.
This performs no action on local files.
*/
static std::string processResource(std::string resource, VROResourceType type, bool *isTemp,
bool *success);
static std::map<std::string, std::string> processResourceMap(const std::map<std::string, std::string> &resourceMap,
VROResourceType type);
};
#endif /* VROModelIOUtil_h */

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 */

View File

@@ -0,0 +1,94 @@
//
// VRONodeCamera.h
// ViroRenderer
//
// Created by Raj Advani on 3/24/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VRONodeCamera_h
#define VRONodeCamera_h
#include "VROAnimatable.h"
#include "VROVector3f.h"
#include "VROQuaternion.h"
enum class VROCameraRotationType;
/*
Node cameras are attached to nodes, and derive their base position and rotation
from said parent node. The "active" node camera each frame becomes the
point of view from which the scene is rendered in that frame. To designate
a node camera as active, set the VROView's pointOfView property to that
camera's node.
*/
class VRONodeCamera : public VROAnimatable {
public:
VRONodeCamera();
virtual ~VRONodeCamera();
void setPosition(VROVector3f position);
void setBaseRotation(VROQuaternion baseRotation);
void setRotationType(VROCameraRotationType type);
void setOrbitFocalPoint(VROVector3f focalPt);
void setFieldOfViewY(float fovy);
VROVector3f getPosition() const {
return _position;
}
VROQuaternion getBaseRotation() const {
return _baseRotation;
}
VROCameraRotationType getRotationType() const {
return _rotationType;
}
VROVector3f getOrbitFocalPoint() const {
return _orbitFocalPt;
}
float getFieldOfView() const {
return _fov;
}
private:
/*
The position of the camera, relative to the node's coordinate system.
*/
VROVector3f _position;
/*
The base rotation. This is set by the application. Total rotation is head
rotation plus base rotation plus the rotation of the parent node.
*/
VROQuaternion _baseRotation;
/*
The camera rotation type (orbit around a focal point, or standard rotation).
*/
VROCameraRotationType _rotationType;
/*
If in orbit mode, this is the point that the camera focuses on, from its current
position. Specified in the coordinate system of the parent node.
*/
VROVector3f _orbitFocalPt;
/*
The field of view for this camera, along the major (larger) axis. The minor axis
FOV will be automatically computed from this and the viewport. If this is zero, then
Viro will use the default FOV for the view. This value is ignored on VR and AR
platforms, where the FOV is fixed by the eye settings or the camera. This value
is given in degrees.
Note that the major axis is the axis with the larger dimension: the X axis in landscape
mode, or the Y axis in portrait mode. By specifying the FOV in terms of the major axis, Viro
can keep the FOV consistent even upon orientation changes when the major/minor axes
swap.
*/
float _fov;
};
#endif /* VRONodeCamera_hpp */

View File

@@ -0,0 +1,65 @@
//
// VROOBJLoader.h
// ViroRenderer
//
// Created by Raj Advani on 12/13/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROOBJLoader_h
#define VROOBJLoader_h
#include <stdio.h>
#include <vector>
#include <string>
#include <memory>
#include <map>
#include <functional>
#include "VROGeometrySource.h"
#include "VROGeometryElement.h"
#include "tiny_obj_loader.h"
class VRONode;
class VROTexture;
class VROGeometry;
enum class VROResourceType;
class VROOBJLoader {
public:
/*
Load the OBJ file at the given resource. For all dependent resources
(e.g. textures) found, locate them in the parent folder of the resource.
If async is true, an empty node is immediately returned while the OBJ is
loaded in the background. Afterward, the geometry is injected into the node
on the main (rendering) thread, and the given callback is invoked.
If async is false, the callback is still executed.
*/
static void loadOBJFromResource(std::string resource, VROResourceType type,
std::shared_ptr<VRONode> destination,
bool async = false, std::function<void(std::shared_ptr<VRONode> node, bool success)> onFinish = nullptr);
static void loadOBJFromResources(std::string resource, VROResourceType type,
std::shared_ptr<VRONode> destination,
std::map<std::string, std::string> resourceMap,
bool async = false, std::function<void(std::shared_ptr<VRONode> node, bool success)> onFinish = nullptr);
private:
static void injectOBJ(std::shared_ptr<VROGeometry> geometry, std::shared_ptr<VRONode> node,
std::function<void(std::shared_ptr<VRONode> node, bool success)> onFinish);
static std::shared_ptr<VROGeometry> loadOBJ(std::string file, std::string base, VROResourceType type);
static std::shared_ptr<VROGeometry> loadOBJ(std::string file,
std::map<std::string, std::string> resourceMap);
static std::shared_ptr<VROGeometry> processOBJ(tinyobj::attrib_t attrib,
std::vector<tinyobj::shape_t> &shapes,
std::vector<tinyobj::material_t> &materials,
std::string base,
VROResourceType type,
std::map<std::string, std::string> *resourceMap = nullptr);
};
#endif /* VROOBJLoader_h */

View File

@@ -0,0 +1,77 @@
//
// VROOpenGL.h
// ViroRenderer
//
// Created by Raj Advani on 11/2/16.
// Copyright © 2016 Viro Media. All rights reserved.
//
#ifndef VROOpenGL_h
#define VROOpenGL_h
#include "VRODefines.h"
#include "VROLog.h"
#if VRO_PLATFORM_ANDROID
#include <cstring>
#include <stdlib.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <GLES2/gl2ext.h>
#include <GLES3/gl3ext.h>
#include <GLES3/gl3platform.h>
// Avoiding glBufferSubData seems to increase stability on Adreno devices
#define VRO_AVOID_BUFFER_SUB_DATA 1
#elif VRO_PLATFORM_IOS
#import <OpenGLES/EAGL.h>
#import <OpenGLES/ES1/glext.h>
#import <OpenGLES/ES2/gl.h>
#import <OpenGLES/ES2/glext.h>
#import <OpenGLES/ES3/gl.h>
#import <OpenGLES/ES3/glext.h>
#define VRO_AVOID_BUFFER_SUB_DATA 0
#endif
#ifdef CHECK_GL_ERRORS
static const char * GlErrorString( GLenum error )
{
switch ( error )
{
case GL_NO_ERROR: return "GL_NO_ERROR";
case GL_INVALID_ENUM: return "GL_INVALID_ENUM";
case GL_INVALID_VALUE: return "GL_INVALID_VALUE";
case GL_INVALID_OPERATION: return "GL_INVALID_OPERATION";
case GL_INVALID_FRAMEBUFFER_OPERATION: return "GL_INVALID_FRAMEBUFFER_OPERATION";
case GL_OUT_OF_MEMORY: return "GL_OUT_OF_MEMORY";
default: return "unknown";
}
}
static void GLCheckErrors( int line )
{
for ( int i = 0; i < 10; i++ )
{
const GLenum error = glGetError();
if ( error == GL_NO_ERROR )
{
break;
}
pinfo( "GL error on line %d: %s", line, GlErrorString( error ) );
}
}
#define GL( func ) func; GLCheckErrors( __LINE__ );
#else // CHECK_GL_ERRORS
#define GL( func ) func;
#endif // CHECK_GL_ERRORS
#endif /* VROOpenGL_h */

View File

@@ -0,0 +1,73 @@
//
// VROParticle.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROParticle_h
#define VROParticle_h
#include "VROMatrix4f.h"
#include "VROVector4f.h"
#include "VROVector3f.h"
/*
Struct containing all properties relating to a single particle, such as
life cycle spawn, transformations, color and physics states.
*/
struct VROParticle{
// Position at which particle had spawned at, local to the particle emitter.
VROMatrix4f spawnedLocalTransform;
// Position at which particle had spawned at, in world transform.
VROMatrix4f spawnedWorldTransform;
// Current position of the particle, local to the particle emitter.
VROMatrix4f currentLocalTransform;
// Current position of the particle, in world transform
VROMatrix4f currentWorldTransform;
// True if this particle's scale, rotation and position are continously
// affected by changes in the emitter's transform after it has been spawned.
bool fixedToEmitter;
// Initial values representing scale, rotation, physics and color properties;
// These are all determined by VROParticleModifiers that have been set on the emitter.
VROVector3f initialRotation;
VROVector3f initialScale;
VROVector3f initialColor;
VROVector3f initialVelocity;
VROVector3f initialAccel;
VROVector3f initialAlpha;
VROVector4f colorCurrent;
// The amount of time that had passed for this particle, since it had spawned.
double timeSinceSpawnedInMs;
// The total amount of travelled distance from it's spawned location.
double distanceTraveled;
// The current speed at which this particle is travelling at.
double velocity;
// True if the particle has died but is not yet due to be de-allocated.
// This is mainly used for recycling particles quickly and to reduce the
// numerous number of allocations / de-allocations of particle objects.
bool isZombie;
// Time at which this particle was spawned at in milliseconds.
double spawnTimeMs;
// Time at which this particle is killed and becomes a zombie, in milliseconds.
double killedTimeMs;
// Duration of time a particle remains alive, in milliseconds.
double lifePeriodMs;
// Duration of time a particle remains a zombie before being deallocated, in milliseconds.
double zombiePeriodMs;
};
#endif /* VROParticle_h */

View File

@@ -0,0 +1,470 @@
//
// VROParticleEmitter.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROParticleEmitter_h
#define VROParticleEmitter_h
#include "VRODriver.h"
#include "VROParticleModifier.h"
// Assumed mass of a single particle, used for all physics calculations.
static float kAssumedParticleMass = 1;
class VROSurface;
class VROParticleUBO;
class VROParticle;
class VROTexture;
/*
Volume describing the area around which particles spawn within / around.
*/
struct VROParticleSpawnVolume{
enum class Shape{
Box,
Sphere,
Point
};
static VROParticleSpawnVolume::Shape getModifierFactorForString(std::string strType) {
if (VROStringUtil::strcmpinsensitive(strType, "Box")) {
return VROParticleSpawnVolume::Shape::Box;
} else if (VROStringUtil::strcmpinsensitive(strType, "Sphere")) {
return VROParticleSpawnVolume::Shape::Sphere;
} else {
return VROParticleSpawnVolume::Shape::Point;
}
}
Shape shape;
// Vec of params to be provided for configuring the specified shape.
std::vector<float> shapeParams;
// True if particles should be spawned on this shape's surface
// instead of within it. Applicable for Box and Sphere shapes only.
bool spawnOnSurface;
};
/*
VROParticleEmitter handles the behavior of quad particles emitted in the scene in terms of
its life cycle, physical motion, and visual characteristics like color and alpha.
*/
class VROParticleEmitter {
public:
VROParticleEmitter(std::shared_ptr<VRODriver> driver,
std::shared_ptr<VROSurface> particleGeometry);
/*
Constructor that creates an uninitialized emitter. To initialize this emitter before
it can be configured / modified, call VROParticleEmitter::initEmitter();
*/
VROParticleEmitter();
virtual ~VROParticleEmitter();
/*
Called per frame to update particle states, lifetime and behavior. The computedTransform
is the final transform of this emitter's parent node.
*/
virtual void update(const VRORenderContext &context, const VROMatrix4f &computedTransform);
/*
Allows for setting of the particleSurface if initEmitter has already been called.
*/
virtual void setParticleSurface(std::shared_ptr<VROSurface> particleSurface);
std::shared_ptr<VROGeometry> getParticleSurface() const;
void setRun(bool emit) {
_requestRun = emit;
}
void setDuration(double duration) {
_duration = duration;
}
void setDelay(double delay) {
_emitterDelayDuration = delay;
}
void setLoop(bool loop) {
_loop = loop;
}
void setFixedToEmitter(bool isFixed) {
_fixToEmitter = isFixed;
}
virtual void setMaxParticles(int maxParticles) {
_maxParticles = maxParticles;
}
void setParticleLifeTime(std::pair <int, int> lifeTime) {
_particleLifeTime = lifeTime;
}
void setEmissionRatePerSecond(std::pair <int, int> rate) {
_particlesEmittedPerSecond = rate;
}
void setEmissionRatePerDistance(std::pair <int, int> rate) {
_particlesEmittedPerMeter = rate;
}
void setBlendMode(VROBlendMode mode);
void setBloomThreshold(float threshold);
/*
True if we are no longer emitting particles and have completed the emission cycle.
*/
bool finishedEmissionCycle();
/*
Reset back to the beginning of the emission cycle for this emitter.
*/
void resetEmissionCycle(bool resetParticles);
/*
Used for constructing the behavior of how bursts of particles spawn.
*/
struct VROParticleBurst {
// Reference factor against which to compare when deciding how to burst-spawn particles.
VROParticleModifier::VROModifierFactor referenceFactor;
// Min, Max range of number of particles to spawn.
std::pair<int, int> numberOfParticles;
// Starting Reference Value at which to begin the burst.
double referenceValueStart;
// Cool down period in milliseconds or distance in meters after each burst.
double referenceValueInterval;
// Number of times to repeat this burst.
int cycles;
};
/*
Sets on this emitter a list of VROParticleBurst to emit.
*/
void setParticleBursts(std::vector<VROParticleBurst> bursts) {
_bursts = bursts;
_scheduledBurst = bursts;
}
/*
Overrides the current specified VROParticleSpawnVolume.
*/
void setParticleSpawnVolume(VROParticleSpawnVolume volume) {
_currentVolume = volume;
}
/*
Parameters for configuring an initial explosive force at a given explosionPoint local
to the emitter with a magnitude of impulseExplosion.
*/
void setInitialExplosion(VROVector3f explosionPoint, float impulseExplosion, float decelleration = -1) {
_explosionCenter = explosionPoint;
_impulseExplosionMagnitude = impulseExplosion;
_impulseDeaccelerationExplosionPeriod = decelleration;
}
/*
Below are specific particle modifiers that can be set by the bridge, that defines the
behavior and appearance of emitted particles.
*/
void setAlphaModifier(std::shared_ptr<VROParticleModifier> mod) {
_alphaModifier = mod;
}
void setColorModifier(std::shared_ptr<VROParticleModifier> mod) {
_colorModifier = mod;
}
void setScaleModifier(std::shared_ptr<VROParticleModifier> mod) {
_scaleModifier = mod;
}
void setRotationModifier(std::shared_ptr<VROParticleModifier> mod) {
_rotationModifier = mod;
}
void setVelocityModifier(std::shared_ptr<VROParticleModifier> mod) {
_velocityModifier = mod;
}
void setAccelerationmodifier(std::shared_ptr<VROParticleModifier> mod) {
_accelerationModifier = mod;
}
/*
Initialize the emitter with default configurations and states.
*/
void initEmitter(std::shared_ptr<VRODriver> driver,
std::shared_ptr<VROSurface> particleGeometry);
void setDefaultValues();
protected:
/*
The last transform computed for this emitter's parent node. Used when resetting
particles.
*/
VROMatrix4f _lastComputedTransform;
/*
The geometry used to represent particles in this emitter.
*/
std::shared_ptr<VROSurface> _particleGeometry;
/*
List of all particles in the scene for this emitter. This includes active particles (particles
that have just been spawned and are animating in the scene) and also zombie particles
(particles that are just killed and become a zombie temporarily before being de-allocated
and removed from this list to encourage the recycling of particle objects).
*/
std::vector<VROParticle> _particles;
/*
Vector containing all particles that have died so that they can be reused. Particles
in a zombie start after a certain time will be de-allocated.
*/
std::vector<VROParticle> _zombieParticles;
/*
The maximum number of active particles (not including zombie ones) that this emitter
can have at any given moment.
*/
int _maxParticles;
private:
#pragma mark - Particle Emission Behaviors
/*
Flag for setting the _run state on a render pass. This is required because emitter states that
are updated as a result of changes to the _run flag are dependent on certain scene->compute
render passes to occur first before we compute this Particle emitter (like transforms).
*/
bool _requestRun;
/*
True to continue emitting particles from when the emitter had last stopped.
*/
bool _run;
/*
The length of time in milliseconds this emitter is emitting particles.
*/
double _duration;
/*
If true, the emission cycle will repeat after the duration.
*/
bool _loop;
/*
If false, already emitted particles will not be affected by transformation changes made
to this emitter's node, else, they would be "locked" to the emitter.
*/
bool _fixToEmitter;
/*
Below are specific particle modifiers that can be set by the bridge, that defines the
behavior and appearance of emitted particles.
*/
std::shared_ptr<VROParticleModifier> _alphaModifier;
std::shared_ptr<VROParticleModifier> _colorModifier;
std::shared_ptr<VROParticleModifier> _scaleModifier;
std::shared_ptr<VROParticleModifier> _rotationModifier;
std::shared_ptr<VROParticleModifier> _velocityModifier;
std::shared_ptr<VROParticleModifier> _accelerationModifier;
/*
Emission of extra particles at specific times or distances during the entire _duration
this emitter is emitting.
*/
std::vector<VROParticleBurst> _bursts;
/*
Copied from _burst at the beginning of every emitter emission cycle to schedule and
maintain the state of all incoming burst events.
*/
std::vector<VROParticleBurst> _scheduledBurst;
/*
The min max lifetime of emitted particles, in milliseconds.
*/
std::pair <int, int> _particleLifeTime;
#pragma mark - Emitter Attributes
/*
Length of time in milliseconds this emitter delays before emitting particles.
Note that this will not be include in _duration.
*/
double _emitterDelayDuration = -1;
/*
Time at which we have started the delay, used for tracking the delay status by
checking against: _emitterDelayStartTime + _emitterDelayTimePassedSoFar > currentTime.
*/
double _emitterDelayStartTime = -1;
/*
Length of delay time left before emitting particles. This is reset to _emitterDelayDuration
but is manipulated / subtracted to track remaining delay time as the emitter is paused/resumed.
*/
double _emitterDelayTimePassedSoFar = 0;
/*
Total time that has passed since the beginning of this emitter's emission cycle.
*/
double _emitterTotalPassedTime = 0;
/*
Time that has passed since this emitter has last started. It is redefined as the emitter
is paused / resumed.
*/
double _emitterPassedTimeSoFar = 0;
/*
Time at which this emitter has been started at in milliseconds.
*/
double _emitterStartTimeMs = 0;
/*
Total travelled distance of the emitter since the beginning of this emitter's emission cycle.
*/
double _emitterTotalPassedDistance = 0;
/*
Distance travelled since this emitter has last started. It is redefined as the emitter
is paused / resumed.
*/
double _emitterPassedDistanceSoFar = 0;
/*
Location at which this emitter has started at. It is redefined as the emitter
is paused / resumed.
*/
VROVector3f _emitterStartLocation;
/*
Set for determining how many particles should be emitted per distance travelled of this
emitter, if any. The pair defines a uniform distribution (min, max).
*/
std::pair <int, int> _particlesEmittedPerMeter;
/*
Position at which we had last emitted particles that were distance spawned.
*/
VROVector3f _distanceSpawnedLastEmitPosition;
/*
Position where we first started distance spawning particles from.
*/
VROVector3f _distanceSpawnedInitPosition;
/*
Rate at which particles are distance spawned, per meter.
*/
double _distanceSpawnedEmissionRate = 0;
/*
Set for determining how many particles should be emitted per second of _duration of this
emitter, if any. The pair defines a uniform distribution (min, max).
*/
std::pair <int, int> _particlesEmittedPerSecond;
/*
Time at which we had last emitted particles that were time spawned.
*/
double _intervalSpawnedLastEmitTime = 0;
/*
Time when we had first started time-spawning particles from.
*/
double _intervalSpawnedInitTime = 0;
double _particlesSpawnIntervalMs = 100;
double _intervalSpawnedEmissionRate = 0;
/*
Updates any time / distance state that the emitter needs to determine particle behavior.
*/
void updateEmitter(double currentTime, const VROMatrix4f &computedTransform);
/*
Processes any delay period left on this particle emitter's current emit cycle.
Returns true if any delay was processed, false otherwise.
*/
bool processDelay(double currentTime);
#pragma mark - Particle Attributes
/*
Below are specific update functions that define the behavior and appearance
of the particle.
*/
void updateParticles(double currentTime, const VRORenderContext &context,
const VROMatrix4f &computedTransform, bool isCurrentlyDelayed);
void updateParticlePhysics(double currentTime);
void updateParticleAppearance(double currentTime);
void updateParticlesToBeKilled(double currentTime);
void updateParticleSpawn(double currentTime, VROVector3f currentPos);
void updateZombieParticles(double currentTime);
/*
Called when we wish to spawn new particles, given the numberOfParticles. To do so,
we firstly attempt to recycle zombie particles and create new ones if we do ever run out.
*/
void spawnParticle(int numberOfParticles, double currentTime);
/*
Returns the number of particles to spawn at the given currentTime with the set
_particlesEmittedPerSecond on this emitter.
*/
int getSpawnParticlesPerSecond(double currentTime);
/*
Returns the number of particles to spawn at the given position with the set
_particlesEmittedPerMeter on this emitter.
*/
int getSpawnParticlesPerMeter(VROVector3f currentPos);
/*
Returns the number of particles to spawn based on _scheduledBurst.
*/
int getSpawnParticleBursts();
/*
Resets the particle to a set of known defaults, so that it can be re-used / re-emitted.
*/
void resetParticle(VROParticle &particle, double currentTime);
/*
Volume defining the location of where particles would spawn.
*/
VROParticleSpawnVolume _currentVolume;
/*
Location local to this Particle Emitter from which to calculate an explosive force
to determine initial velocity.
*/
VROVector3f _explosionCenter;
/*
The magnitude of an explosion's impulse.
*/
float _impulseExplosionMagnitude = -1;
double _impulseDeaccelerationExplosionPeriod = -1;
/*
Grabs a random point from the currently configured _currentVolume.
*/
VROVector3f getPointInSpawnVolume();
/*
Extrapolate the initial velocity for this particle if explosion parameters have been set.
*/
VROVector3f getExplosionInitialVel(VROVector3f particlePosition);
VROVector3f getExplosionAccel(VROVector3f particlePosition);
};
#endif /* VROParticleEmitter_h */

View File

@@ -0,0 +1,229 @@
//
// VROParticleModifier.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROParticleModifier_h
#define VROParticleModifier_h
#include <memory>
#include <vector>
#include <algorithm>
#include "VROMatrix4f.h"
#include "VROVector4f.h"
#include "VROOpenGL.h"
#include "VROVector3f.h"
#include "VROParticle.h"
#include "VROMath.h"
#include "VROStringUtil.h"
/*
VROParticleModifier contains a list of VROModifierIntervals to interpolate against with
referenceFactor to time, distance or velocity (as defined by a given VROModifierFactor). This
is used by VROParticleEmitter to pre-define a set of particle property behaviors (color,
scale, rotation, etc) that can then be applied to any particle.
*/
class VROParticleModifier {
public:
/*
VROModifierFactor represents the referenceFactor factor this modifier will interpolate against.
*/
enum class VROModifierFactor {
Time, // Interpolate against the timeSinceSpawnedInMs of a particle.
Distance, // Interpolate against the distanceTravelled of a particle.
Velocity // Interpolate against the current velocity of a particle.
};
static VROModifierFactor getModifierFactorForString(std::string strType) {
if (VROStringUtil::strcmpinsensitive(strType, "Velocity")) {
return VROModifierFactor::Velocity;
} else if (VROStringUtil::strcmpinsensitive(strType, "Distance")) {
return VROModifierFactor::Distance;
} else {
return VROModifierFactor::Time;
}
}
/*
Interpolation points between which to animate a given initial value (most likely the
particle's property value) towards.
*/
struct VROModifierInterval {
// Property of the particle to interpolate towards for this given VROModifierWindow.
VROVector3f targetedValue;
// Start and End factor values. For example, startTime and endTime.
double startFactor;
double endFactor;
bool operator < (const VROModifierInterval& point) const {
return (endFactor <= point.startFactor);
}
};
VROParticleModifier(VROVector3f constant) {
init(constant, constant, VROModifierFactor::Time);
};
VROParticleModifier(VROVector3f minRange, VROVector3f maxRange) {
init(minRange, maxRange, VROModifierFactor::Time);
};
VROParticleModifier(VROVector3f minRange, VROVector3f maxRange,
VROModifierFactor factor, std::vector<VROModifierInterval> values) {
init(minRange, maxRange, factor);
setInterpolatedPoints(values);
};
virtual ~VROParticleModifier(){};
VROVector3f getInitialValue() {
return random(_initialMinValue, _initialMaxValue);
}
/*
Apply the behavior of this modifier (set by VROInterpolateValues) on the given initialValue
with referenceFactor to the preset _referenceFactor.
*/
VROVector3f applyModifier(VROParticle &particle, VROVector3f initialValue) {
if (_modifierInterval.size() <= 0) {
return initialValue;
}
double deltaFactor = getReferenceFactorForParticle(particle);
return getFinalValue(initialValue, deltaFactor);
}
private:
void init(VROVector3f minRange, VROVector3f maxRange, VROModifierFactor factor) {
_initialMinValue = minRange;
_initialMaxValue = maxRange;
_referenceFactor = factor;
}
/*
Min and Max ranges from which randomize across and determine the initial value applied
by this modifier.
*/
VROVector3f _initialMinValue;
VROVector3f _initialMaxValue;
/*
Reference factor this modifier will interpolate against (Time, Distance or Velocity).
*/
VROModifierFactor _referenceFactor;
/*
List of VROModifiers with values dictating the behavior of this modifier, along which this
VROParticleModifier will interpolate against.
*/
std::vector<VROModifierInterval> _modifierInterval;
/*
Sets a list of VROModifierInterval values that will be used by this VROParticleModifier.
*/
void setInterpolatedPoints(std::vector<VROModifierInterval> values) {
if (values.size() == 0 ){
return;
}
std::sort(values.begin(), values.end());
for (int i = 0; i < values.size() - 1; i ++) {
if (values[i].endFactor > values[i + 1].startFactor
|| (values[i].startFactor > values[i].endFactor)) {
perror("Attempted to set an invalid set of interpolated points for the Particle Emitter!");
return;
}
}
_modifierInterval = values;
}
/*
Returns the referenceFactor factor value from the provided particle. The type of referenceFactor factor
is determined by this VROParticleModifier _referenceFactor.
*/
double getReferenceFactorForParticle(const VROParticle &particle) {
if (_referenceFactor == VROModifierFactor::Distance) {
return particle.distanceTraveled;
} else if (_referenceFactor == VROModifierFactor::Velocity) {
return particle.velocity;
}
return particle.timeSinceSpawnedInMs;
}
/*
With the given particle, and based on this emitter's referenceFactor factor, determine the amount of
passed time, distance, or velocity that is required to interpolate the desired value.
*/
VROVector3f getFinalValue(VROVector3f initialValue, double currentFactor) {
VROVector3f start;
VROVector3f end;
for (int i = 0; i < _modifierInterval.size(); i ++) {
// Determine if this VROModifierInterval contains a startFactor and endFactor interval
// that applies to the current deltaFactor.
if (currentFactor >= _modifierInterval[i].startFactor && currentFactor <= _modifierInterval[i].endFactor) {
// If so, calculate progression ratio
float delta = currentFactor - _modifierInterval[i].startFactor;
float deltaWindow = _modifierInterval[i].endFactor - _modifierInterval[i].startFactor;
float ratio = delta / deltaWindow;
if (i == 0){
start = initialValue;
} else {
start = _modifierInterval[i-1].targetedValue;
}
end = _modifierInterval[i].targetedValue;
return interpolatePoint(start, end, ratio);
}
// Else, if we can't find a VROModifierInterval that matches the currentFactor,
// check if the currentFactor may be referring to a time/distance period in between
// VROModifierIntervals. If so, attempt to find the last known VROModifierInterval
// that we had applied before and use its ending value.
if (i != 0 && currentFactor >= _modifierInterval[i-1].endFactor
& currentFactor <= _modifierInterval[i].endFactor) {
if (i - 1 == 0) {
start = initialValue;
} else {
start = _modifierInterval[i-2].targetedValue;
}
end = _modifierInterval[i-1].targetedValue;
return interpolatePoint(start, end, 1);
}
// Else if this is the last VROModifierInterval, and the currentFactor has progressed
// beyond it, attempt to use the ending value of the last known VROModifierInterval.
if (i == _modifierInterval.size() - 1 && currentFactor > _modifierInterval[i].endFactor) {
if (i != 0) {
start = _modifierInterval[i-1].targetedValue;
} else {
start = _modifierInterval[i].targetedValue;
}
end = _modifierInterval[i].targetedValue;
return interpolatePoint(start, end, 1);
}
}
// If no last known windows were yet found, we have yet to encounter our first
// VROModifierInterval, thus return initialValue.
return initialValue;
}
VROVector3f interpolatePoint(VROVector3f &startValue, VROVector3f &endValue, float ratio) {
VROVector3f final;
if (ratio >= 1 ) {
final = endValue;
} else {
final = startValue.interpolate(endValue, ratio);
}
return final;
}
};
#endif /* VROParticleModifier_h */

View File

@@ -0,0 +1,91 @@
//
// VROParticleUBO.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROParticleUBO_h
#define VROParticleUBO_h
#include "VROInstancedUBO.h"
static const int kMaxParticlesPerUBO = 180;
static const int kMaxFloatsPerTransform = 16;
static const int kMaxFloatsPerColor = 4;
/*
Uniform buffer object structure format through which particle transform data are batched
into the Vertex shader. Data is grouped in 4N slots, matching layout specified
in particle_vsh.glsl.
*/
typedef struct {
float particles_transform[kMaxParticlesPerUBO * kMaxFloatsPerTransform];
} VROParticlesUBOVertexData;
/*
Uniform buffer object structure format through which particle "appearance" data are
batched into the Fragment shader. Data is grouped in 4N slots, matching layout specified
in particle_fsh.glsl.
*/
typedef struct {
float frag_particles_color[kMaxParticlesPerUBO * kMaxFloatsPerColor];
} VROParticlesUBOFragmentData;
class VROParticle;
/*
VROParticleUBO handles the binding and batching of particle information into the vertex
and fragment shaders for instance rendering. Note that any instance of a given VROParticleUBO
will always bind data to the same uniform buffers (Binding Point and Buffer ID).
*/
class VROParticleUBO : public VROInstancedUBO {
public:
VROParticleUBO(std::shared_ptr<VRODriver> driver);
virtual ~VROParticleUBO();
void bind();
std::vector<std::shared_ptr<VROShaderModifier>> createInstanceShaderModifier();
/*
Returns number of glDraw(s) required to instance draw all the particles represented
by this VROParticleUBO.
*/
int getNumberOfDrawCalls();
/*
Binds all VROParticlesUBOVertexData and VROParticlesUBOFragmentData to its corresponding
vertex and fragment uniform buffers so that they can be referred to and processed
by shader modifiers crated with createInstanceShaderModifier().
*/
int bindDrawData(int currentDrawCallIndex);
/*
Update the data in this UBO with the latest list of instanced particle data
like transformation matrix / color.
*/
void update(std::vector<VROParticle> &particles, VROBoundingBox &box);
/*
Returns a bounding box that encapsulates all _lastKnownParticles.
*/
VROBoundingBox getInstancedBoundingBox();
private:
/*
Buffer IDs representing the Uniform Buffer objects that were generated for this
UBO.
*/
GLuint _particleVertexUBO;
GLuint _particleFragmentUBO;
/*
The driver that created this UBO.
*/
std::weak_ptr<VRODriver> _driver;
std::vector<VROParticle> _lastKnownParticles;
VROBoundingBox _lastKnownBoundingBox;
};
#endif /* VROParticleUBO_h */

View File

@@ -0,0 +1,52 @@
//
// VROPencil.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROPencil_h
#define VROPencil_h
#include <memory>
#include <vector>
#include "VROSortKey.h"
class VRONode;
class VRORenderContext;
class VRODriver;
class VROVector3f;
class VROVector4f;
class VROMaterial;
/*
Stored in VRORenderContext, VROPencil is used to draw a list of VROPolylines
in a separate render pass, after having rendered the scene, mainly for drawing
debug information.
*/
class VROPencil {
public:
VROPencil(){}
virtual ~VROPencil();
/*
Adds a line to be drawn starting and ending at the provided world coordinates.
*/
void draw(VROVector3f from, VROVector3f to);
/*
Renders the geometry of all lines added with VROPencil.draw(), called in VRORenderer.renderEye(),
after the scene and reticle has been rendered.
*/
void render(const VRORenderContext &context, std::shared_ptr<VRODriver> &driver);
/*
Clears all added lines in preparation for the next render pass.
*/
void clear();
private:
std::vector<std::vector<VROVector3f>> _paths;
};
#endif

View File

@@ -0,0 +1,260 @@
//
// VROPhysicsBody.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROPhysicsBody_h
#define VROPhysicsBody_h
#include <atomic>
#include "VROVector3f.h"
#include "VROPhysicsShape.h"
#include "VROLog.h"
#include "VROStringUtil.h"
class VRONode;
class btTransform;
class btMotionState;
class btRigidBody;
class btVector3;
class VROPhysicsBodyDelegate;
//Atomic counter used to grab a unique Id to represent a VROPhysicsBody.
static std::atomic_int sPhysicsBodyIdCounter;
/*
VROPhysicsBody contains all the physics properties and forces that are associated with and/or
applied to a given node. After construction, it is given to and processed within a simulated
VROPhysicsWorld.
*/
class VROPhysicsBody : public std::enable_shared_from_this<VROPhysicsBody> {
public:
enum class VROPhysicsBodyType {
/*
Static bodies are stationary, has 0 mass, and will not move.
It can only collide with dynamic bodies.
*/
Static = 0,
/*
Kinematic bodies can be moved via animations, and has 0 mass.
It can only collide with dynamic bodies (but cannot be influenced by them).
*/
Kinematic = 1,
/*
Dynamic bodies are designed to be moved only under a physics simulation,
and has positive mass. It collides with all VROPhysicsBody types.
*/
Dynamic = 2
};
static const std::string kDynamicTag;
static const std::string kKinematicTag;
static const std::string kStaticTag;
/*
Returns true if the given string and mass represents a valid representation of
VROPhysicsBodyType. Else, false is returned and the errorMsg is populated
with the reason for failure.
*/
static bool isValidType(std::string strType, float mass, std::string &errorMsg) {
if (!VROStringUtil::strcmpinsensitive(strType, kKinematicTag)
&& !VROStringUtil::strcmpinsensitive(strType, kDynamicTag)
&& !VROStringUtil::strcmpinsensitive(strType, kStaticTag)) {
errorMsg = "Provided invalid physicsBody of type: " + strType;
return false;
} else if ((VROStringUtil::strcmpinsensitive(strType, kKinematicTag) || VROStringUtil::strcmpinsensitive(strType, kStaticTag)) && mass != 0) {
errorMsg = "Mass must be 0 for kinematic or static bodies.";
return false;
} else if (VROStringUtil::strcmpinsensitive(strType, kDynamicTag) && mass <= 0) {
errorMsg = "Mass must be > 0 for dynamic bodies.";
return false;
}
return true;
}
/*
Returns a VROPhysicsBodyType for a given string.
*/
static VROPhysicsBody::VROPhysicsBodyType getBodyTypeForString(std::string strType) {
if (VROStringUtil::strcmpinsensitive(strType, kKinematicTag)) {
return VROPhysicsBody::VROPhysicsBodyType::Kinematic;
} else if (VROStringUtil::strcmpinsensitive(strType, kDynamicTag)) {
return VROPhysicsBody::VROPhysicsBodyType::Dynamic;
}
return VROPhysicsBody::VROPhysicsBodyType::Static;
}
VROPhysicsBody(std::shared_ptr<VRONode> node, VROPhysicsBody::VROPhysicsBodyType type,
float mass, std::shared_ptr<VROPhysicsShape> shape);
virtual ~VROPhysicsBody();
/*
Unique key identifier that the VROPhysicsWorld uses to track this VROPhysicsBody.
*/
std::string getKey();
/*
Returns a non-unique tag identifier stored in VRONode for referring to this VROPhysicsbody.
*/
std::string getTag();
/*
Setters and getters for physics properties associated with this VROPhysicsBody.
*/
void setMass(float mass);
void setInertia(VROVector3f inertia);
void setIsSimulated(bool enabled);
bool getIsSimulated();
void setRestitution(float restitution);
void setUseGravity(bool useGravity);
bool getUseGravity();
void setFriction(float friction);
void setType(VROPhysicsBodyType type, float mass);
/*
Sets this physics body in a kinematic drag mode, where we momentarily treat the body as
a draggable kinematic object.
*/
void setKinematicDrag(bool isDragging);
/*
Sets the given VROPhysicsShape that will be used to process collisions.
*/
void setPhysicsShape(std::shared_ptr<VROPhysicsShape> shape);
/*
Schedules an update that re-invalidates the properties of this
physics body on the next compute physics step.
*/
void refreshBody();
/*
Functions for applying forces on this VROPhysicsBody.
*/
void applyForce(VROVector3f power, VROVector3f position);
void applyImpulse(VROVector3f impulse, VROVector3f position);
/*
Functions for applying torque on this VROPhysicsBody.
*/
void applyTorque(VROVector3f torque);
void applyTorqueImpulse(VROVector3f impulse);
void clearForces();
/*
Sets a velocity on this VROPhysicsBody to be applied when VROPhysicsWorld calls
applyPresetVelocity on this physics body.
*/
void setVelocity(VROVector3f velocity, bool isConstant);
/*
Returns the underlying bullet rigid body that represents this VROPhysicsBody.
*/
btRigidBody* getBulletRigidBody();
/*
Called to synchronize the world transform of the node associated with this VROPhysicsBody
on to the underlying bullet physics body's transform.
*/
void getWorldTransform(btTransform& centerOfMassWorldTrans ) const;
/*
Called to synchronize the world transform of the underlying bullet physics body, on to the
node's transform associated with this VROPhysicsBody.
*/
void setWorldTransform(const btTransform& centerOfMassWorldTrans);
/*
Updates the underlying Bullet physics body with the latest properties of VROPhysicsBody.
*/
void updateBulletRigidBody();
/*
Flag to notify the physics world if the VROPhysicsBody has been modified (where it can then
decide to perform updates if needed).
*/
bool needsBulletUpdate();
/*
Updates the forces applied on the underlying bullet physics body. This is called and re-applied
in each simulated physics step, as required by bullet.
*/
void updateBulletForces();
/*
Applies the set velocity on this VROPhysicsBody at every physics step if isConstant was true,
simulating constant velocity. Else, an instantaneous velocity is applied only once.
*/
void applyPresetVelocity();
/*
Delegates attached to this VROPhysicsBody to be notified of collision events.
*/
void setPhysicsDelegate(std::shared_ptr<VROPhysicsBodyDelegate> delegate);
std::shared_ptr<VROPhysicsBodyDelegate> getPhysicsDelegate();
/*
Collision struct encapsulating all collision properties representing
a collided event.
*/
struct VROCollision {
VROCollision(): penetrationDistance(1) { }
VROVector3f collidedPoint;
VROVector3f collidedNormal;
std::string collidedBodyTag;
/*
Penetration depth given by bullet will be some negative number
if they are colliding. VROCollision defaults penetrationDistance
to a positive number (1) to ensure that it is set / re-evaulated
in a computeCollision pass.
*/
float penetrationDistance;
};
private:
std::string _key;
std::weak_ptr<VRONode> _w_node;
bool _needsBulletUpdate;
btRigidBody* _rigidBody;
// Physics Properties
std::shared_ptr<VROPhysicsShape> _shape;
VROPhysicsBody::VROPhysicsBodyType _type;
bool _enableSimulation;
float _mass;
VROVector3f _inertia;
bool _useGravity;
std::weak_ptr<VROPhysicsBodyDelegate> _w_physicsDelegate;
VROVector3f _constantVelocity;
VROVector3f _instantVelocity;
/*
* Preserved physics properties when in kinematic drag mode.
*/
float _preservedDraggedMass;
VROPhysicsBodyType _preservedType;
/*
Simple force struct containing a force vector
and the location that it is applied at.
*/
struct BulletForce {
VROVector3f force;
VROVector3f location;
};
std::vector<BulletForce> _forces;
std::vector<VROVector3f> _torques;
/*
Creates / destroys the underlying bullet object representing this VROPhysicsBody.
*/
void createBulletBody();
void releaseBulletBody();
};
#endif

View File

@@ -0,0 +1,62 @@
//
// VROPhysicsBodyDelegate.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROPhysicsBodyDelegate_h
#define VROPhysicsBodyDelegate_h
#include "VROPhysicsBody.h"
#include "VROTime.h"
/*
VROPhysicsBodyDelegate contains all callbacks delegate events pertaining to
the VROPhysicsBody that it is attached to (like collisions).
*/
class VROPhysicsBodyDelegate {
/*
LastKnownCollidedObjects is used to filter out similar collision results
so that delegates are only notify with collided-enter events.
*/
std::map<std::string, VROPhysicsBody::VROCollision> _lastKnownCollidedObjects;
std::map<std::string, VROPhysicsBody::VROCollision> _currentCollidedObjects;
double _lastSampledTime = 0;
public:
VROPhysicsBodyDelegate(){}
virtual ~VROPhysicsBodyDelegate() {}
virtual void onCollided(std::string bodyBKey, VROPhysicsBody::VROCollision collision) = 0;
/*
Called by VROPhysicsWorld when an object has collided within the computeCollisions() pass.
Bullet however only provides continuous contact collision checks. Instead, we only want to
notify our delegates about collision-entered events with onCollided(). Thus, here we
iterate through all known latestCollidedObjects and compare it with the objects we have
last seen in _lastKnownCollidedObjects, and then only notify the delegates regarding
new collisions.
*/
void onEngineCollisionUpdate(std::string currentObject, const std::map<std::string, VROPhysicsBody::VROCollision> &latestCollidedObjects) {
_currentCollidedObjects.insert(latestCollidedObjects.begin(), latestCollidedObjects.end());
// Sample at a rate of every 10 frames
double collidedTime = VROTimeCurrentMillis();
if (_lastSampledTime + 160 > collidedTime) {
return;
}
_lastSampledTime = collidedTime;
for (auto &it: _currentCollidedObjects) {
if (_lastKnownCollidedObjects.find(it.first) == _lastKnownCollidedObjects.end()) {
onCollided(it.first, it.second);
}
}
_lastKnownCollidedObjects = _currentCollidedObjects;
_currentCollidedObjects.clear();
}
};
#endif /* VROPhysicsBodyDelegate_h */

View File

@@ -0,0 +1,42 @@
//
// VROPhysicsBodyDelegateiOS.h
// ViroRenderer
//
// Copyright © 201Z Viro Media. All rights reserved.
//
#ifndef VROPhysicsBodyDelegateiOS_h
#define VROPhysicsBodyDelegateiOS_h
#import <Foundation/Foundation.h>
#import "VROPhysicsBodyDelegate.h"
/**
* Protocol to be implemented by objective C controls to be
* set on VROPhysicsBodyDelegateiOS for the notification of
* physics events.
*/
@protocol VROPhysicsBodyDelegateProtocol<NSObject>
@required
- (void)onCollided:(std::string) bodyTagB
collision:(VROPhysicsBody::VROCollision) collision;
@end
/**
* iOS implementation of VROPhysicsBodyDelegate for the notification
* of delegate events across the bridge.
*/
class VROPhysicsBodyDelegateiOS : public VROPhysicsBodyDelegate {
public:
VROPhysicsBodyDelegateiOS(id<VROPhysicsBodyDelegateProtocol> delegate) :
_delegate(delegate) {}
virtual ~VROPhysicsBodyDelegateiOS() {}
virtual void onCollided(std::string bodyBKey, VROPhysicsBody::VROCollision collision) {
[_delegate onCollided:bodyBKey collision:collision];
}
private:
__weak id<VROPhysicsBodyDelegateProtocol> _delegate;
};
#endif /* VROEventDelegateiOS_h */

View File

@@ -0,0 +1,65 @@
//
// VROPhysicsContactResultCallback.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROPhysicsMotionState_h
#define VROPhysicsMotionState_h
#include <btBulletDynamicsCommon.h>
#include "VROPhysicsBody.h"
/*
VROPhysicsContactResultCallback is used by Bullet to return a list of collision hit results that are
detected from a findCollisionsWithShape call.
*/
struct VROPhysicsContactResultCallback : public btCollisionWorld::ContactResultCallback {
std::vector<VROPhysicsBody::VROCollision> _collisions;
VROPhysicsContactResultCallback() {}
~VROPhysicsContactResultCallback() {_collisions.clear();}
btScalar addSingleResult(btManifoldPoint& bulletPoint,
const btCollisionObjectWrapper* colObj0Wrap,
int partId0,
int index0,
const btCollisionObjectWrapper* colObj1Wrap,
int partId1,
int index1) {
// Only process points that have collided
if (bulletPoint.getDistance() > 0.f) {
return 1.f;
}
// Sanity check ensuring Bullet / VROPhysics bodies are properly constructed
const btCollisionObject* obB = colObj1Wrap->m_collisionObject;
if (obB->getUserPointer() == nullptr) {
perror("Incorrectly constructed bullet rigid body for a VROPhysics body!");
return 1.f;
}
// Grab bullet's phsyics properties from the collided body
const btVector3& ptB = bulletPoint.getPositionWorldOnB();
VROVector3f collisionOnBodyB = VROVector3f(ptB.x(), ptB.y(), ptB.z());
VROPhysicsBody *vroPhysicsBodyB = ((VROPhysicsBody *) obB->getUserPointer());
std::string bodyKeyB = vroPhysicsBodyB->getKey();
std::string bodyTagB = vroPhysicsBodyB->getTag();
VROVector3f collidedNormal = VROVector3f(bulletPoint.m_normalWorldOnB.x(),
bulletPoint.m_normalWorldOnB.y(),
bulletPoint.m_normalWorldOnB.z());
// Create and save a vector of all VROCollisions
VROPhysicsBody::VROCollision collision;
collision.collidedBodyTag = bodyKeyB;
collision.collidedPoint = collisionOnBodyB;
collision.collidedNormal = collidedNormal;
_collisions.push_back(collision);
// Return a 1.f hit fraction to prevent bullet from extending the hit distance.
return 1.f;
}
};
#endif

View File

@@ -0,0 +1,55 @@
//
// VROPhysicsMotionState.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROPhysicsMotionState_h
#define VROPhysicsMotionState_h
#include <btBulletDynamicsCommon.h>
/*
VROPhysicsMotionState, when attached to a Bullet body, notifies or grabs
transformation updates to/from a weakly referenced VROPhysicsBody.
*/
class VROPhysicsMotionState : public btMotionState {
public:
std::weak_ptr<VROPhysicsBody> _w_physicsBody;
VROPhysicsMotionState(std::shared_ptr<VROPhysicsBody> body, btTransform transformOffset) {
_w_physicsBody = body;
_physicsTransformOffset = transformOffset;
}
virtual ~VROPhysicsMotionState(){}
void getWorldTransform(btTransform& centerOfMassWorldTrans) const {
std::shared_ptr<VROPhysicsBody> body = _w_physicsBody.lock();
if (!body) {
return;
}
body->getWorldTransform(centerOfMassWorldTrans);
}
void setWorldTransform(const btTransform& centerOfMassWorldTrans) {
std::shared_ptr<VROPhysicsBody> body = _w_physicsBody.lock();
if (!body) {
return;
}
body->setWorldTransform(centerOfMassWorldTrans);
}
btTransform getPhysicsTransformOffset(){
return _physicsTransformOffset;
}
private:
/*
The offset from Viro's geometric transform to Bullet's physicsBody transform (center of mass).
*/
btTransform _physicsTransformOffset;
};
#endif

View File

@@ -0,0 +1,124 @@
//
// VROPhysicsShape.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROPhysicsShape_h
#define VROPhysicsShape_h
#include "VROLog.h"
#include <memory>
#include <stack>
#include <vector>
#include <string>
#include <algorithm>
#include "VROStringUtil.h"
class VRONode;
class btCollisionShape;
class btCompoundShape;
/*
VROPhysicsShape describes the type and dimensions of a physics shape that represents a VROPhysicsBody.
*/
class VROPhysicsShape {
public:
/*
VROShapeType describes the type of shape representing this object.
Required parameters for each shape type are as shown below:
*/
enum VROShapeType {
Auto = 0, // Automatically infer a shape from attached geometry.
AutoCompound = 1, // Automatically infer a compound shape from attached geometry.
Sphere = 2, // _params[0] represents the radius of the sphere
Box = 3 // _params[0],[1],[2] represents the X,Y,Z half span of the Box
};
static const std::string kSphereTag;
static const std::string kBoxTag;
static const std::string kAutoCompoundTag;
/*
Returns true of the given string and mass represents a valid representation of
VROPhysicsBodyType. Else, false is returned and the errorMsg is populated
with the reason for failure.
*/
static bool isValidShape(std::string strType, std::vector<float> params, std::string &errorMsg) {
if (!VROStringUtil::strcmpinsensitive(strType, kSphereTag)
&& !VROStringUtil::strcmpinsensitive(strType, kBoxTag)
&& !VROStringUtil::strcmpinsensitive(strType,kAutoCompoundTag)) {
errorMsg = "Provided invalid shape of type: " + strType;
return false;
} else if (VROStringUtil::strcmpinsensitive(strType, kSphereTag) && params.size() != 1) {
errorMsg = "Invalid params provided for type sphere! Expected 1 parameter for radius.";
return false;
} else if (VROStringUtil::strcmpinsensitive(strType, kBoxTag) && params.size() != 3) {
errorMsg = "Invalid params provided for type box! Expected 3 parameter defining [x,y,z].";
return false;
}
return true;
}
static VROPhysicsShape::VROShapeType getTypeForString(std::string strType) {
if (VROStringUtil::strcmpinsensitive(strType, kSphereTag)) {
return VROPhysicsShape::VROShapeType::Sphere;
} else if (VROStringUtil::strcmpinsensitive(strType, kAutoCompoundTag)) {
return VROPhysicsShape::VROShapeType::AutoCompound;
}
return VROPhysicsShape::VROShapeType::Box;
}
VROPhysicsShape(VROShapeType type, std::vector<float> params = std::vector<float>());
VROPhysicsShape(std::shared_ptr<VRONode> node, bool hasCompoundShapes = false);
virtual ~VROPhysicsShape();
/*
Returns the Bullet representation of a VROPhysicsShape.
*/
btCollisionShape* getBulletShape();
/*
Returns true if this VROShape was generated from the geometry of the
node it is attached to.
*/
bool getIsGeneratedFromGeometry();
/*
Returns true if this VROShape was generated from a combination of several
geometric shapes (compound shape).
*/
bool getIsCompoundShape();
private:
/*
Parameters that describe the dimensions of a shape.
See VROShapeType for what parameters should be defined for which shape type.
*/
VROShapeType _type;
btCollisionShape* _bulletShape;
/*
Creates an underlying bullet collision shape representing this VROPhysicsShape,
given the target shape type and associated params.
*/
btCollisionShape *generateBasicBulletShape(VROShapeType type, std::vector<float> params);
/*
Infers from the geometry associated with the given node to create an underlying
bullet collision shape representing this VROPhysicsShape.
*/
btCollisionShape *generateBasicBulletShape(std::shared_ptr<VRONode> node);
/*
Recursively examines each node within the given root node's subtree and automatically infer
the corresponding bullet collision shape of each node. These shapes are then combined and
returned as a compound bullet shape.
*/
void generateCompoundBulletShape(btCompoundShape &compoundShape,
const std::shared_ptr<VRONode> &rootNode,
const std::shared_ptr<VRONode> &childNode);
};
#endif

View File

@@ -0,0 +1,141 @@
//
// VROPhysicsWorld.h
// ViroRenderer
//
// Copyright © 2017 Viro Media. All rights reserved.
//
#ifndef VROPhysicsWorld_h
#define VROPhysicsWorld_h
#include <memory>
#include "VROPhysicsBody.h"
class btBulletDynamicsCommon;
class btDiscreteDynamicsWorld;
class btBroadphaseInterface;
class btDefaultCollisionConfiguration;
class btCollisionDispatcher;
class btSequentialImpulseConstraintSolver;
class VROPhysicsDebugDraw;
class VRODriver;
class VRORenderContext;
/*
VROPhysicsWorld is a simulated physics environment that contains and processes
all acting forces and collisions on VROPhysicsBodies. It also contains both
the physics properties of the simulated world (like gravity) and collision
configuration parameters.
*/
class VROPhysicsWorld{
public:
VROPhysicsWorld();
virtual ~VROPhysicsWorld();
/*
Adds and removes a physics rigid body from the physics world.
Also guards against adding or removing the same physics
body from the world twice.
*/
void addPhysicsBody(std::shared_ptr<VROPhysicsBody> body);
void removePhysicsBody(std::shared_ptr<VROPhysicsBody> body);
/*
When called, performs a timeStep of simulation / calculations for this physics world.
*/
void computePhysics(const VRORenderContext &context);
/*
Iterate through the dynamic world, identify collided object pairs and notify their corresponding
physicsBodyDelegates regarding the collision event.
*/
void computeCollisions();
/*
Sets the x,y,z gravity on this physics world.
*/
void setGravity(VROVector3f gravity);
/*
Projects a ray into the scene from the given start to end location and returns
true if it has collided with any VROPhysics shape. If a collision occurred,
the collided body's physics delegate will be notified as well.
*/
bool findCollisionsWithRay(VROVector3f from, VROVector3f to, bool returnClosest,
std::string rayTag);
/*
Projects a shape into the scene from the given start to end location and returns
true if it has collided with any VROPhysics shape. If a collision occurred,
the collided body's physics delegate will be notified as well.
Note: If checking along a path, only the first collided object is notified. Else,
if checking at a point (where start and end VROVector3fs are the same), all collided
objects intersecting the shape are notified. This is currently a Bullet limitation.
*/
bool findCollisionsWithShape(VROVector3f fromPos, VROVector3f toPos,
std::shared_ptr<VROPhysicsShape> shape,
std::string rayTag);
/*
If true, renders a set of lines representing the collision mesh of all physicsBodies
within this world.
*/
void setDebugDrawVisible(bool isVisible);
private:
/*
Represents the physicsBodies that have been added to and processed by this physics world.
*/
std::map<std::string, std::shared_ptr<VROPhysicsBody>> _activePhysicsBodies;
/*
Bullet's representation of the physics world.
*/
btDiscreteDynamicsWorld* _dynamicsWorld;
/*
Bullet Broadphase represents the collision algorithm used for quick, rough computations
of collision pairs early on in the physics pipeline.
*/
btBroadphaseInterface* _broadphase;
/*
Configuration used for fine tuning collision algorithms.
*/
btDefaultCollisionConfiguration* _collisionConfiguration;
/*
Dispatcher is used for the notification of collisions.
*/
btCollisionDispatcher* _collisionDispatcher;
/*
Represents the constraints upon which the objects in this world will be resolved against.
This takes into account things like gravity, collisions, and hinges.
*/
btSequentialImpulseConstraintSolver* _constraintSolver;
/*
Performs a collision shape test at the given location, returns true if it has collided
with any VROPhysics shape, and notifies delegates along the way.
*/
bool collisionTestAtPoint(VROVector3f pos, std::shared_ptr<VROPhysicsShape> shape,
std::string rayTag);
/*
Projects a shape into the scene from the given start to end location, returns
true if it has collided with any VROPhysics shape. Only the closest VROPhysicsShape's
delegate is notified.
*/
bool collisionTestAlongPath(VROVector3f fromPos, VROVector3f toPos,
std::shared_ptr<VROPhysicsShape> shape,
std::string rayTag);
/*
Used by Bullet to render all debug elements within the physics world.
*/
VROPhysicsDebugDraw* _debugDraw;
bool _debugDrawVisible;
};
#endif

View File

@@ -0,0 +1,59 @@
//
// VROPlane.h
// ViroRenderer
//
// Created by Raj Advani on 10/15/15.
// Copyright © 2015 Viro Media. All rights reserved.
//
#ifndef VROPLANE_H_
#define VROPLANE_H_
#include "VROVector3f.h"
#include "VROQuaternion.h"
enum class VROPlaneHalfSpace {
OnPlane,
Negative,
Positive
};
class VROPlane {
public:
/*
The normal of the plane (defines a,b,c in the plane equation).
*/
VROVector3f normal;
/*
The distance of the plane from the origin in the direction of its normal.
*/
float d;
VROPlane();
VROPlane(VROVector3f normal, float d);
VROPlane(VROVector3f normal, VROVector3f point);
virtual ~VROPlane();
VROVector3f projectNormalizedVector(VROVector3f vector);
float distanceToPoint(VROVector3f point) const;
float distanceToPointXY(VROVector3f point) const;
VROPlaneHalfSpace getHalfSpaceOfPoint(VROVector3f point) const;
float getA() const { return normal.x; }
float getB() const { return normal.y; }
float getC() const { return normal.z; }
float getD() const { return d; }
void setA(float a) { normal.x = a; }
void setB(float b) { normal.y = b; }
void setC(float c) { normal.z = c; }
void setD(float d) { this->d = d; }
void normalize();
};
#endif /* VROPLANE_H_ */

Some files were not shown because too many files have changed in this diff Show More