我在XNA中写了一个光线三角形碰撞。要做到这一点,我正在从我的模型中生成一个三角形列表,然后我使用相同的矩阵进行变换,我用它来变换模型来绘制它。然后我在变换后的三角形列表上运行一个三角形交叉算法,看看我是否点击它。
据我所知,由于性能问题,这不是最好的解决方案,但转换光线并没有成功,所以我将继续这样做。
我的问题是单独变换的三角形不会生成与变换模型相同的形状。
左边是XNA绘制的模型。右侧是响应鼠标点击的区域。 (为了得到这个图像,我生成了一个float?-s数组,其中我存储了三角形交集算法在变换后的三角形上测量的距离。然后,对于每个非空值,我在secreen上绘制了一个像素:像素的像素,交叉路口越靠近相机。)
我的假设是变换的三角形实际上产生了上面的形状。这意味着单独转换它们的椎骨不会产生与整体模型转换相同的结果。我不明白为什么。
这是绘图代码:
public void DrawMe(Camera camera, Matrix world, Texture2D texture)
{
foreach (ModelMesh mesh in ModelToDraw.Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.TextureEnabled = true;
effect.Texture = texture;
effect.EnableDefaultLighting();
effect.PreferPerPixelLighting = true;
effect.World = world;
effect.Projection = camera.Projection;
effect.View = camera.View;
}
mesh.Draw();
}
}
这是我用来转换三角形的代码: 在包含该片段信息的类中:
private void transformTriangles()
{
for (int i=0; i<myTriangles.Length; i++)
{
transformedTriangles[i] = myTriangles[i].GetCopy();
}
foreach (Triangle t in transformedTriangles)
{
t.Transform(world);
}
}
myTriangles包含从模型中提取的三角形。它们存储在自定义Triangle类中。我测试了这些数据是否准确无误。
GetCopy只返回一个新的Triangle实例,其数据与生成它的实例相同。
世界就是我用来转换模型的矩阵。
在三角形类中:
public void Transform(Matrix transformation)
{
vertices[0] = Vector3.Transform(vertices[0], transformation);
vertices[1] = Vector3.Transform(vertices[1], transformation);
vertices[2] = Vector3.Transform(vertices[2], transformation);
}
我的目标是让右侧的形状与左侧的形状相匹配。任何建议都表示赞赏。
谢谢!
编辑:
根据要求,这里是整个Triangle类:
class Triangle
{
public Vector3[] vertices;
public Vector3 normal;
public Triangle(Vector3 A, Vector3 B, Vector3 C)
{
vertices = new Vector3[3];
vertices[0] = A;
vertices[1] = B;
vertices[2] = C;
calculateNormal();
}
public Triangle(Vector3[] vertices)
{
this.vertices = vertices;
calculateNormal();
}
private void calculateNormal()
{
Vector3 AB = new Vector3();
Vector3 AC = new Vector3();
AB = Vector3.Subtract(vertices[1], vertices[0]);
AC = Vector3.Subtract(vertices[2], vertices[0]);
normal = Vector3.Cross(AB, AC);
normal.Normalize();
}
private Vector3 project(Vector3 projectUnto, Vector3 toProject)
{
float multiplier = Vector3.Dot(projectUnto, toProject)/Vector3.Dot(projectUnto, projectUnto);
return Vector3.Multiply(projectUnto, multiplier);
}
private Vector3? calculateIntersectionPoint(Ray r)
{
if (Vector3.Dot(r.Direction, normal) == 0)
{
return null;
}
Vector3 I, w;
float multiplier;
w = Vector3.Subtract(vertices[0], r.Position);
multiplier = Vector3.Dot(w, normal)/Vector3.Dot(r.Direction, normal);
I = Vector3.Add(r.Position, Vector3.Multiply(r.Direction, multiplier));
return I;
}
private bool inside(Vector3? i)
{
if (i == null)
{
return false;
}
float a, b, c;
Vector3 AB, AC, BC, v, w, u, AI, BI, CI;
Vector3 I = (Vector3) i;
AB = Vector3.Subtract(vertices[1], vertices[0]);
AC = Vector3.Subtract(vertices[2], vertices[0]);
BC = Vector3.Subtract(vertices[2], vertices[1]);
AI = Vector3.Subtract(I, vertices[0]);
BI = Vector3.Subtract(I, vertices[1]);
CI = Vector3.Subtract(I, vertices[2]);
v = Vector3.Subtract(AB, project(Vector3.Multiply(BC, -1), AB));
u = Vector3.Subtract(BC, project(Vector3.Multiply(AC, -1), BC));
w = Vector3.Subtract(Vector3.Multiply(AC, -1), project(AB, Vector3.Multiply(AC, -1)));
a = 1 - Vector3.Dot(v, AI)/Vector3.Dot(v, AB);
b = 1 - Vector3.Dot(u, BI)/Vector3.Dot(u, BC);
c = 1 - Vector3.Dot(w, CI)/Vector3.Dot(w, Vector3.Multiply(AC, -1));
return a >= 0 && a <= 1 && b >= 0 && b <= 1 && c >= 0 && c <= 1;
}
public float? Intersects(Ray ray)
{
Vector3? I = calculateIntersectionPoint(ray);
if (I == null)
{
return null;
}
if (inside(I))
{
Vector3 i = (Vector3) I;
return Vector3.Distance(ray.Position, i);
}
return null;
}
public Triangle GetCopy()
{
return new Triangle(vertices);
}
public void Transform(Matrix transformation)
{
vertices[0] = Vector3.Transform(vertices[0], transformation);
vertices[1] = Vector3.Transform(vertices[1], transformation);
vertices[2] = Vector3.Transform(vertices[2], transformation);
}
}
编辑2:
根据请求,生成光线的代码。如果你问我,可能不会更标准:
private Ray getRay()
{
Vector3 nearPoint = BoardViewPort.Unproject(new Vector3(ms.X, ms.Y, 0), cam.Projection, cam.View, Matrix.Identity);
Vector3 farPoint = BoardViewPort.Unproject(new Vector3(ms.X, ms.Y, 1), cam.Projection, cam.View, Matrix.Identity);
Vector3 direction = farPoint - nearPoint;
direction.Normalize();
return new Ray(nearPoint, direction);
}
答案 0 :(得分:0)
转换后我根本没有重新计算正常情况。添加calculateNormal();转换函数结束时的语句解决了问题。