Core Concepts
The following paragraphs describe the core concepts, as well as important classes, of the SDK. Any class name starts with an RR
prefix (e.g. RRAvatar3D
).
Containers
We provide a series of container classes like e.g. RRAvatar
, RRGarment
or RRImage
. These classes usually provide IO functionality for the respective file types and store the associated information in the device’s memory during runtime. For some instances, there are separate loader classes like the RROBJLoader
which returns a RRMesh3D
object.
The RRImage
class represents our container format for handling images. It provides functionality for a seamless conversion to and from instances of the Android Bitmap
class. The conversion happens on demand and is only performed once.
Renderables
Renderables are objects which can be displayed by our rendering engine. The base class RRRenderable
holds an RRTransformation
which defines the location, orientation and scale of the renderable. Renderables make use a parent/child hierarchy which allows you to create a scene graph. It’s important to understand that the transformation of a parent renderable is applied to all its children. To see the renderable, we need to add it to a render view by calling RRGLRenderView.addRenderable()
.
val parentRenderable = RRRenderable.create()!!
val childRenderable = RRRenderable.create()!!
parentRenderable.addChild(childRenderable)
// The child renderable will inherit the translation from its parent renderable
val transformation = parentRenderable.transformation
transformation.translation = RRVector3(0.0f, 5.0f, 0.0f)
parentRenderable.transformation = transformation
Colliders
We need to attach colliders to interact with renderables by e.g. selecting them through a touch gesture. The collider is usually a simplified representation of the renderables visual appearance. This could for example be a box in 3D which contains a complex textured mesh with a high number of triangles. The idea behind this concept is to reduce the algorithmic complexity when checking which object has been touched by the user. The user most likey won’t notice whether the test has been performed with the simplified collider geometry or with the complex geometry used for rendering.
val planeRegion = RectF(0f, 0f, 2f, 2f)
val collider = RRPlaneCollider.createWithRegion(planeRegion)!!
renderable.attachCollider(collider)
To actually select a renderable from the scene, we can intersect the colliders with a ray that corresponds e.g. to the position the user clicked on the render view. The RRGLRenderView
provides functionality to obtain a corresponding ray by providing a position within the coordinate space of the view. This ray can then be used to query the scene for objects along its path. Be aware that the ray will only possibly intersect renderables with attached colliders.
val ray = renderView.rayFromViewPosition(touchPosition)
val intersections = renderView.getIntersections(ray)
Layouts
Layouts are a mechanism that helps you with arranging content in the form of renderables in a meaningful way. On top of that, they can provide logic or user interaction. The RRUserPhotoLayout
or the RROrbitViewerLayout
are two examples. To apply a layout to the render view, do as followed:
val orbitLayout = RROrbitViewerLayout.create()!!
renderView.setLayout(orbitLayout)
If you choose to use a layout for a certain application, it is usually not advisable to interact with the renderables of the respective view directly. The logic of the layout might interfere with your code and thereby produce unwanted effects.