İlgi çekici noktaların üzerine bir ünlem işareti koyduğum bir 3D oyun yapıyorum.
2B ekranın neresinde yer almam gerektiğini öğrenmek için, 3B noktasını el ile işaretleyicinin olması gereken yere yansıtıyorum.
Şöyle görünüyor:
Oldukça iyi görünüyor. İşaretçi ekranın dışında olduğunda, koordinatları ekrana sığacak şekilde kırparım. Şöyle görünüyor:
Şimdiye kadar fikir oldukça iyi gidiyor. Ancak, ilgi noktaları kameranın arkasında olduğunda, ortaya çıkan X, Y koordinatları ters çevrilir (pozitif / negatif olarak) ve işaretçiyi ekranın karşı köşesinde görünmesini sağlarım, şöyle:
(Öngörülen-sonra-kenetli nokta işaretleyicinin ucu. İşaretçinin dönüşüne aldırmayın)
Frustumun arkasındaki koordinatlar X ve Y'de ters çevrildiğinden mantıklı geliyor. Yani yaptığım şey koordinatları kameranın arkasındayken tersine çevirmek. Ancak, yine de koordinatların ters çevrilmesi gereken durumun tam olarak ne olduğunu bilmiyorum.
Şu anda benim projeksiyon kodum gibi görünüyor (Sharp # ile C #):
public override PointF ProjectPosition(float viewportWidth, float viewportHeight, float y)
{
var projectionMatrix = Matrix.PerspectiveFovRH(GetCalibratedFOV(Camera.FOV, viewportWidth, viewportHeight), viewportWidth / viewportHeight, Camera.Near, Camera.Far);
var viewMatrix = Matrix.LookAtRH(new Vector3(Camera.PositionX, Camera.PositionY, Camera.PositionZ), new Vector3(Camera.LookAtX, Camera.LookAtY, Camera.LookAtZ), Vector3.UnitY);
var worldMatrix = Matrix.RotationY(Rotation) * Matrix.Scaling(Scaling) * Matrix.Translation(PositionX, PositionY, PositionZ);
var worldViewProjectionMatrix = worldMatrix * viewMatrix * projectionMatrix;
Vector4 targetVector = new Vector4(0, y, 0, 1);
Vector4 projectedVector = Vector4.Transform(targetVector, worldViewProjectionMatrix);
float screenX = (((projectedVector.X / projectedVector.W) + 1.0f) / 2.0f) * viewportWidth;
float screenY = ((1.0f - (projectedVector.Y / projectedVector.W)) / 2.0f) * viewportHeight;
float screenZ = projectedVector.Z / projectedVector.W;
// Invert X and Y when behind the camera
if (projectedVector.Z < 0 ||
projectedVector.W < 0)
{
screenX = -screenX;
screenY = -screenY;
}
return new PointF(screenX, screenY);
}
Gördüğünüz gibi, şu anki fikrim Z veya W koordinatları negatif olduğunda koordinatları tersine çevirmek. Çoğu zaman çalışır, ancak hala çalışmadığı bazı çok spesifik kamera konumları vardır. Özellikle bu nokta bir koordinatın çalıştığını ve diğerinin çalışmadığını gösterir (doğru konum sağ alt olmalıdır):
Ne zaman ters çevirme denedim:
Z
negatif (bu benim için en anlamlı olan şey)W
negatif (negatif W değerinin anlamını anlamıyorum)- Ya
Z
yaW
negatif (şu anda çoğu zaman ne çalışıyor) Z
veW
farklı işaretlere sahipler, aka:Z / W < 0
(bana mantıklı geliyor. yine de çalışmıyor)
Ancak yine de tüm noktalarımın doğru bir şekilde yansıtıldığı tutarlı bir yol bulamadık.
Herhangi bir fikir?