- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 SceneKit 中,我试图创建一个带有纹理的简单自定义几何体。我只是想制作一个立方体,但每个面的方向都正确,因此 SCNBox 将无法工作。
形状非常好,但纹理映射完全错误。
这是几何图形的样子:
根据我的理解,每个面的纹理坐标应该是相同的。但是,当我以相同的顺序为每张脸添加点时,它会以类似的方式绘制错误。所以我玩弄了坐标的顺序,并得到了正面、背面和一侧的面,大部分都正确地绘制了。不过,我一直无法找出导致这种情况的模式或逻辑。
正面是每张脸的样子。
这是我的做法:
public struct face {
var topLeft: SCNVector3
var topRight: SCNVector3
var bottomLeft: SCNVector3
var bottomRight: SCNVector3
}
func createCube(startFace: face, endFace: face) -> SCNGeometry {
var vertices: [SCNVector3] = []
var indices: [Int32] = []
var textCords: [vector_float2] = []
// Add table of contents to indices array because we're using polygons
let polygons = 6 // cube so 6 faces
indices.append(4) // front face
indices.append(4) // left face
indices.append(4) // right face
indices.append(4) // top face
indices.append(4) // bottom face
indices.append(4) // back face
// - Convenience Values -
// Indices offsets
let startFaceVertex: Int32 = 0
let endFaceVertex: Int32 = 4
// Vertex indices
let bottomLeftPos: Int32 = 0
let bottomRightPos: Int32 = 1
let topRightPos: Int32 = 2
let topLeftPos: Int32 = 3
// Texture Coordinates
let topLeft = CGPoint(x: 0, y: 1)
let topRight = CGPoint(x: 1, y: 1)
let bottomLeft = CGPoint(x: 0, y: 0)
let bottomRight = CGPoint(x: 1, y: 0)
// Add vertices
vertices.append(startFace.bottomLeft)
vertices.append(startFace.bottomRight)
vertices.append(startFace.topRight)
vertices.append(startFace.topLeft)
vertices.append(endFace.bottomLeft)
vertices.append(endFace.bottomRight)
vertices.append(endFace.topRight)
vertices.append(endFace.topLeft)
// Front Face
indices.append(startFaceVertex + bottomLeftPos)
indices.append(startFaceVertex + bottomRightPos)
indices.append(startFaceVertex + topRightPos)
indices.append(startFaceVertex + topLeftPos)
textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y)))
textCords.append(vector_float2(Float(topRight.x), Float(topRight.y)))
textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y)))
textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y)))
// Left Face
indices.append(startFaceVertex + bottomLeftPos)
indices.append(endFaceVertex + bottomLeftPos)
indices.append(endFaceVertex + topLeftPos)
indices.append(startFaceVertex + topLeftPos)
textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y)))
textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y)))
textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y)))
textCords.append(vector_float2(Float(topRight.x), Float(topRight.y)))
// Top Face
indices.append(endFaceVertex + topLeftPos)
indices.append(endFaceVertex + topRightPos)
indices.append(startFaceVertex + topRightPos)
indices.append(startFaceVertex + topLeftPos)
textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y)))
textCords.append(vector_float2(Float(topRight.x), Float(topRight.y)))
textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y)))
textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y)))
// Right Face
indices.append(endFaceVertex + bottomRightPos)
indices.append(startFaceVertex + bottomRightPos)
indices.append(startFaceVertex + topRightPos)
indices.append(endFaceVertex + topRightPos)
textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y)))
textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y)))
textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y)))
textCords.append(vector_float2(Float(topRight.x), Float(topRight.y)))
// Bottom Face
indices.append(startFaceVertex + bottomLeftPos)
indices.append(startFaceVertex + bottomRightPos)
indices.append(endFaceVertex + bottomRightPos)
indices.append(endFaceVertex + bottomLeftPos)
textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y)))
textCords.append(vector_float2(Float(topRight.x), Float(topRight.y)))
textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y)))
textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y)))
// Back Face
indices.append(endFaceVertex + bottomLeftPos)
indices.append(endFaceVertex + bottomRightPos)
indices.append(endFaceVertex + topRightPos)
indices.append(endFaceVertex + topLeftPos)
textCords.append(vector_float2(Float(topLeft.x), Float(topLeft.y)))
textCords.append(vector_float2(Float(topRight.x), Float(topRight.y)))
textCords.append(vector_float2(Float(bottomRight.x), Float(bottomRight.y)))
textCords.append(vector_float2(Float(bottomLeft.x), Float(bottomLeft.y)))
// Create geometry
let verticesSource = SCNGeometrySource(vertices: vertices)
let uvData = Data(bytes: textCords, count: textCords.count * MemoryLayout<vector_float2>.size)
let textureSource = SCNGeometrySource(data: uvData,
semantic: .texcoord,
vectorCount: textCords.count,
usesFloatComponents: true,
componentsPerVector: 2,
bytesPerComponent: MemoryLayout<Float>.size,
dataOffset: 0,
dataStride: MemoryLayout<vector_float2>.size)
let indexData = Data(bytes: indices,
count: indices.count * MemoryLayout<Int32>.size)
let elements = SCNGeometryElement(data: indexData,
primitiveType: .polygon,
primitiveCount: polygons,
bytesPerIndex: MemoryLayout<Int32>.size)
return SCNGeometry(sources: [verticesSource, textureSource], elements: [elements])
}
解决方案
开始工作了,这是我的工作版本代码:
public struct face {
var topLeft: SCNVector3
var topRight: SCNVector3
var bottomLeft: SCNVector3
var bottomRight: SCNVector3
}
let topLeft = CGPoint(x: 0, y: 1)
let topRight = CGPoint(x: 1, y: 1)
let bottomLeft = CGPoint(x: 0, y: 0)
let bottomRight = CGPoint(x: 1, y: 0)
func createCube(startFace: face, endFace: face) -> SCNGeometry {
var vertices: [SCNVector3] = []
var indexTable: [Int32] = []
var indices: [Int32] = []
var textCords: [vector_float2] = []
// Front Face
addFace(face: startFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords)
// Left Face
let leftFace = face(topLeft: endFace.topLeft, topRight: startFace.topLeft, bottomLeft: endFace.bottomLeft, bottomRight: startFace.bottomLeft, center: SCNVector3Zero, originOffset: startFace.originOffset)
addFace(face: leftFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords)
// Top Face
//let topFace = face(topLeft: startFace.topLeft, topRight: endFace.topLeft, bottomLeft: startFace.topRight, bottomRight: endFace.topRight, center: SCNVector3Zero, originOffset: startFace.originOffset)
let topFace = face(topLeft: startFace.topLeft, topRight: endFace.topLeft, bottomLeft: startFace.topRight, bottomRight: endFace.topRight, center: SCNVector3Zero, originOffset: startFace.originOffset)
addFace(face: topFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords)
// Right Face
let rightFace = face(topLeft: startFace.topRight, topRight: endFace.topRight, bottomLeft: startFace.bottomRight, bottomRight: endFace.bottomRight, center: SCNVector3Zero, originOffset: startFace.originOffset)
addFace(face: rightFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords)
// Bottom Face
let bottomFace = face(topLeft: endFace.bottomLeft, topRight: startFace.bottomLeft, bottomLeft: endFace.bottomRight, bottomRight: startFace.bottomRight, center: SCNVector3Zero, originOffset: startFace.originOffset)
addFace(face: bottomFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords)
// Back Face
addFace(face: endFace, textureOffset: CGPoint.zero, textureSize: CGSize(width: 1, height: 1), toVertices: &vertices, indexTable: &indexTable, indices: &indices, textCords: &textCords)
// Create geometry
let verticesSource = SCNGeometrySource(vertices: vertices)
let uvData = Data(bytes: textCords, count: textCords.count * MemoryLayout<vector_float2>.size)
let textureSource = SCNGeometrySource(data: uvData,
semantic: .texcoord,
vectorCount: textCords.count,
usesFloatComponents: true,
componentsPerVector: 2,
bytesPerComponent: MemoryLayout<Float>.size,
dataOffset: 0,
dataStride: MemoryLayout<vector_float2>.size)
var finalIndices: [Int32] = []
finalIndices.append(contentsOf: indexTable)
finalIndices.append(contentsOf: indices)
let indexData = Data(bytes: finalIndices,
count: finalIndices.count * MemoryLayout<Int32>.size)
let elements = SCNGeometryElement(data: indexData,
primitiveType: .polygon,
primitiveCount: indexTable.count,
bytesPerIndex: MemoryLayout<Int32>.size)
return SCNGeometry(sources: [verticesSource, textureSource], elements: [elements])
}
fileprivate func addFace(face: face, textureOffset: CGPoint, textureSize: CGSize, toVertices: inout [SCNVector3], indexTable: inout [Int32], indices: inout [Int32], textCords: inout [vector_float2]) {
toVertices.append(face.topRight)
toVertices.append(face.topLeft)
toVertices.append(face.bottomLeft)
toVertices.append(face.bottomRight)
let polygonPointCount: Int32 = 4
indexTable.append(polygonPointCount)
for _ in 0..<polygonPointCount {
indices.append(Int32(indices.count))
}
textCords.append(vector_float2(Float(bottomRight.x + textureOffset.x + textureSize.width), Float(bottomRight.y + textureOffset.y)))
textCords.append(vector_float2(Float(bottomLeft.x + textureOffset.x + textureSize.width), Float(bottomLeft.y + textureOffset.y)))
textCords.append(vector_float2(Float(topLeft.x + textureOffset.x + textureSize.width), Float(topLeft.y + textureOffset.y)))
textCords.append(vector_float2(Float(topRight.x + textureOffset.x + textureSize.width), Float(topRight.y + textureOffset.y)))
}
最佳答案
一个顶点位置和所有相关的属性组成一条记录。这意味着,如果必须使用不同的纹理坐标多次使用顶点位置,则必须为每个纹理坐标将顶点位置添加到缓冲区一次。不可能将元素数组与纹理坐标相关联。
您必须为立方体的每一侧创建一个具有 4 个顶点的顶点位置缓冲区,并为立方体的每一侧创建一个具有 4 个纹理坐标的纹理坐标缓冲区:
texureCoordsSide =[
vector_float2(Float(bottomLeft.x), Float(bottomLeft.y)),
vector_float2(Float(bottomRight.x), Float(bottomRight.y)),
vector_float2(Float(topRight.x), Float(topRight.y)),
vector_float2(Float(topLeft.x), Float(topLeft.y))]
// Front Face
vertices += [startFace.bottomLeft, startFace.bottomRight, startFace.topRight, startFace.topLeft];
textCords += texureCoordsSide
// Left Face
vertices += [endFace.bottomLeft, startFace.bottomLeft, startFace.topLeft, endFace.topLeft];
textCords += texureCoordsSide
// Top Face
vertices += [startFace.topLeft, startFace.topRight, endFace.topRight, endFace.topLeft];
textCords += texureCoordsSide
// Right Face
vertices += [startFace.bottomRight, endFace.bottomRight, endFace.topRight, startFace.topRight];
textCords += texureCoordsSide
// Bottom Face
vertices += [endFace.bottomRight, endFace.bottomLeft, startFace.bottomLeft, startFace.bottomRight];
textCords += texureCoordsSide
// Back Face
vertices += [endFace.bottomRight, endFace.bottomLeft, endFace.topLeft, endFace.topRight];
textCords += texureCoordsSide
元素数组 (indices
) 必须包含从 0 到 23 的连续顺序的 24 个索引(立方体的 6 个边各有 4 个)。
关于ios - SceneKit自定义几何纹理错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46383685/
IO 设备如何知道属于它的内存中的值在memory mapped IO 中发生了变化? ? 例如,假设内存地址 0 专用于保存 VGA 设备的背景颜色。当我们更改 memory[0] 中的值时,VGA
我目前正在开发一个使用Facebook sdk登录(通过FBLoginView)的iOS应用。 一切正常,除了那些拥有较旧版本的facebook的人。 当他们按下“使用Facebook登录”按钮时,他
假设我有: this - is an - example - with some - dashesNSRange将使用`rangeOfString:@“-”拾取“-”的第一个实例,但是如果我只想要最后
Card.io SDK提供以下详细信息: 卡号,有效期,月份,年份,CVV和邮政编码。 如何从此SDK获取国家名称。 - (void)userDidProvideCreditCardInfo:(Car
iOS 应用程序如何从网络服务下载图片并在安装过程中将它们安装到用户的 iOS 设备上?可能吗? 最佳答案 您无法控制应用在用户设备上的安装,因此无法在安装过程中下载其他数据。 只需在安装后首次启动应
我曾经开发过一款企业版 iOS 产品,我们公司曾将其出售给大型企业,供他们的员工使用。 该应用程序通过 AppStore 提供,企业用户获得了公司特定的配置文件(包含应用程序配置文件)以启用他们有权使
我正在尝试将 Card.io SDK 集成到我的 iOS 应用程序中。我想为 CardIO ui 做一个简单的本地化,如更改取消按钮标题或“在此保留信用卡”提示文本。 我在 github 上找到了这个
我正在使用 CardIOView 和 CardIOViewDelegate 类,没有可以设置为 YES 的 BOOL 来扫描 collectCardholderName。我可以看到它在 CardIOP
我有一个集成了通话工具包的 voip 应用程序。每次我从我的 voip 应用程序调用时,都会在 native 电话应用程序中创建一个新的最近通话记录。我在 voip 应用程序中也有自定义联系人(电话应
iOS 应用程序如何知道应用程序打开时屏幕上是否已经有键盘?应用程序运行后,它可以接收键盘显示/隐藏通知。但是,如果应用程序在分屏模式下作为辅助应用程序打开,而主应用程序已经显示键盘,则辅助应用程序不
我在模拟器中收到以下错误: ImageIO: CGImageReadSessionGetCachedImageBlockData *** CGImageReadSessionGetCachedIm
如 Apple 文档所示,可以通过 EAAccessory Framework 与经过认证的配件(由 Apple 认证)进行通信。但是我有点困惑,因为一些帖子告诉我它也可以通过 CoreBluetoo
尽管现在的调试器已经很不错了,但有时找出应用程序中正在发生的事情的最好方法仍然是古老的 NSLog。当您连接到计算机时,这样做很容易; Xcode 会帮助弹出日志查看器面板,然后就可以了。当您不在办公
在我的 iOS 应用程序中,我定义了一些兴趣点。其中一些有一个 Kontakt.io 信标的名称,它绑定(bind)到一个特定的 PoI(我的意思是通常贴在信标标签上的名称)。现在我想在附近发现信标,
我正在为警报提示创建一个 trigger.io 插件。尝试从警报提示返回数据。这是我的代码: // Prompt + (void)show_prompt:(ForgeTask*)task{
您好,我是 Apple iOS 的新手。我阅读并搜索了很多关于推送通知的文章,但我没有发现任何关于 APNS 从 io4 到 ios 6 的新更新的信息。任何人都可以向我提供 APNS 如何在 ios
UITabBar 的高度似乎在 iOS 7 和 8/9/10/11 之间发生了变化。我发布这个问题是为了让其他人轻松找到答案。 那么:在 iPhone 和 iPad 上的 iOS 8/9/10/11
我想我可以针对不同的 iOS 版本使用不同的 Storyboard。 由于 UI 的差异,我将创建下一个 Storyboard: Main_iPhone.storyboard Main_iPad.st
我正在写一些东西,我将使用设备的 iTunes 库中的一部分音轨来覆盖 2 个视频的组合,例如: AVMutableComposition* mixComposition = [[AVMutableC
我创建了一个简单的 iOS 程序,可以顺利编译并在 iPad 模拟器上运行良好。当我告诉 XCode 4 使用我连接的 iPad 设备时,无法编译相同的程序。问题似乎是当我尝试使用附加的 iPad 时
我是一名优秀的程序员,十分优秀!