Pictofit / iOS SDK / 2.6.2 / Shape from Measurements

Shape from Measurements

To edit the body shape of a 3D avatar, you can either use the interactive Avatar Configurator feature or create a 3D body shape based on a small set of input body measurements. Therefore, you just need to provide a general body type to start from and a set of body measurements with a desired target values for each. Our algorithms will then generate a body shape which matches these measurments taking the selected body type into account.

The recommended flow is to first ask the users about their overall body type. This body type is then used as a starting point for the algorithm. When creating the body shape of the avatar, we ask the users only for a small set of measurments. The basic type helps us to resolve ambiguities and to be able to generate more accurate results.

The RRBodyModel3DDefaultShapes class provides an easy-to-use functionality for accessing some pre-defined body types (Ectomorph, Mesomorph, Endomorph). Using different body types (e.g like triangle, rectangle, oval) is also possible if you want to customise this experience. Our team can create RRBodyModel3DShape files for you which can then be used as body type and therefore the starting point for the algorithms.

Example of the Body Shape Pre-Selection

Based on the selected body shape, you can initialize the RRBodyModel3DStateFromMeasurements class. This class returns a set of available target measurements. Each of this measurements needs to be provided with a desired target value. Based on these values, the RRBodyModel3DStateFromMeasurements instance modifies the RRBodyModel3DState instance that was provided in the initializer. The generated body shape will then have the proportions to fit the desired target body measurements.

Example of the UI for editing body measurements

Please see the API reference for more details on the Shape from Measurements feature.

Using the Default Body Shapes Component

The RRBodyModel3DDefaultShapes class provides a simple interface to retrieve a set of default body shapes given a RRBodyModel3D instance. Each body model comes with a set of default shapes as part of the respective file. Alternatively, it is straight forward to load an RRBodyModel3DShape instances from file and thereby use your custom body types.

The following code snippet shows the simpicity of using the RRBodyModel3DDefaultShapes class:

func getDefaultBodyModelState(bodyModel: RRBodyModel3D, shapeType: RRBodyModel3DDefaultShapesConfigShapeType) -> RRBodyModel3DState? {
  let defaultShapes = RRBodyModel3DDefaultShapes(bodyModel: bodyModel)
  guard let bodyShape = defaultShapes?.getDefaultBodyShape(shapeType) else {
    return nil
  }

  let result = RRBodyModel3DState(bodyModel: bodyModel)
  try! result.setBodyModelShape(bodyShape)
  
  return result
}

BodyModel3DState from Measurements

Given a RRBodyModel3DState instance, the RRBodyModel3DStateFromMeasurements can be initialized. This class contains the algorithms which generate the body shape that fits the target input measurements provided by the user. The target measurement values will be initailized with the values of the provided RRBodyModel3DState instance. To generate a new body shape after you have altered the target measurement values, call the applyMeasurementTargets method on the RRBodyModel3DStateFromMeasurements instance. This will alter the RRBodyModel3DState instance which then holds your body shape matching the provided values.

The following code snippet shows how to modify a RRBodyModel3DState instance and how to display it using an RRAvatar3DUserAdjustmentsLayout. This will enable the user to interactively modify the pose and shape further. When modifying the shape there, keep in mind that this is very likely to change the body measurement of your avatar again. This step is optional and only shown for completeness.

func shapeFromMeasurements(editorLayout: RRAvatar3DUserAdjustmentsLayout, targetMeasurements: [Float], initialShape: RRBodyModel3DShape) {
  // get the current body model
  let bodyModel = editorLayout.avatar!.getVisualRepresentationBodyModelState()!.bodyModel
  
  // Create a body model state that is based on the same body model like the avatar already shown inside the editor
  let bodyModelState = RRBodyModel3DState(bodyModel: bodyModel)
  try! bodyModelState.setBodyModelShape(initialShape)
  
  //Create shape from measurements instance:
  let shapeFromMeasurements = RRBodyModel3DStateFromMeasurements(bodyModelState: bodyModelState)!
  
  // Print available measurements and apply target values:
  self.printMeasurementNames(shapeFromMeasurements: shapeFromMeasurements)
  for index in 0...(targetMeasurements.count-1) {
    self.modifyMeasurementValue(shapeFromMeasurements: shapeFromMeasurements, value: targetMeasurements[index], measurementIndex: UInt(index))
  }
  
  // Apply measurements and set the created shape inside the avatar editor
  shapeFromMeasurements.applyMeasurementTargets()
  try! editorLayout.setBodyModelShape(shapeFromMeasurements.bodyModelState.bodyModelShape)
}

func printMeasurementNames(shapeFromMeasurements: RRBodyModel3DStateFromMeasurements) {
  print("Available Measurements")
  for name in shapeFromMeasurements.measurementNames {
    print(name)
  }
}

func modifyMeasurementValue(shapeFromMeasurements: RRBodyModel3DStateFromMeasurements, value: Float, measurementIndex: UInt) {
  do {
    try shapeFromMeasurements.setMeasurementTarget(CGFloat(value), measurementIndex: measurementIndex)
    let measurementName = shapeFromMeasurements.measurementNames[Int(measurementIndex)]
    print("Setting measurement " + measurementName + " to " + String(value))
  } catch {
    print("Error: " + error.localizedDescription)
  }
}

Advanced

The Shape from Measurements component is designed in a highly flexible manner so it is possible to define the set of target measurements and their exact locations on the human body. Thereby, this feature can be customised and adjusted to your indivdual use case.

Using a Set of Custom Input Measurements

When using a custom set of measurements, the only difference compared to the above code samples is to load and use your custom configuration file for initializing the RRBodyModel3DStateFromMeasurements instance. To get a customized configuration file suitable for your individual needs, please contact us. Our team is happy to work with you on this.

The code snippet shows how to use your customized config file by just replacing the single line where the RRBodyModel3DStateFromMeasurements instance is created. configPath is a string instance holding a file path pointing to your customized configuration file.

//Create shape from measurements instance:
let config = RRBodyModel3DStateFromMeasurementsConfig.load(fromConfigFile: configPath)!
let shapeFromMeasurements = RRBodyModel3DStateFromMeasurements(config: config, bodyModelState: bodyModelState)!
© 2014-2020 Reactive Reality AG