虽然 mnuages 的回答为标题提供了合适的答案(实际上是“隐藏”几何的一部分),但我意识到这还不够,因为我想以编程方式将剩余的几何序列化为场景中的节点。
为了回答我的“问题 2”,我在 SceneKit 类中添加了一些内容,这些内容可以让我生成新的 SCNGeometry 对象,其中包含原始对象的基元范围。它在材质方面可能相当幼稚(我的模型使用简单的颜色;此代码可能尚未正确处理其他纹理);它可能不适用于三角形条带以外的图元。
代码可在 GitHub 上https://github.com/Fyrestead/PartialGeometry 获得
为了完整起见,下面贴的是初始版本。
SCNG几何加法:
//
// SCNGeometry.swift
//
// Created by Shon Frazier on 11/22/14.
// Copyright (c) 2014 Fyrestead, LLC. All rights reserved.
//
import Foundation
import SceneKit
let allSemantics = [
SCNGeometrySourceSemanticVertex,
SCNGeometrySourceSemanticNormal,
SCNGeometrySourceSemanticColor,
SCNGeometrySourceSemanticTexcoord,
SCNGeometrySourceSemanticVertexCrease,
SCNGeometrySourceSemanticEdgeCrease,
SCNGeometrySourceSemanticBoneWeights,
SCNGeometrySourceSemanticBoneIndices
]
extension SCNGeometry {
func geometryForRangeOfPrimitives(range: NSRange) -> SCNGeometry? {
var primitiveType: SCNGeometryPrimitiveType
var allElements: [SCNGeometryElement] = [SCNGeometryElement]()
for i in 0..<self.geometryElementCount {
let element = self.geometryElementAtIndex(i)
if element == nil {
continue
}
var newElement = element!.geometryElementForRangeOfPrimitives(range)
if newElement != nil {
allElements += [newElement!]
}
}
var allSources: [SCNGeometrySource] = [SCNGeometrySource]()
for semantic in allSemantics {
var sources = self.geometrySourcesForSemantic(semantic)
if sources == nil {
continue
}
for source in sources! as [SCNGeometrySource] {
var range: NSRange = NSRange(location: 0, length: 5)
let newSource = source.geometrySourceForRangeOfPrimitives(range, primitiveType: SCNGeometryPrimitiveType.TriangleStrip)
allSources += [newSource!]
}
}
var newGeometry = SCNGeometry(sources: allSources, elements: allElements)
newGeometry.materials = materials
return newGeometry
}
}
SCNGeometry 元素添加:
//
// SCNGeometryElement.swift
//
// Created by Shon Frazier on 11/23/14.
// Copyright (c) 2014 Fyrestead, LLC. All rights reserved.
//
import Foundation
import SceneKit
extension SCNGeometryElement {
func geometryElementForRangeOfPrimitives(range: NSRange) -> SCNGeometryElement? {
if data == nil {
return nil
}
let newCount = range.length
let newLocation = range.location * bytesPerIndex
let newLength = range.length * bytesPerIndex
let newRange = NSRange(location: newLocation, length: newLength)
let newData = data!.subdataWithRange(newRange)
let newElement = SCNGeometryElement(
data: newData,
primitiveType: primitiveType,
primitiveCount: newCount,
bytesPerIndex: bytesPerIndex
)
return newElement
}
}
SCNGeometrySource 添加:
//
// SCNGeometrySource.swift
//
// Created by Shon Frazier on 11/23/14.
// Copyright (c) 2014 Fyrestead, LLC. All rights reserved.
//
import Foundation
import SceneKit
extension SCNGeometrySource {
/* Preserves use of existing data buffer by changing only the offset */
func geometrySourceForRangeOfVectors(range: NSRange) -> SCNGeometrySource? {
if data == nil {
return nil
}
let newOffset = dataOffset + range.location * (dataStride + bytesPerComponent * componentsPerVector)
return SCNGeometrySource(
data: data!,
semantic: semantic,
vectorCount: range.length,
floatComponents: floatComponents,
componentsPerVector: componentsPerVector,
bytesPerComponent: bytesPerComponent,
dataOffset: newOffset,
dataStride: dataStride)
}
func geometrySourceForRangeOfPrimitives(range: NSRange, primitiveType: SCNGeometryPrimitiveType) -> SCNGeometrySource? {
var newGSource: SCNGeometrySource?
switch primitiveType {
case .TriangleStrip, .Point:
newGSource = geometrySourceForRangeOfVectors(range)
case .Triangles:
let newRange = NSRange(location: range.location * 3, length: range.length * 3)
newGSource = geometrySourceForRangeOfVectors(newRange)
case .Line:
let newRange = NSRange(location: range.location * 2, length: range.length * 2)
newGSource = geometrySourceForRangeOfVectors(newRange)
}
return newGSource
}
}