public Ray GetMouseCursorRay(MouseState _CurrentMouseState, Matrix _projectionMatrix, Matrix _viewMatrix){ // Create 2 positions in screenspace using the cursor position. // 0 is as close as possible to the camera, 1 is as far away as possible. Vector3 nearSource = new Vector3(_CurrentMouseState.X, _CurrentMouseState.Y, 0.0f); Vector3 farSource = new Vector3(_CurrentMouseState.X, _CurrentMouseState.Y, 1.0f); // Use Viewport. Unproject to tell what those two screen space positions would be in world space. // We'll need the projection matrix and view matrix, which we have saved as member variables. // We also need a world matrix, which can just be identity. Vector3 nearPoint = _GraphicsDevice.Viewport.Unproject(nearSource, _projectionMatrix, _viewMatrix, Matrix.Identity); Vector3 farPoint = _GraphicsDevice.Viewport.Unproject(farSource, _projectionMatrix, _viewMatrix, Matrix.Identity); // Find the direction vector that goes from the nearPoint to the farPoint and normalize it... Vector3 direction = farPoint - nearPoint; direction.Normalize(); // ... and then create a new ray using nearPoint as the source. return new Ray(nearPoint, direction);}public bool PickedTriangle(Ray cursorRay, ref Vector3 intersection, ref float distance, ref int[] triangle){ float pickDist = 0.0f; // distance from ray origin to intersection float pickU = 0.0f; // barycentric coordinate of intersection float pickV = 0.0f; // barycentric coordinate of intersection for (int i = 0; i < (this._IndicesCount / 3); ++i) { // changed from left handed (DirectX) to right handed (XNA) Vector3 tri0 = this._transformedVertices[this._Indices[3 * i + 0]]; Vector3 tri1 = this._transformedVertices[this._Indices[3 * i + 2]]; Vector3 tri2 = this._transformedVertices[this._Indices[3 * i + 1]]; // Check if the pick ray passes through this point if (RayIntersectTriangle(cursorRay.Position, cursorRay.Direction, tri0, tri1, tri2, ref pickDist, ref pickU, ref pickV)) { if (pickDist > 0.0f) { intersection = pickU * tri1 + pickV * tri2 + (1 - pickU - pickV) * tri0; distance = pickDist; triangle[0] = 3 * i + 0; triangle[1] = 3 * i + 2; triangle[2] = 3 * i + 1; return true; } } } return false;}private bool RayIntersectTriangle(Vector3 rayPosition, Vector3 rayDirection, Vector3 tri0, Vector3 tri1, Vector3 tri2, ref float pickDistance, ref float barycentricU, ref float barycentricV){ // Find vectors for two edges sharing vert0 Vector3 edge1 = tri1 - tri0; Vector3 edge2 = tri2 - tri0; // Begin calculating determinant - also used to calculate barycentricU parameter Vector3 pvec = Vector3.Cross(rayDirection, edge2); // If determinant is near zero, ray lies in plane of triangle float det = Vector3.Dot(edge1, pvec); if (det < 0.0001f) return false; // Calculate distance from vert0 to ray origin Vector3 tvec = rayPosition - tri0; // Calculate barycentricU parameter and test bounds barycentricU = Vector3.Dot(tvec, pvec); if (barycentricU < 0.0f || barycentricU > det) return false; // Prepare to test barycentricV parameter Vector3 qvec = Vector3.Cross(tvec, edge1); // Calculate barycentricV parameter and test bounds barycentricV = Vector3.Dot(rayDirection, qvec); if (barycentricV < 0.0f || barycentricU + barycentricV > det) return false; // Calculate pickDistance, scale parameters, ray intersects triangle pickDistance = Vector3.Dot(edge2, qvec); float fInvDet = 1.0f / det; pickDistance *= fInvDet; barycentricU *= fInvDet; barycentricV *= fInvDet; return true;}