protected override void OnMouseDown(MouseEventArgs e) { if (e.Button == MouseButtons.Left) { // Try to do gizmo picking if (DrawGizmo) { var result = _gizmo.DoPicking(GetRay(e.X, e.Y)); if (result != null) { _gizmo.ActivateGizmo(result); Invalidate(); return; } } // Try to do node picking WadMeshBoneNode foundNode = null; foreach (var node in Skeleton) { float distance = 0; float minDistance = float.PositiveInfinity; if (DoNodePicking(GetRay(e.X, e.Y), node, out distance)) { if (distance < minDistance) { distance = minDistance; foundNode = node; } } } SelectedNode = foundNode; } Invalidate(); _lastX = e.X; _lastY = e.Y; base.OnMouseDown(e); }
private bool DoNodePicking(Ray ray, WadMeshBoneNode node, out float nodeDistance) { nodeDistance = 0; // Transform view ray to object space space Matrix4x4 inverseObjectMatrix; if (!Matrix4x4.Invert(node.GlobalTransform, out inverseObjectMatrix)) { return(false); } Vector3 transformedRayPos = MathC.HomogenousTransform(ray.Position, inverseObjectMatrix); Vector3 transformedRayDestination = MathC.HomogenousTransform(ray.Position + ray.Direction, inverseObjectMatrix); Ray transformedRay = new Ray(transformedRayPos, transformedRayDestination - transformedRayPos); transformedRay.Direction = Vector3.Normalize(transformedRay.Direction); // Now do a ray - triangle intersection test bool hit = false; float minDistance = float.PositiveInfinity; var mesh = node.WadMesh; foreach (var poly in mesh.Polys) { if (poly.Shape == WadPolygonShape.Quad) { Vector3 p1 = mesh.VerticesPositions[poly.Index0]; Vector3 p2 = mesh.VerticesPositions[poly.Index1]; Vector3 p3 = mesh.VerticesPositions[poly.Index2]; Vector3 p4 = mesh.VerticesPositions[poly.Index3]; float distance; if (Collision.RayIntersectsTriangle(transformedRay, p1, p2, p3, out distance) && distance < minDistance) { minDistance = distance; hit = true; } if (Collision.RayIntersectsTriangle(transformedRay, p1, p3, p4, out distance) && distance < minDistance) { minDistance = distance; hit = true; } } else { Vector3 p1 = mesh.VerticesPositions[poly.Index0]; Vector3 p2 = mesh.VerticesPositions[poly.Index1]; Vector3 p3 = mesh.VerticesPositions[poly.Index2]; float distance; if (Collision.RayIntersectsTriangle(transformedRay, p1, p2, p3, out distance) && distance < minDistance) { minDistance = distance; hit = true; } } } /* * _wadRenderer.Dispose(); * foreach (var submesh in node.Bone.Children.Select(bone => bone.Mesh)) * for (int k = 0; k < submesh.Value.Indices.Count; k += 3) * { * var mesh = _wadRenderer.GetStatic(new WadStatic(new WadStaticId(0)) { Mesh = node.WadMesh }); * * Vector3 p1 = mesh.Vertices[submesh.Value.Indices[k]].Position; * Vector3 p2 = mesh.Vertices[submesh.Value.Indices[k + 1]].Position; * Vector3 p3 = mesh.Vertices[submesh.Value.Indices[k + 2]].Position; * * float distance; * if (Collision.RayIntersectsTriangle(transformedRay, p1, p2, p3, out distance) && distance < minDistance) * { * minDistance = distance; * hit = true; * } * }*/ // TODO Avoid using the renderer for pickingData transforms need to be available in wad mesh without rendering. int TODO_DoNodePicking; if (hit) { nodeDistance = minDistance; return(true); } else { return(false); } }