SceneKit – SCNMatrix4 中最低行的元素是做什么用的?
SceneKit – What is the lowest row of elements in SCNMatrix4 for?
在 SCNMatrix4
结构中,最后一个 m44
元素用于齐次坐标。
I'd like to know what are m41
, m42
and m43
elements in SCNMatrix4? And what exactly I can use these three elements for?
init(m11: Float, m12: Float, m13: Float, m14: Float,
m21: Float, m22: Float, m23: Float, m24: Float,
m31: Float, m32: Float, m33: Float, m34: Float,
m41: Float, m42: Float, m43: Float, m44: Float)
我可能是错的,但我认为 m41
、m42
和 m43
可用于获取位置数据,并且与使用 result.worldTransform.columns.3
时基本相同执行 hitTest。
因此,当通过执行 ARSCNHitTest
放置 SCNNode
时,您可以使用:
let hitTestTransform = SCNMatrix4(result.worldTransform)
let positionFromMatrix4 = SCNVector3(hitTestTransform.m41, hitTestTransform.m42, hitTestTransform.m43)
let positionFromColumns = SCNVector3(result.worldTransform.columns.3.x, result.worldTransform.columns.3.y, result.worldTransform.columns.3.z)
下面的例子应该有助于澄清事情:
/// Places Our Model At The Position Of An Existining ARPlaneAnchor
///
/// - Parameter gesture: UITapGestureRecognizer
@IBAction func placeModel(_ gesture: UITapGestureRecognizer){
//1. Get The Touch Location
let touchLocation = gesture.location(in: self.augmentedRealityView)
//2. Perform An ARSCNHitTest For Any Existing Planes
guard let result = self.augmentedRealityView.hitTest(touchLocation, types: [.existingPlane, .existingPlaneUsingExtent]).first else { return }
//3. Get The World Transform
let hitTestTransform = SCNMatrix4(result.worldTransform)
//4. Initialize Our Position Either From .m41, .m42, .m43 Or From Columns.3
let positionFromMatrix4 = SCNVector3(hitTestTransform.m41, hitTestTransform.m42, hitTestTransform.m43)
let positionFromColumns = SCNVector3(result.worldTransform.columns.3.x, result.worldTransform.columns.3.y, result.worldTransform.columns.3.z)
//5. Log Them To Check I'm Not Being A Moron
print(
"""
Position From Matrix 4 == \(positionFromMatrix4)
Position From Columns == \(positionFromColumns)
""")
/*
Position From Matrix 4 == SCNVector3(x: -0.39050543, y: -0.004766479, z: 0.08107365)
Position From Columns == SCNVector3(x: -0.39050543, y: -0.004766479, z: 0.08107365)
*/
//6. Add A Node At The Position & Add It To The Hierachy
let boxNode = SCNNode(geometry: SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0))
boxNode.geometry?.firstMaterial?.diffuse.contents = UIColor.cyan
boxNode.position = positionFromMatrix4
self.augmentedRealityView.scene.rootNode.addChildNode(boxNode)
}
希望对您有所帮助...
基于@BlackMirrorz 的回答。
使用 SceneKit 的相机投影时,在 SCNMatrix4
中使用 m41
、m42
和 m43
元素的明显实际好处出现了。
最后一行用于平移和投影,例如透视图或相机视锥体。
虽然不是 Apple 代码,但以下来源(根据 MIT 许可获得许可)取自 https://referencesource.microsoft.com/#System.Numerics/System/Numerics/Matrix4x4.cs,78a107de58a17946(从第 864 行开始),显示“[如何创建] 基于视野、宽高比的透视投影矩阵, 以及近景和远景平面距离。"
/// <summary>
/// Creates a perspective projection matrix based on a field of view, aspect ratio, and near and far view plane distances.
/// </summary>
/// <param name="fieldOfView">Field of view in the y direction, in radians.</param>
/// <param name="aspectRatio">Aspect ratio, defined as view space width divided by height.</param>
/// <param name="nearPlaneDistance">Distance to the near view plane.</param>
/// <param name="farPlaneDistance">Distance to the far view plane.</param>
/// <returns>The perspective projection matrix.</returns>
public static Matrix4x4 CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance)
{
if (fieldOfView <= 0.0f || fieldOfView >= Math.PI)
throw new ArgumentOutOfRangeException("fieldOfView");
if (nearPlaneDistance <= 0.0f)
throw new ArgumentOutOfRangeException("nearPlaneDistance");
if (farPlaneDistance <= 0.0f)
throw new ArgumentOutOfRangeException("farPlaneDistance");
if (nearPlaneDistance >= farPlaneDistance)
throw new ArgumentOutOfRangeException("nearPlaneDistance");
float yScale = 1.0f / (float)Math.Tan(fieldOfView * 0.5f);
float xScale = yScale / aspectRatio;
Matrix4x4 result;
result.M11 = xScale;
result.M12 = result.M13 = result.M14 = 0.0f;
result.M22 = yScale;
result.M21 = result.M23 = result.M24 = 0.0f;
result.M31 = result.M32 = 0.0f;
result.M33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
result.M34 = -1.0f;
result.M41 = result.M42 = result.M44 = 0.0f;
result.M43 = nearPlaneDistance * farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
return result;
}
这个片段是 ARKit - 它获取相机的位置...
https://gist.github.com/fisherds/a2a75c914c293213f594daf5fd940d3d
@IBAction func pressedAddEarth(_ sender: Any) {
guard let pointOfView = sceneView.pointOfView else {return}
let transform = pointOfView.transform
let orientation = SCNVector3(-transform.m31, -transform.m32, -transform.m33)
let location = SCNVector3(transform.m41, transform.m42, transform.m43)
let currentPositionOfCamera = orientation + location
// other stuff
}
func +(left: SCNVector3, right: SCNVector3) -> SCNVector3 {
return SCNVector3Make(left.x + right.x, left.y + right.y, left.z + right.z)
}
在 SCNMatrix4
结构中,最后一个 m44
元素用于齐次坐标。
I'd like to know what are
m41
,m42
andm43
elements in SCNMatrix4? And what exactly I can use these three elements for?
init(m11: Float, m12: Float, m13: Float, m14: Float,
m21: Float, m22: Float, m23: Float, m24: Float,
m31: Float, m32: Float, m33: Float, m34: Float,
m41: Float, m42: Float, m43: Float, m44: Float)
我可能是错的,但我认为 m41
、m42
和 m43
可用于获取位置数据,并且与使用 result.worldTransform.columns.3
时基本相同执行 hitTest。
因此,当通过执行 ARSCNHitTest
放置 SCNNode
时,您可以使用:
let hitTestTransform = SCNMatrix4(result.worldTransform)
let positionFromMatrix4 = SCNVector3(hitTestTransform.m41, hitTestTransform.m42, hitTestTransform.m43)
let positionFromColumns = SCNVector3(result.worldTransform.columns.3.x, result.worldTransform.columns.3.y, result.worldTransform.columns.3.z)
下面的例子应该有助于澄清事情:
/// Places Our Model At The Position Of An Existining ARPlaneAnchor
///
/// - Parameter gesture: UITapGestureRecognizer
@IBAction func placeModel(_ gesture: UITapGestureRecognizer){
//1. Get The Touch Location
let touchLocation = gesture.location(in: self.augmentedRealityView)
//2. Perform An ARSCNHitTest For Any Existing Planes
guard let result = self.augmentedRealityView.hitTest(touchLocation, types: [.existingPlane, .existingPlaneUsingExtent]).first else { return }
//3. Get The World Transform
let hitTestTransform = SCNMatrix4(result.worldTransform)
//4. Initialize Our Position Either From .m41, .m42, .m43 Or From Columns.3
let positionFromMatrix4 = SCNVector3(hitTestTransform.m41, hitTestTransform.m42, hitTestTransform.m43)
let positionFromColumns = SCNVector3(result.worldTransform.columns.3.x, result.worldTransform.columns.3.y, result.worldTransform.columns.3.z)
//5. Log Them To Check I'm Not Being A Moron
print(
"""
Position From Matrix 4 == \(positionFromMatrix4)
Position From Columns == \(positionFromColumns)
""")
/*
Position From Matrix 4 == SCNVector3(x: -0.39050543, y: -0.004766479, z: 0.08107365)
Position From Columns == SCNVector3(x: -0.39050543, y: -0.004766479, z: 0.08107365)
*/
//6. Add A Node At The Position & Add It To The Hierachy
let boxNode = SCNNode(geometry: SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0))
boxNode.geometry?.firstMaterial?.diffuse.contents = UIColor.cyan
boxNode.position = positionFromMatrix4
self.augmentedRealityView.scene.rootNode.addChildNode(boxNode)
}
希望对您有所帮助...
基于@BlackMirrorz 的回答。
使用 SceneKit 的相机投影时,在 SCNMatrix4
中使用 m41
、m42
和 m43
元素的明显实际好处出现了。
最后一行用于平移和投影,例如透视图或相机视锥体。 虽然不是 Apple 代码,但以下来源(根据 MIT 许可获得许可)取自 https://referencesource.microsoft.com/#System.Numerics/System/Numerics/Matrix4x4.cs,78a107de58a17946(从第 864 行开始),显示“[如何创建] 基于视野、宽高比的透视投影矩阵, 以及近景和远景平面距离。"
/// <summary>
/// Creates a perspective projection matrix based on a field of view, aspect ratio, and near and far view plane distances.
/// </summary>
/// <param name="fieldOfView">Field of view in the y direction, in radians.</param>
/// <param name="aspectRatio">Aspect ratio, defined as view space width divided by height.</param>
/// <param name="nearPlaneDistance">Distance to the near view plane.</param>
/// <param name="farPlaneDistance">Distance to the far view plane.</param>
/// <returns>The perspective projection matrix.</returns>
public static Matrix4x4 CreatePerspectiveFieldOfView(float fieldOfView, float aspectRatio, float nearPlaneDistance, float farPlaneDistance)
{
if (fieldOfView <= 0.0f || fieldOfView >= Math.PI)
throw new ArgumentOutOfRangeException("fieldOfView");
if (nearPlaneDistance <= 0.0f)
throw new ArgumentOutOfRangeException("nearPlaneDistance");
if (farPlaneDistance <= 0.0f)
throw new ArgumentOutOfRangeException("farPlaneDistance");
if (nearPlaneDistance >= farPlaneDistance)
throw new ArgumentOutOfRangeException("nearPlaneDistance");
float yScale = 1.0f / (float)Math.Tan(fieldOfView * 0.5f);
float xScale = yScale / aspectRatio;
Matrix4x4 result;
result.M11 = xScale;
result.M12 = result.M13 = result.M14 = 0.0f;
result.M22 = yScale;
result.M21 = result.M23 = result.M24 = 0.0f;
result.M31 = result.M32 = 0.0f;
result.M33 = farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
result.M34 = -1.0f;
result.M41 = result.M42 = result.M44 = 0.0f;
result.M43 = nearPlaneDistance * farPlaneDistance / (nearPlaneDistance - farPlaneDistance);
return result;
}
这个片段是 ARKit - 它获取相机的位置... https://gist.github.com/fisherds/a2a75c914c293213f594daf5fd940d3d
@IBAction func pressedAddEarth(_ sender: Any) {
guard let pointOfView = sceneView.pointOfView else {return}
let transform = pointOfView.transform
let orientation = SCNVector3(-transform.m31, -transform.m32, -transform.m33)
let location = SCNVector3(transform.m41, transform.m42, transform.m43)
let currentPositionOfCamera = orientation + location
// other stuff
}
func +(left: SCNVector3, right: SCNVector3) -> SCNVector3 {
return SCNVector3Make(left.x + right.x, left.y + right.y, left.z + right.z)
}