- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我是一名数学家,想编写一个几何游戏。
我有一些我需要显示的网格及其单位法线的确切坐标和数学公式。
每个网格我只需要一个纹理(彩色反光 Metal )。
我需要让用户移动棋子,即通过简单的数学公式再次更改网格的坐标。
所以我不需要导入 3D 文件,而是可以计算所有内容。
想象一种魔方。计算立方体坐标,并由用户旋转立方体。我的程序在 Mathematica 中运行。
我正经历一段非常艰难的时期,现在已经失眠了好几天,我试图找到如何在 SceneKit 中准确显示计算的网格 - 每个顶点和法线分别设置动画。
任何工作示例,例如,具有计算坐标(而不是股票提供的形状)的单个三角形,由 SceneKit 以可动画坐标显示,我们将非常感激。
我看多了,似乎网格的个别点在SceneKit中可能是不可移动的。我喜欢 SceneKit(与 OpenGL 不同)的一项功能,即可以在用户的手指下获取对象。可以在项目中混合使用 OpenGL 和 SceneKit 吗?
我可以从那里接手....
最佳答案
通常,单独为顶点位置设置动画是一个棘手的问题。但是在 SceneKit 中有很好的方法来处理它。
GPU 确实希望在开始渲染帧之前将顶点数据全部上传到一个 block 中。这意味着,如果您不断地在 CPU 上计算新的顶点位置/法线/等,您就会遇到每次将数据所有转移到 GPU 的问题,即使只是其中的一部分发生变化。
因为您已经用数学方法描述了表面,所以您可以在 GPU 本身上完成这项工作。如果每个顶点位置都是某个变量的函数,您可以在着色器中编写该函数,并找到一种方法来传递每个顶点的输入变量。
为此,您可以考虑几个选项:
着色器修改器。从具有所需拓扑结构的虚拟几何体开始(顶点数以及它们作为多边形的连接方式)。将您的输入变量作为额外纹理传递,并在您的着色器修改器代码(用于几何入口点)中查找纹理,执行您的函数,并使用结果设置顶点位置。
Metal 计算着色器。创建几何源 backed by a Metal buffer ,然后在渲染时,根据您的函数将顶点数据写入该缓冲区的计算着色器入队。 (链接中有部分框架代码。)
更新:从您的评论来看,您可能处于更轻松的位置。
如果您拥有的是由相对于自身静止但相对于彼此移动的部分组成的几何体——就像魔方的小立方体——在渲染时计算顶点是多余的。相反,您可以将几何体的静态部分一次性上传到 GPU,然后使用变换将它们相对定位。
在 SceneKit 中执行此操作的方法是创建单独的节点,每个节点都有自己的(静态)几何形状,然后设置节点变换(或位置/方向/比例)以相对于彼此移动节点。要一次移动多个节点,请使用节点层次结构——让其中的几个节点成为另一个节点的子节点。如果一些需要同时移动,而不同的子集需要稍后一起移动,您可以更改层次结构。
这是魔方创意的具体示例。首先,创建一些立方体:
// convenience for creating solid color materials
func materialWithColor(color: NSColor) -> SCNMaterial {
let mat = SCNMaterial()
mat.diffuse.contents = color
mat.specular.contents = NSColor.whiteColor()
return mat
}
// create and arrange a 3x3x3 array of cubelets
var cubelets: [SCNNode] = []
for x in -1...1 {
for y in -1...1 {
for z in -1...1 {
let box = SCNBox()
box.chamferRadius = 0.1
box.materials = [
materialWithColor(NSColor.greenColor()),
materialWithColor(NSColor.redColor()),
materialWithColor(NSColor.blueColor()),
materialWithColor(NSColor.orangeColor()),
materialWithColor(NSColor.whiteColor()),
materialWithColor(NSColor.yellowColor()),
]
let node = SCNNode(geometry: box)
node.position = SCNVector3(x: CGFloat(x), y: CGFloat(y), z: CGFloat(z))
scene.rootNode.addChildNode(node)
cubelets += [node]
}
}
}
接下来是做轮换的过程。这是一个特定的旋转,但您可以将其概括为一个函数,该函数对立方体的任何子集进行任何变换:
// create a temporary node for the rotation
let rotateNode = SCNNode()
scene.rootNode.addChildNode(rotateNode)
// grab the set of cubelets whose position is along the right face of the puzzle,
// and add them to the rotation node
let rightCubelets = cubelets.filter { node in
return abs(node.position.x - 1) < 0.001
}
rightCubelets.map { rotateNode.addChildNode($0) }
// animate a rotation
SCNTransaction.begin()
SCNTransaction.setAnimationDuration(2)
rotateNode.eulerAngles.x += CGFloat(M_PI_2)
SCNTransaction.setCompletionBlock {
// after animating, remove the cubelets from the rotation node,
// and re-add them to the parent node with their transforms altered
rotateNode.enumerateChildNodesUsingBlock { cubelet, _ in
cubelet.transform = cubelet.worldTransform
cubelet.removeFromParentNode()
scene.rootNode.addChildNode(cubelet)
}
rotateNode.removeFromParentNode()
}
SCNTransaction.commit()
神奇的部分在于动画之后的清理。立方体从场景根节点的子节点开始,我们暂时将它们重新设置为另一个节点的父节点,以便我们可以一起转换它们。再次将它们返回为根节点的子节点后,我们将每个本地的 transform
设置为它的 worldTransform
,以便它保持临时节点的转换变化的效果。
然后您可以重复此过程以获取一组(新的)世界空间位置中的任何一组节点,并使用另一个临时节点来转换它们。
我不太确定你的问题有多像 Rubik's-cube,但听起来你可能可以从类似的东西中概括出一个解决方案。
关于swift - 使用 SceneKit 快速移动数学网格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31082361/
只是想知道 Jquery Mobile 是否足够稳定以用于实时生产企业移动应用程序。 有很多 HTML5 框架,因为我们的团队使用 JQuery 已经有一段时间了,我们更愿意使用 Jquery 移动框
关闭。这个问题需要details or clarity .它目前不接受答案。 想改进这个问题吗? 通过 editing this post 添加细节并澄清问题. 关闭 3 年前。 Improve t
所以我尝试在 JavaScript 中对元素进行拖放。我使用的视频教程在这里; https://www.youtube.com/watch?v=KTlZ4Hs5h80 。我已经按照它的说明进行了编码,
无法在移动 iOS(safari 和 chrome)上自动播放以前缓存的 mp3 音频 我正在 Angular 8 中开发一个应用程序,在该应用程序的一部分中,我试图在对象数组中缓存几个传入的音频 m
Git 基于内容而不是文件,所以我目前理解以下行为,但我想知道是否有特殊选项或 hack 来检测此类事情: git init mkdir -p foo/bar echo "test" foo/a.tx
我正在寻找语义 ui 正确的类来隐藏例如移动 View 中的 DIV。在 Bootstrap 中,我们有“visible-xs”和“hidden-xs”。 但是在语义ui上我只找到了“仅移动网格” 最
我正在使用 ubuntu 和 想要移动或复制大文件。 但是当我与其他人一起使用服务器时,我不想拥有所有内存并使其他进程几乎停止。 那么有没有办法在内存使用受限的情况下移动或复制文件? 最佳答案 如果你
这些指令有什么区别?以 ARM9 处理器为例,它不应该是: ASM: mov r0, 0 C: r0 = 0; ASM: ld r0, 0 C: r0 = 0; ? 我不知道为什么要使用一个或另一个:
我有一个文件夹,其中包含一些随机命名的文件,其中包含我需要的数据。 为了使用数据,我必须将文件移动到另一个文件夹并将文件命名为“file1.xml” 每次移动和重命名文件时,它都会替换目标文件夹中以前
我经常在 IB/Storyboard 中堆叠对象,几乎不可能拖动其他对象后面的对象而不移动前面的对象。无论如何我可以移动已经选择但位于其他对象后面的对象吗?当我尝试移动它时,它总是选择顶部的对象,还是
几个月前,我看到 Safari 7 允许推送通知,它似乎是一个非常有用的工具,除了我看到的每个示例都专注于桌面浏览,而不是移动设备。 Safari 推送通知是否可以在移动设备上运行,如果没有,是否有计
我有一个简单的 View 模型,其中包含修改后的 ObservableCollection使用 SynchronizationContext.Current.Send在 UI 线程上执行对集合的更改。
关于cassandra创建的数据文件和系统文件的位置,我需要移动在“cassandra.yaml”配置文件中设置的“commitlog_directory”、“data_file_directorie
我有这个代码 $(function() { var message = 'Dont forget us'; var original; var txt1 = ' - '; $(wind
我的客户报告说他的网站有一个奇怪的问题。该网站的 URL 是 your-montenegro.me 在 基于 Android 的浏览器 上加载时,页面底部会出现一个奇怪的空白区域。以下是屏幕截图: 华
我有这个 HTML 标记: Express 300 bsf Sign Up 我需要将元素从 DOM 上的一个
我有一个可重新排序的 TableView (UITableView 实例)。尽管我已经实现了 UITableViewDataSource 方法: tableView:moveRowAtIndexPat
我的客户报告说他的网站有一个奇怪的问题。该网站的 URL 是 your-montenegro.me 在 基于 Android 的浏览器 上加载时,页面底部会出现一个奇怪的空白区域。以下是屏幕截图: 华
我需要在拖放或复制/剪切和粘贴(复制与移动)期间获取操作类型。它是一个 Swing 应用程序,并且实现了 TransferHandle。我在操作结束时需要此信息,在 importData 方法中。 对
我编写了一个具有 add 和 get 方法的 SortedIntList 类。 我调用以下四个方法: SortedIntList mySortedIntList = new SortedIntList
我是一名优秀的程序员,十分优秀!