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.
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.
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)!