下采样SceneKit模型纹理图像的最佳方法?

时间:2018-12-31 22:54:22

标签: ios core-graphics scenekit arkit

是否存在减小SceneKit模型纹理图像大小的标准方法?

WWDC 2018 talk about USDZ files说:“ AR Quick Look将在需要时动态地对其他设备的纹理进行下采样。”但是我们直接使用SceneKit而不是通过Quick Look使用,所以我想知道SceneKit或Model I / O中是否存在用于动态下采样纹理图像的选项或技术?

我已经实现了我自己的SCNode扩展,可以在加载模型场景后使用,但是它有点慢,我不确定它是否非常理想:

extension SCNode {

    func downsampleTextures(maxSize: Int = 512) {

    let options = [kCGImageSourceThumbnailMaxPixelSize: maxSize, kCGImageSourceCreateThumbnailWithTransform: true, kCGImageSourceCreateThumbnailFromImageAlways: true, kCGImageSourceCreateThumbnailFromImageIfAbsent: true] as CFDictionary

    // Resize material texture images in the model that are too big.
    self.enumerateHierarchy { (childNode, stop) in
        if let geometry = childNode.geometry {
            for material in geometry.materials {
                for materialProperty in [material.ambientOcclusion, material.diffuse, material.displacement, material.emission, material.metalness, material.multiply, material.roughness, material.normal, material.reflective, material.specular, material.transparent] {
                    autoreleasepool {

                        if let texture = materialProperty.contents as? MDLURLTexture, texture.dimensions.x > maxSize {

                            NSLog("Downsampling URL \(material.name ?? "material") in \(self.name ?? "") from \(texture.dimensions) to (\(maxSize), \(maxSize)), \(texture.url)")
                            if let imageSource = CGImageSourceCreateWithURL(texture.url as CFURL, [kCGImageSourceShouldCache: false] as CFDictionary) {

                                if let cgImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options) {
                                    materialProperty.contents = cgImage
                                }
                            }
                        } else if let texture = materialProperty.contents as? MDLTexture {
                            if texture.dimensions.x > maxSize, let image = texture.imageFromTexture()?.takeUnretainedValue() {
                                NSLog("Downsampling image \(material.name ?? "material") in \(self.name ?? "") from \(texture.dimensions) to (\(maxSize), \(maxSize))")
                                materialProperty.contents = image.resized(toWidth: maxSize, toHeight: maxSize)
                            }
                        } else if let imageData = materialProperty.contents as? Data, let image = UIImage.init(data: imageData)?.cgImage {
                            if image.width > maxSize {
                                NSLog("Downsampling data \(self.name ?? "") from (\(image.width), \(image.height)) to (\(maxSize), \(maxSize))")
                                materialProperty.contents = image.resized(toWidth: maxSize, toHeight: maxSize)
                            }
                        } else if let texturePath = materialProperty.contents as? String {

                            if let url = Bundle.main.url(forResource: texturePath, withExtension: nil) {
                                if let imageSource = CGImageSourceCreateWithURL(url as CFURL, [kCGImageSourceShouldCache: false] as CFDictionary),
                                    let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [NSString: AnyObject] {
                                    if let width = properties[kCGImagePropertyPixelWidth] as? NSNumber, width.intValue > maxSize {
                                        if let cgImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options) {
                                            materialProperty.contents = cgImage
                                            NSLog("Downsampling path \(url.lastPathComponent) in \(self.name ?? "") from \(width) to (\(cgImage.width), \(cgImage.height))")
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

}

0 个答案:

没有答案