SceneKit – 在 3D 对象上绘图
SceneKit – Drawing on 3D Object
我创建了示例应用程序来绘制 3d 对象,输出绘图不流畅(如图)。我花了将近一天的时间来弄清楚仍然无法解决的问题是什么。可能是什么问题?
我正在创建如下所示的自定义绘图几何图形
//I am creating self.drawingNode touches begin and adding to the rootnode
//points are nothing but 2d points from touches
func createGeometryForPoints(points:[CGPoint]) -> SCNGeometry {
var all_3d_points:[SCNVector3] = []
for point in points {
let result = self.get3dPoint(point)
if result.1 == true {
all_3d_points.append(result.0)
} else {
print("INVALID POINT")
}
}
var indices: [Int32] = []
var index:Int32 = 0
var previousIndex:Int32 = -1
for _ in all_3d_points {
if(previousIndex != -1) {
indices.append(previousIndex)
}
indices.append(index)
index = index + 1
previousIndex = index
}
if indices.count > 0 {
indices.removeLast();
}
let indexData = NSData(bytes: indices, length: sizeof(Int32) * indices.count)
let source = SCNGeometrySource.init(vertices: all_3d_points, count: all_3d_points.count)
let element = SCNGeometryElement.init(data: indexData, primitiveType: .Line, primitiveCount: indices.count/2, bytesPerIndex: sizeof(Int32))
let line = SCNGeometry(sources: [source], elements: [element])
line.materials.first?.diffuse.contents = UIColor.redColor()
line.materials.first?.doubleSided = true
return line
}
func get3dPoint(point:CGPoint) -> (SCNVector3,Bool) {
var canAdd = false
let scnView = self.view as! SCNView
var unprojectedStartPoint = SCNVector3.init(x:Float(point.x), y:Float(point.y), z:0)
let hitResults = scnView.hitTest(point, options: nil)
if hitResults.count > 0 {
let result: AnyObject! = hitResults[0]
if hitResults.count > 1 {
print("SOME PROBLEM")
}
unprojectedStartPoint = result.localCoordinates
unprojectedStartPoint = result.node.convertPosition(unprojectedStartPoint, toNode: self.drawingNode!)
canAdd = true
}
return (unprojectedStartPoint,canAdd)
}
编辑
我正在考虑沿着相机方向或法线找到偏移量,因为我是 scenekit 的新手,我不知道如何将这个偏移量添加到绘图节点,在这个方向上寻求帮助
func createMarkup() -> Void {
let drawingNode = SCNNode()
drawingNode.renderingOrder = 1000
self.parentNode!.addChildNode(drawingNode)
let geometry = self.createGeometryForPoints(allPoints,node: drawingNode)
drawingNode.geometry = geometry
drawingNode.geometry?.materials.first?.doubleSided = true
}
编辑:2
通过沿命中测试的法线添加较小的偏移量解决了该问题
let offsetToAvoidFlickering: Float = 0.05
unprojectedStartPoint = unprojectedStartPoint + result.localNormal.normalized() * offsetToAvoidFlickering
我怀疑你有深度精度问题;看起来你的部分线被剪掉了,因为它们与球体的部分相交。尝试在禁用深度测试的情况下画线。
SceneKit State of the Union Demo 示例代码显示了类似的效果,您可以在圆环上绘画。它更强大,因为您可以绘制任何东西(不仅是线条,还可以绘制纹理等)并且更更有效率,因为它不依赖于创建新几何体。
我创建了示例应用程序来绘制 3d 对象,输出绘图不流畅(如图)。我花了将近一天的时间来弄清楚仍然无法解决的问题是什么。可能是什么问题?
我正在创建如下所示的自定义绘图几何图形
//I am creating self.drawingNode touches begin and adding to the rootnode
//points are nothing but 2d points from touches
func createGeometryForPoints(points:[CGPoint]) -> SCNGeometry {
var all_3d_points:[SCNVector3] = []
for point in points {
let result = self.get3dPoint(point)
if result.1 == true {
all_3d_points.append(result.0)
} else {
print("INVALID POINT")
}
}
var indices: [Int32] = []
var index:Int32 = 0
var previousIndex:Int32 = -1
for _ in all_3d_points {
if(previousIndex != -1) {
indices.append(previousIndex)
}
indices.append(index)
index = index + 1
previousIndex = index
}
if indices.count > 0 {
indices.removeLast();
}
let indexData = NSData(bytes: indices, length: sizeof(Int32) * indices.count)
let source = SCNGeometrySource.init(vertices: all_3d_points, count: all_3d_points.count)
let element = SCNGeometryElement.init(data: indexData, primitiveType: .Line, primitiveCount: indices.count/2, bytesPerIndex: sizeof(Int32))
let line = SCNGeometry(sources: [source], elements: [element])
line.materials.first?.diffuse.contents = UIColor.redColor()
line.materials.first?.doubleSided = true
return line
}
func get3dPoint(point:CGPoint) -> (SCNVector3,Bool) {
var canAdd = false
let scnView = self.view as! SCNView
var unprojectedStartPoint = SCNVector3.init(x:Float(point.x), y:Float(point.y), z:0)
let hitResults = scnView.hitTest(point, options: nil)
if hitResults.count > 0 {
let result: AnyObject! = hitResults[0]
if hitResults.count > 1 {
print("SOME PROBLEM")
}
unprojectedStartPoint = result.localCoordinates
unprojectedStartPoint = result.node.convertPosition(unprojectedStartPoint, toNode: self.drawingNode!)
canAdd = true
}
return (unprojectedStartPoint,canAdd)
}
编辑
我正在考虑沿着相机方向或法线找到偏移量,因为我是 scenekit 的新手,我不知道如何将这个偏移量添加到绘图节点,在这个方向上寻求帮助
func createMarkup() -> Void { let drawingNode = SCNNode() drawingNode.renderingOrder = 1000 self.parentNode!.addChildNode(drawingNode) let geometry = self.createGeometryForPoints(allPoints,node: drawingNode) drawingNode.geometry = geometry drawingNode.geometry?.materials.first?.doubleSided = true }
编辑:2
通过沿命中测试的法线添加较小的偏移量解决了该问题
let offsetToAvoidFlickering: Float = 0.05
unprojectedStartPoint = unprojectedStartPoint + result.localNormal.normalized() * offsetToAvoidFlickering
我怀疑你有深度精度问题;看起来你的部分线被剪掉了,因为它们与球体的部分相交。尝试在禁用深度测试的情况下画线。
SceneKit State of the Union Demo 示例代码显示了类似的效果,您可以在圆环上绘画。它更强大,因为您可以绘制任何东西(不仅是线条,还可以绘制纹理等)并且更更有效率,因为它不依赖于创建新几何体。