Хотя ответ mnuages дает подходящий ответ на заголовок (на самом деле «скрытие» частей геометрии), я понял, что этого будет недостаточно, потому что я хотел бы программно сериализовать оставшуюся геометрию как узел в сцене.
Чтобы ответить на мой «Вопрос 2», я написал дополнения к классам SceneKit, которые позволили бы мне генерировать новые объекты SCNGeometry с диапазонами примитивов из исходных объектов. Это может быть довольно наивно по отношению к материалам (мои модели используют простые цвета, этот код может еще неправильно обрабатывать другие текстуры); и это может не работать для примитивов, отличных от треугольных полос.
Код доступен на GitHub по адресу https://github.com/Fyrestead/PartialGeometry.
Для полноты изначальная версия вставлена ниже.
Добавление SCNGeometry:
//
// 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
}
}
Добавление SCNGeometryElement:
//
// 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
}
}
person
Shon
schedule
02.12.2014