我想渲染一个模型,如果特定的顶点(我该如何标记它们?)可见,我想在它们所在的位置上渲染一些2D内容。
我该怎么做呢?
我该怎么做呢?
Vector4
(透视投影需要使用齐次坐标;设置W = 1
)。我假设您知道要获取哪个顶点以及如何获取其位置。其位置将在模型空间中。Vector4 position = new Vector4(/* your position as a Vector3 */, 1);
IEffectMatrices e = /* a BasicEffect or whatever you are using to render with */
Matrix worldViewProjection = e.World * e.View * e.Projection;
Vector4 result = Vector4.Transform(position, worldViewProjection);
result /= result.W;
SpriteBatch
使用的),那么只需使用与SpriteBatch
所使用的隐式视图-投影矩阵相匹配的矩阵的逆变换即可。Viewport vp = GraphicsDevice.Viewport;
Matrix invClient = Matrix.Invert(Matrix.CreateOrthographicOffCenter(0, vp.Width, vp.Height, 0, -1, 1));
Vector2 clientResult = Vector2.Transform(new Vector2(result.X, result.Y), invClient);
可能最好的方法是使用一个BoundingFrustrum
。它基本上像一个矩形,向某个方向扩展,类似于玩家的相机工作方式。然后,您可以检查所需点是否包含在BoundingFrustrum中,如果是,则渲染您的对象。
基本上,它形成的形状看起来像这样:
示例:
// A view frustum almost always is initialized with the ViewMatrix * ProjectionMatrix
BoundingFrustum viewFrustum = new BoundingFrustum(ActivePlayer.ViewMatrix * ProjectionMatrix);
// Check every entity in the game to see if it collides with the frustum.
foreach (Entity sourceEntity in entityList)
{
// Create a collision sphere at the entities location. Collision spheres have a
// relative location to their entity and this translates them to a world location.
BoundingSphere sourceSphere = new BoundingSphere(sourceEntity.Position,
sourceEntity.Model.Meshes[0].BoundingSphere.Radius);
// Checks if entity is in viewing range, if not it is not drawn
if (viewFrustum.Intersects(sourceSphere))
sourceEntity.Draw(gameTime);
}
这个例子实际上是用于剔除游戏中的所有对象,但可以很容易地修改以处理您想要执行的操作。
示例源代码:http://nfostergames.com/Lessons/SimpleViewCulling.htm
要将您的世界坐标转换为屏幕空间,请查看Viewport.Project。
仔细看一下你的引擎中的遮挡剔除功能。对于XNA,你可以在这里查阅框架指南(包含示例)。
Vector4 aux = Vector4.Transform(new Vector4(position, 1), worldViewProjection); result.X = aux.X /aux.W; result.Y = aux.Y /aux.W; result.Z = aux.Z /aux.W;
我尝试编辑安德鲁的回复,但被拒绝了... :( - Blau