我正在XNA中編寫光線三角形碰撞。爲此,我從我的模型生成一個三角形列表,然後使用我用來轉換模型來繪製它的相同矩陣進行變換。然後,我在轉換後的三角形列表上運行一個三角形交集算法,看看我是否擊中它。XNA:轉換個別三角形給出了不同於轉換模型的結果
我明白,這是不是因爲性能問題的最佳解決方案,但改造射線沒有發揮出來,所以我有這個打算。
我的問題是,單獨的三角形轉化也沒有產生變換模型是相同的形狀。
在左邊的是該模型由XNA繪製。右側是響應鼠標點擊的區域。 (爲了得到這個圖像,我生成了一個float?-s數組,其中存儲了三角形交集算法在轉換後的三角形上測量的距離。然後,對於每個非空值,我在secreen上繪製了一個像素:像素越高,越接近intersetion方式向照相機。)
我的假設是實際轉化的三角形產生上述的形狀。這意味着單獨轉換它們的頂點不會產生與整體模型轉換相同的結果。我不明白爲什麼。
下面是附圖的代碼:
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簡單地返回具有相同的數據作爲實例生成一個新的三角形實例。
世界就是我用來改變我的模型的矩陣。
在三角形類:
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);
}
我的目標是對匹配左邊的形狀合適的形狀。任何建議表示讚賞。
謝謝!
編輯:
根據要求,在此是整體三角類:
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);
}
是'Triangle'類還是結構?請顯示你的碰撞碼。 –
老實說,我不知道你在那裏做什麼樣的花哨的東西。以前沒見過有人這樣做過。特別是「內部」方法似乎太過分了。看看[這裏](http://gamedev.stackexchange.com/questions/23743/whats-the-most-efficient-way-to-find-barycentric-coordinates)看看如何計算重心座標。我強烈建議您清理數學(或至少編寫單元測試以充分測試它)。這可能就是你的光線轉換不起作用的原因。並使用合理的變量名稱! –
順便說一句,你知道象'*',''和'+'這樣的常用運算符對於向量來說是過載的,對吧?使用那些而不是'Vector3.Subtract'等。這會使你的代碼更具可讀性。 –