How to get USD / USDZ model metersPerUnit value in iOS?

241 views Asked by At

I've been trying for a few years to find out how to get the USD / USDZ metersPerUnit value in an iOS / macCatalyst app but so far have not discovered any solution. The issue has become more important as our users utilize more of their own USDZ models to create multi-model 3D and AR scenes in our app.

From Apple's SceneKit documentation I would expect that SCNSceneSource.getProperty(forKey: SCNSceneSourceAssetUnitKey) would provide the value, but I have not found the getProperty API to ever return any value other than nil for any type of model file including: .obj, .scn, .dae, .usdc, .usdz.

According to Pixar's USD spec, the default value for metersPerUnit if unspecified is 0.01 (i.e., centimeters) and some USDZ sources like Sketchfab seem to nearly always set it to 0.01. But Apple's apps like RealityConverter and usdconvert enable the user to set the value directly so we're seeing lots of models with other values.

I'd like to do something like the sample code below, but I cannot get it to work.Since SCNSource seems to use ModelIO I would have thought ModelIO would have an API for this, but I have not discovered it. Is there some API anyone can suggest to get the metersPerUnit value?

            do {
            var options: [SCNSceneSource.LoadingOption : Any] = [
                .animationImportPolicy: SCNSceneSource.AnimationImportPolicy.doNotPlay
                                                            ]
            if let modelSource = SCNSceneSource(url: url)  {
                
                if let units = modelSource.property(forKey: SCNSceneSourceAssetUnitKey) as? [String : Any] {
                    if let metersPerUnit = units[SCNSceneSourceAssetUnitMeterKey] as? Float {
                        options[.convertUnitsToMeters] = NSNumber(value: metersPerUnit)
                    }
                }
                let scene = try modelSource.scene(options: options)

            }
            
        } catch {
            throw NSError(domain: "OurApp", code: 0, userInfo: [NSLocalizedDescriptionKey: "Model \(url.lastPathComponent) cannot be loaded"])
        }
0

There are 0 answers