Mix & Match in 2D
The mix & match feature allows you to virtually create outfits by combining different garments on an avatar. The garments are fitted to the avatars body in a realistic way creating a rendering of the outfit which is often not distinguishable from a photo.
Avatars and Garments
The main ingredients to this are
.avatar files. Both can be generated from images using the Pictofit Content Service. These files are smart objects which contain a visual representation as well as semantic information about the respective entity. The counterparts in code are the
RRAvatar classes. Loading those objects is very easy as you can see in the following snippet.
// Load avatar from file delivered along with the app's resources: let avatarFilePath = Bundle.main.path(forResource: "name", ofType: "avatar") let avatar = RRAvatar.init(fromFile: avatarFilePath!)
RRAvatar are container classes for storing the information about the respective object in memory. To display such objects, we need to create the corresponding renderable as well.
let garmentRenderable = RRGarmentRenderable.init(garment: garment!)
Using Renderables and Layouts
Now to actually render a virtual try-on of garments on an avatar, we need to first create a try-on layout and then assign it to the render view. The layout defines how the avatar is positioned and displayed on the users device. Every layout that supports this functionality is derived from
RRAbstractTryOnLayout. For this example, we’ll create a
RRUserPhotoLayout which simply displays the avatar screen-filling within the view.
let renderLayout = RRUserPhotoLayout.init()! self.renderView!.layout = renderLayout
Try-on layouts provide a
.avatarRenderable and a
.garmentRenderables property to define the respective renderables to be display. Note that
.garmentRenderables is an array. This means that you can specify multiple garments to combine them into an outfit. The order within the array defines the layering of the garments. You can think of the index as of the order in which you put on the cloths. Our virtual fitting engine correctly computes the effects of the physical interaction between garments (e.g. tucking in a shirt). Now let’s put all of this together to actually render an outfit.
renderLayout.avatarRenderable = avatarRenderable! renderLayout.garmentRenderables = [pantsRenderable!, shirtRenderable!]
Play around with this by for example changing the order of the garment renderables to see the effect. Computing the virtual fit is very fast. This means that you can allow your users to interactively create their outfit within your application. But you can also use this feature to generate on-model images of single garments or outfits for recommendations, campaigns or tailored ads.
RRSlotLayout allows you to arrange avatars, garments and also accessories any way you want. This gives you freedom to create collage-style renderings or to annotate the try-on with visual elements. The
RRSlot base class defines properties which tell the rendering engine how to position the slot and how to scale its content. Different types of slots provide different functionality. The
RRTryOnSlot allows you to place an avatar with virtually fitted garments. The
RRGarmentSlot enables you to display a garment or even an accessory while the
RRQuadSlot simply displays an image.
let tryonSlot = RRTryOnSlot.init() tryonSlot.frame = self.renderView.bounds tryonSlot.avatarRenderable = avatarRenderable tryonSlot.scalingMode = .scaleToHeight let quadSlot = RRQuadSlot.init() let image = UIImage.init(named: "myimage.png") let imageRenderable = RRQuadRenderable.init(image: RRImage.init(image: image!)) quadSlot.quadRenderable = imageRenderable
User Immersion Through Scenes
Scenes allow you to create virtual environments in which users can see themselves and mix & match outfits. These scenes can be stylized or resemble actual events and locations. Scenes can be generated by the Pictofit Content Service. The samples contain a few assets for you to play around. The following sample shows how to load a scene.
// load the scene from the .arscene file self.renderView!.layout = RRSceneLayout() let scenePath = Bundle.main.path(forResource: sceneFileName, ofType: "arscene") let binaryFormatProvider = RRBinarySceneGraphFormat.init() let serializer = RRSceneGraphSerializer.init(formatProvider: binaryFormatProvider!)! try! serializer.deserialize(fromPath: scenePath!, renderView: self.renderView)
To learn more about this feature, check out the following samples: