我有一个弧形机械手,它使用Timer
来创建当前旋转角度的平滑减速衰减。它在我的GL
应用中运行得很好。在Metal
中,它会崩溃该应用。
以下是我实例化计时器的方法:
rotationTimer = Timer.scheduledTimer(
timeInterval: TimeInterval(kRotationRate),
target: self,
selector: Selector(("rotationTimerHandler")),
userInfo: [ "radiansBegin":radians, "radians":radians, "radiansEnd":0, "counter":0 ],
repeats: true)
函数rotationTimerHandler
递减角度 - radians
- 然后从中构建一个转换矩阵,它包含在渲染绘制循环的更新函数中。
我怀疑我需要与Metal
绘制循环的时序进行一些同步,但我认为没办法这样做。如何让Timer
和Metal
一起玩得很好?
Per Warren的问题风暴:-)这里有更多的背景。
我的应用视图是MTKView
,有2个属性。
符合MTKViewDelegate
协议并实现的渲染器:
func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize)
func draw(in view: MTKView)
绘图由MTKView的内部显示链接计时器驱动。一切都在主线程上运行。没有异步调用。
和一个弧形球。将屏幕手势映射到四元数到3D旋转矩阵的对象。 arcball是视图的平移手势处理程序:
addGestureRecognizer(UIPanGestureRecognizer.init(
target: arcBall,
action: #selector(EIArcball.arcBallPanHandler)))
}
当弧形球的平移手势处理程序进入结束状态时,我实例化一个计时器N秒,以便在平移结束时基于角度/旋转轴继续生成四元数/矩阵,以获得令人愉悦的滑动效果。
好的,渲染器(符合MTKViewDelegate
)。绘制循环:
public func draw(in view: MTKView) {
update(view: view as! EIView, drawableSize: view.bounds.size)
// final pass
if let passDescriptor = view.currentRenderPassDescriptor, let drawable = view.currentDrawable {
passDescriptor.colorAttachments[ 0 ].clearColor = MTLClearColorMake(0.5, 0.5, 0.5, 1.0)
let commandBuffer = commandQueue.makeCommandBuffer()
let renderCommandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: passDescriptor)
renderCommandEncoder.setFrontFacing(.counterClockwise)
renderCommandEncoder.setTriangleFillMode(.fill)
renderCommandEncoder.setCullMode(.none)
renderCommandEncoder.setRenderPipelineState(heroModelPipelineState)
renderCommandEncoder.setVertexBuffer(heroModel.vertexMetalBuffer, offset: 0, at: 0)
renderCommandEncoder.setVertexBuffer(heroModel.metallicTransform.metalBuffer, offset: 0, at: 1)
renderCommandEncoder.setFragmentTexture(heroModelTexture, at: 0)
renderCommandEncoder.drawIndexedPrimitives(
type: .triangle,
indexCount: heroModel.vertexIndexMetalBuffer.length / MemoryLayout<UInt16>.size,
indexType: MTLIndexType.uint16,
indexBuffer: heroModel.vertexIndexMetalBuffer,
indexBufferOffset: 0)
renderCommandEncoder.endEncoding()
commandBuffer.present(drawable)
commandBuffer.commit()
}
}
这里没什么特别有趣的。请注意电话:
update(view: view as! EIView, drawableSize: view.bounds.size)
以下是update
func update(view: EIView, drawableSize:CGSize) {
heroModel.metallicTransform.update(camera: camera, transformer: {
return view.arcBall.rotationMatrix * GLKMatrix4MakeScale(150, 150, 1)
})
}
function heroModel.metallicTransform.update(...)
构建我的顶点着色器中使用的模型 - 视图 - 投影矩阵。这是一个玩具应用程序,它将x-y缩放的四边形绘制为150,通过平移手势操纵(旋转)到弧形球。
在update
中,我没有尝试安排使用arcball的变换矩阵进行更新。这似乎是代码味道。
我越想到这一点似乎我应该明确地进行绘制调用,因为我没有必要不断地重绘。 1)平移时只需调用renderer.draw()。 2)平移结束后,从我的Timer处理程序中调用render.draw()。
这是更多的堆栈跟踪。只是一大堆汇编程序:
bt(backtrace)的输出:
我想我会尝试在没有内部计时器的情况下运行Metal
并明确调用MTKView.draw()
。在这样一个简单的应用程序中不需要基于计时器的方法,并且基于NSTimer
的Arcball也存在问题。
答案 0 :(得分:0)
解决。我决定保留使用card_names
内部计时器,并在NSTimer回调中平移和期间在 public function sortupdate(Request $response)
{
$get_result_arr = json_decode($response->getContent());
foreach($get_result_arr as $result){
$lists = $result->lists;
}
}
中明确调用MTKView
。十分简单。工作方式相同。