public MyIntersectionResultLineTriangle(ref MyTriangle_Vertexes triangle, ref MyTriangle_BoneWeigths? boneWeigths, ref Vector3 triangleNormal, double distance) { InputTriangle = triangle; InputTriangleNormal = triangleNormal; Distance = distance; BoneWeights = boneWeigths; }
/// <summary> /// Returns closest hit from line start position. /// </summary> public bool GetIntersectionWithLine(ref LineD line, ref MyCharacterHitInfo info, IntersectionFlags flags = IntersectionFlags.ALL_TRIANGLES) { // TODO: This now uses caspule of physics rigid body on the character, it needs to be changed to ragdoll // Currently this approach will be used to support Characters with different skeleton than humanoid if (info == null) info = new MyCharacterHitInfo(); info.Reset(); bool capsulesReady = UpdateCapsuleBones(); if (!capsulesReady) return false; double closestDistanceToHit = double.MaxValue; Vector3D hitPosition = Vector3D.Zero; Vector3D hitPosition2 = Vector3D.Zero; Vector3 hitNormal = Vector3.Zero; Vector3 hitNormal2 = Vector3.Zero; int capsuleIndex = -1; for (int i = 0; i < m_bodyCapsules.Length; i++) { CapsuleD capsule = m_bodyCapsules[i]; if (capsule.Intersect(line, ref hitPosition, ref hitPosition2, ref hitNormal, ref hitNormal2)) { double distanceToHit = Vector3.Distance(hitPosition, line.From); if (distanceToHit >= closestDistanceToHit) continue; closestDistanceToHit = distanceToHit; capsuleIndex = i; } } if (capsuleIndex != -1) { Matrix worldMatrix = PositionComp.WorldMatrix; int boneIndex = FindBestBone(capsuleIndex, ref hitPosition, ref worldMatrix); // Transform line to model static position and compute accurate collision there // 1. Transform line in local coordinates (used later) Matrix worldMatrixInv = PositionComp.WorldMatrixNormalizedInv; Vector3 fromTrans = Vector3.Transform(line.From, ref worldMatrixInv); Vector3 toTrans = Vector3.Transform(line.To, ref worldMatrixInv); LineD lineLocal = new LineD(fromTrans, toTrans); // 2. Transform line to to bone pose in binding position var bone = AnimationController.CharacterBones[boneIndex]; bone.ComputeAbsoluteTransform(); Matrix boneAbsTrans = bone.AbsoluteTransform; Matrix skinTransform = bone.SkinTransform; Matrix boneTrans = skinTransform * boneAbsTrans; Matrix invBoneTrans = Matrix.Invert(boneTrans); fromTrans = Vector3.Transform(fromTrans, ref invBoneTrans); toTrans = Vector3.Transform(toTrans, ref invBoneTrans); // 3. Move back line to world coordinates LineD lineTransWorld = new LineD(Vector3.Transform(fromTrans, ref worldMatrix), Vector3.Transform(toTrans, ref worldMatrix)); MyIntersectionResultLineTriangleEx? triangle_; bool success = base.GetIntersectionWithLine(ref lineTransWorld, out triangle_, flags); if (success) { MyIntersectionResultLineTriangleEx triangle = triangle_.Value; info.CapsuleIndex = capsuleIndex; info.BoneIndex = boneIndex; info.Capsule = m_bodyCapsules[info.CapsuleIndex]; info.HitHead = info.CapsuleIndex == 0 && m_bodyCapsules.Length > 1; info.HitPositionBindingPose = triangle.IntersectionPointInObjectSpace; info.HitNormalBindingPose = triangle.NormalInObjectSpace; // 4. Move intersection from binding to dynamic pose MyTriangle_Vertexes vertices = new MyTriangle_Vertexes(); vertices.Vertex0 = Vector3.Transform(triangle.Triangle.InputTriangle.Vertex0, ref boneTrans); vertices.Vertex1 = Vector3.Transform(triangle.Triangle.InputTriangle.Vertex1, ref boneTrans); vertices.Vertex2 = Vector3.Transform(triangle.Triangle.InputTriangle.Vertex2, ref boneTrans); Vector3 triangleNormal = Vector3.TransformNormal(triangle.Triangle.InputTriangleNormal, boneTrans); MyIntersectionResultLineTriangle triraw = new MyIntersectionResultLineTriangle(ref vertices, ref triangleNormal, triangle.Triangle.Distance); Vector3 intersectionLocal = Vector3.Transform(triangle.IntersectionPointInObjectSpace, ref boneTrans); Vector3 normalLocal = Vector3.TransformNormal(triangle.NormalInObjectSpace, boneTrans); // 5. Store results triangle = new MyIntersectionResultLineTriangleEx(); triangle.Triangle = triraw; triangle.IntersectionPointInObjectSpace = intersectionLocal; triangle.NormalInObjectSpace = normalLocal; triangle.IntersectionPointInWorldSpace = Vector3.Transform(intersectionLocal, ref worldMatrix); triangle.NormalInWorldSpace = Vector3.TransformNormal(normalLocal, worldMatrix); triangle.InputLineInObjectSpace = lineLocal; info.Triangle = triangle; if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW) { MyRenderProxy.DebugClearPersistentMessages(); MyRenderProxy.DebugDrawCapsule(info.Capsule.P0, info.Capsule.P1, info.Capsule.Radius, Color.Aqua, false, persistent: true); Vector3 p0Local = Vector3.Transform(info.Capsule.P0, ref worldMatrixInv); Vector3 p1Local = Vector3.Transform(info.Capsule.P1, ref worldMatrixInv); Vector3 p0LocalTrans = Vector3.Transform(p0Local, ref invBoneTrans); Vector3 p1LocalTrans = Vector3.Transform(p1Local, ref invBoneTrans); MyRenderProxy.DebugDrawCapsule(Vector3.Transform(p0LocalTrans, ref worldMatrix), Vector3.Transform(p1LocalTrans, ref worldMatrix), info.Capsule.Radius, Color.Brown, false, persistent: true); MyRenderProxy.DebugDrawLine3D(line.From, line.To, Color.Blue, Color.Red, false, true); MyRenderProxy.DebugDrawLine3D(lineTransWorld.From, lineTransWorld.To, Color.Green, Color.Yellow, false, true); MyRenderProxy.DebugDrawSphere(triangle.IntersectionPointInWorldSpace, 0.02f, Color.Red, 1, false, persistent: true); MyRenderProxy.DebugDrawAxis((MatrixD)boneTrans * WorldMatrix, 0.1f, false, true, true); } return true; } } return false; }
public MyPlane(ref MyTriangle_Vertexes triangle) { Point = triangle.Vertex0; Normal = MyUtils.Normalize(Vector3.Cross((triangle.Vertex1 - triangle.Vertex0), (triangle.Vertex2 - triangle.Vertex0))); }
/// <summary> /// Returns closest hit from line start position. /// </summary> public bool GetIntersectionWithLine(ref LineD line, out VRage.Game.Models.MyIntersectionResultLineTriangleEx? t, out bool hitHead) { // TODO: This now uses caspule of physics rigid body on the character, it needs to be changed to ragdoll // Currently this approach will be used to support Characters with different skeleton than humanoid t = null; hitHead = false; if (!m_characterBoneCapsulesReady) UpdateCapsuleBones(); if (!m_characterBoneCapsulesReady) return false; double closestDistanceToHit = double.MaxValue; int hitCapsule = -1; m_hitCapsule = null; m_hitInfo = null; Vector3D hitPosition = Vector3D.Zero; Vector3D hitPosition2 = Vector3D.Zero; Vector3 hitNormal = Vector3.Zero; Vector3 hitNormal2 = Vector3.Zero; for (int i = 0; i < m_bodyCapsules.Length; i++) { CapsuleD capsule = m_bodyCapsules[i]; //if (capsule.IsIntersected(line, out hitVector, out hitVector2, out hitVector3)) if (capsule.Intersect(line, ref hitPosition, ref hitPosition2, ref hitNormal, ref hitNormal2)) { double distanceToHit = Vector3.Distance(hitPosition, line.From); if (distanceToHit >= closestDistanceToHit) continue; closestDistanceToHit = distanceToHit; hitCapsule = i; MyTriangle_Vertexes vertexes = new MyTriangle_Vertexes(); //TODO: Make correct alg. to make triangle from capsule intersection vertexes.Vertex0 = hitPosition + line.Direction * 0.5f; vertexes.Vertex1 = hitPosition + hitNormal * 0.5f; vertexes.Vertex2 = hitPosition - hitNormal * 0.8f; t = new VRage.Game.Models.MyIntersectionResultLineTriangleEx( new VRage.Game.Models.MyIntersectionResultLineTriangle( ref vertexes, ref hitNormal, Vector3.Distance(hitPosition, line.From)), this, ref line, (Vector3D)hitPosition, hitNormal); } } if (t != null) { hitHead = hitCapsule == 0 && m_bodyCapsules.Length > 1; m_hitCapsule = m_bodyCapsules[hitCapsule]; m_hitInfo = t; if (MyDebugDrawSettings.ENABLE_DEBUG_DRAW) { CapsuleD capsule = m_bodyCapsules[hitCapsule]; MyRenderProxy.DebugDrawCapsule(capsule.P0, capsule.P1, capsule.Radius, Color.Red, false, false); MyRenderProxy.DebugDrawSphere(hitPosition, 0.1f, Color.White, 1f, false); } return true; } return false; }
public void GetTrianglesIntersectingAABB(ref BoundingBoxD aabb, List<MyTriangle_Vertex_Normal> retTriangles, int maxNeighbourTriangles) { BoundingBox boxF = (BoundingBox)aabb; IndexedVector3 min = boxF.Min.ToBullet(); IndexedVector3 max = boxF.Max.ToBullet(); AABB gi_aabb = new AABB(ref min, ref max); m_overlappedTriangles.Clear(); VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("m_bvh.BoxQuery"); bool res = m_bvh.BoxQuery(ref gi_aabb, m_overlappedTriangles); VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); if (res) { VRageRender.MyRenderProxy.GetRenderProfiler().StartProfilingBlock("m_overlappedTriangles"); //foreach (var triangleIndex in m_overlappedTriangles) for (int i = 0; i < m_overlappedTriangles.Count; i++) { var triangleIndex = m_overlappedTriangles[i]; // If we reached end of the buffer of neighbour triangles, we stop adding new ones. This is better behavior than throwing exception because of array overflow. if (retTriangles.Count == maxNeighbourTriangles) { VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); return; } MyTriangleVertexIndices triangle = m_model.Triangles[triangleIndex]; MyTriangle_Vertexes triangleVertices = new MyTriangle_Vertexes(); m_model.GetVertex(triangle.I0, triangle.I1, triangle.I2, out triangleVertices.Vertex0, out triangleVertices.Vertex1, out triangleVertices.Vertex2); IndexedVector3 iv0 = triangleVertices.Vertex0.ToBullet(); IndexedVector3 iv1 = triangleVertices.Vertex1.ToBullet(); IndexedVector3 iv2 = triangleVertices.Vertex2.ToBullet(); MyTriangle_Vertex_Normal retTriangle; retTriangle.Vertexes = triangleVertices; retTriangle.Normal = Vector3.Forward; retTriangles.Add(retTriangle); } VRageRender.MyRenderProxy.GetRenderProfiler().EndProfilingBlock(); } }