确定 3D 立方体上哪一面面向观察者
对于一项学校作业,我和一个朋友一直致力于使用 2D 库(slick)在 2D 表面(屏幕)上渲染立方体
为此,我们使用此处描述的方法 3D 投影 - 维基百科免费百科全书。
我们使用 3x3 矩阵来旋转表示立方体表面上的点的 3D 向量。然后我们使用以下方法将 3D 矢量投影到位于正 X 轴的平面(屏幕)上:
public Vector2D translate2D(Vector3D v){
Vector3D trans = translate(v);//Rotates the vector into position
float w = -trans.getX()/(700) + 1;
float x = (trans.getZ())/w;
float y = (trans.getY())/w;
return new Vector2D(x, y);
}
其中,translate() 将矢量旋转到正确的位置,w 向立方体添加一些透视。
现在问题是:
我需要知道立方体的哪些面要渲染,哪些面不渲染(即哪些面面向观看者,哪些面不面向观看者)。只要您不使用透视图(w),这很容易。立方体始终向用户显示三个面,要找到这些面,您需要做的就是:
- 获取该面的法线
- 使用旋转矩阵平移它
- 如果平移法线 X 分量为正,则该面面向正 X 方向因此对于观众来说是可见的。
这是因为屏幕直接位于正 X 轴上。
现在,由于透视的原因,观察者面临着 1-3 个侧面,具体取决于立方体的旋转。 如何在计算中补偿透视并确定哪一侧面向观察者?如上所述,我可以访问每侧的法线(直接指向每侧的单位向量)以及处理旋转方法同上。
(编辑)谢谢您的回答horatius83,但这是我的问题:我不知道他的表面是否正常,因为由于增加的视角,侧面的法线稍微扭曲了。
这里有一些图像来进一步描述我的问题
没有透视(侧面法线=表面法线):
显示透视3 面(面法线!=表面法线):
透视图显示 3 面,但应该只显示1(侧面法线!=表面法线)
(编辑)确定是否应渲染侧面的代码是非常简单,但并不完全正确,因为我们使用侧面的法线,就好像没有透视一样(如图 1 所示)。如果有观点,就必须以某种方式补偿。我只是不知道怎么办。
public boolean sideVisible(Vector3D normal){
if (translate(normal).getX()>0) {
return true;
}else{
return false;
}
}
For a school assignment me and a friend have been working on rendering a cube on a 2D surface(the screen) using a 2D-library(slick)
To do this we use the method described here 3D-projection - Wikipedia the free encyclopedia.
We use a 3x3 matrix to rotate the 3D-vectors which represents points on the cubes surface. Then We project the 3D vectors onto a plane(the screen) located on the positive X-axis using this method:
public Vector2D translate2D(Vector3D v){
Vector3D trans = translate(v);//Rotates the vector into position
float w = -trans.getX()/(700) + 1;
float x = (trans.getZ())/w;
float y = (trans.getY())/w;
return new Vector2D(x, y);
}
where translate() rotates the vector into the correct position and w adds some perspective to the cube.
Now here's the problem:
I need to know which sides of the cube to render and which to not render(i e which are facing the viewer and which aren't). As long as you don't use perspective(w) this is easy. The cube always shows three sides to the user and to find these all you needed to do was:
- Get the side's normal
- Translate it using the rotational matrix
- If the translated normals X-component was positive, then the side was facing the positive X-direction and therefore was to be visible to the viewer.
This because the screen is located directly on the positive X-axis.
Now, because of perspective, the viewer is facing 1-3 sides depending on the rotation of the cube. How can I compensate for perspective in my calculations and determine which sides are facing the viewer? As mentioned I have access to each side's normal(unit vectors pointing straight away from each side) and the matrix which handles the rotation as well as the above method.
(edit) Thank you for your answer horatius83 but here's my problem: I dont know he surfaces normal since the side's normal is slightly distorted due to the added perspective.
Here are some images to describe my problem further
Without perspective(side's normal=surface normal):
With perspective showing 3 sides(side's normal!=surface normal):
With perspective showing 3 sides but should only be showing 1(side's normal!=surface normal)
(edit) the code determining whether the side should be rendered is very simple and not entirely correct since we're using the side's normal as if there was no perspective(as in image 1). If there is perspective this must be compensated for in some way. I just don't know how.
public boolean sideVisible(Vector3D normal){
if (translate(normal).getX()>0) {
return true;
}else{
return false;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
取视图向量(想象一个从相机中出来的箭头)和表面法线的点积。如果为负,则面部可见。
(编辑:您需要在世界空间中进行这些计算,即遵循模型到世界的转换)
Take the dot-product of the view-vector (imagine an arrow coming out of the camera) and the surface normal. If it's negative, then the face is visible.
(Edit: you'll want to do these calculations in world-space, that is following the model to world transformation)
首先感谢 horatius83 和 asawyer 提供的许多有用的提示。以下是在不知道表面法线的情况下,仅使用侧面法线以及屏幕和观看者的位置来解决此问题的方法。
有关详细说明,请参阅 此链接
First of all thanks to horatius83 and asawyer for many useful tips. Here's how to solve this without knowing the surface normal, just using the side's normal and the position of the screen and viewer.
For a lengthier explanation see this link