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;
        }
예제 #3
0
 public MyPlane(ref MyTriangle_Vertexes triangle)
 {
     Point = triangle.Vertex0;
     Normal = MyUtils.Normalize(Vector3.Cross((triangle.Vertex1 - triangle.Vertex0), (triangle.Vertex2 - triangle.Vertex0)));
 }
예제 #4
0
        /// <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();
            }
        }