コード例 #1
0
ファイル: Convex.cs プロジェクト: suzuke/ode.net
 private Convex(Space space, ConvexData data)
     : base(NativeMethods.dCreateConvex(space != null ? space.Id : dSpaceID.Null,
                                        data._planes, data._planeCount,
                                        data._points, data._pointCount,
                                        data._polygons))
 {
     this.data = data;
 }
コード例 #2
0
    void OnGUI()
    {
        GUILayout.BeginVertical();

        cc = EditorGUILayout.ObjectField("凸包文件:", cc, typeof(ConvexCollection)) as ConvexCollection;

        if (GUILayout.Button("创建Convexdatas"))
        {
            cc = ScriptableObject.CreateInstance <ConvexCollection>();
            AssetDatabase.CreateAsset(cc, "Assets/Resources/ConvexDataCollection.asset");
            AssetDatabase.SaveAssets();
        }

        if (GUILayout.Button("创建Convex"))
        {
            GameObject cur = Selection.activeGameObject;
            if (cur != null)
            {
                Mesh m = cur.GetComponent <MeshFilter>().sharedMesh;
                if (m != null)
                {
                    ConvexData cd = new ConvexData();
                    if (ConvexUtil.MakeHull(m, cur.transform, "", ref cd))
                    {
                        cc.ConvexDatas.Add(cd);
                    }
                }
            }
        }

        if (GUILayout.Button("从文件添加凸包"))
        {
            LEditTextFile tf = new LEditTextFile();
            tf.OpenRead("convex.txt");

            ConvexData cd = new ConvexData();
            cd.EditLoad(tf);
            cc.ConvexDatas.Add(cd);

            tf.Close();
        }

        if (GUILayout.Button("显示凸包"))
        {
            cc.DebugRender(debugShow);
            debugShow = !debugShow;
        }

        if (GUILayout.Button("保存"))
        {
            AssetDatabase.DeleteAsset("Assets/Resources/ConvexDataCollection.asset");
            AssetDatabase.CreateAsset(cc, "Assets/Resources/ConvexDataCollection.asset");

            AssetDatabase.SaveAssets();
        }
    }
コード例 #3
0
ファイル: Convex.cs プロジェクト: suzuke/ode.net
        /// <summary>
        /// Sets the convex hull data.
        /// </summary>
        /// <param name="planes">
        /// The planes' definition array. Each polygon in the convex hull will be
        /// attached to one of these planes. Each plane is defined by a quadruplet
        /// of the a, b, c and d parameters of the plane equation.
        /// </param>
        /// <param name="points">
        /// The array of points, aligned in triplets of x, y and z components.
        /// </param>
        /// <param name="polygons">
        /// The polygons' definition array. Each element in the array is an index
        /// to a previously defined point in the array of point triplets.
        /// Each polygon definition sequence begins and ends in the same point.
        /// There must be as many polygon definition sequences as the number of planes.
        /// </param>
        public void SetConvex(dReal[] planes, dReal[] points, int[] polygons)
        {
            if (data != null)
            {
                data.Dispose();
            }

            data = new ConvexData(planes, points, polygons);
            NativeMethods.dGeomSetConvex(Id, data._planes, data._planeCount,
                                         data._points, data._pointCount,
                                         data._polygons);
        }
コード例 #4
0
ファイル: Convex.cs プロジェクト: suzuke/ode.net
        /// <summary>
        /// Releases the unmanaged resources used by the <see cref="Convex"/> class
        /// specifying whether to perform a normal dispose operation.
        /// </summary>
        /// <param name="disposing">
        /// <b>true</b> for a normal dispose operation; <b>false</b> to finalize
        /// the geom.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (data != null)
            {
                if (disposing)
                {
                    data.Dispose();
                    data = null;
                }
            }

            base.Dispose(disposing);
        }
コード例 #5
0
    public void Set(ConvexData src)
    {
        Reset();
        int i;

        for (i = 0; i < src.GetVertexNum(); i++)
        {
            AddVertex(src.mLstVertices[i]);
        }
        for (i = 0; i < src.GetFaceNum(); i++)
        {
            AddFace(src.mLstCovFace[i]);
        }

        Flags = src.Flags;
        mAABB = src.mAABB;
    }
コード例 #6
0
    //导出数据到ConvexData中
    public void ExportCHData(ConvexData chData)
    {
        List <int> lstMap = new List <int>();           //一个由顶点在本类中id到CConvexHullData中id的一个映射表;

        //遍历每一个Patch
        for (int i = 0; i < LstPatches.Count; i++)
        {
            Patch   pat  = LstPatches[i];
            Vector3 n    = pat.Normal;
            CovFace face = new CovFace();
            face.Normal = n;
            face.Dist   = pat.Dist;

            for (int j = 0; j < pat.GetVNum(); j++)
            {
                int vid = pat.GetVID(j);

                //构造垂直于该边法向朝外的HalfSpace
                Vector3 v1 = Vector3.zero;
                Vector3 v2 = Vector3.zero;
                pat.GetEdge(j, ref v1, ref v2);
                int ExistID = FindInArray(vid, lstMap);
                if (ExistID == -1)
                {
                    //说明是新的顶点

                    //插入到CConvexHullData的Vertices中
                    chData.AddVertex(v1);
                    int newID = chData.GetVertexNum() - 1;      //在pCHData中的id
                    face.AddElement(newID);

                    lstMap.Add(vid);
                }
                else
                {
                    //说明是已经存在的顶点
                    face.AddElement(ExistID);
                }
            }

            //插入该面片
            chData.AddFace(face);
        }
    }
コード例 #7
0
ファイル: GJKRaycast.cs プロジェクト: liuxq/GJKLearn
    static Vector3 getClosestPoint(Vector3 closest, int size, ConvexData convex)
    {
        Vector3 closestB = Vector3.zero;

        switch (size)
        {
        case 1:
        {
            closestB = convex.GetVertex(B[0]);
            break;
        }

        case 2:
        {
            float   v  = 0;
            Vector3 B0 = convex.GetVertex(B[0]);
            Vector3 B1 = convex.GetVertex(B[1]);
            barycentricCoordinates(closest, Q[0], Q[1], ref v);
            Vector3 bv = B1 - B0;
            closestB = bv * v + B0;

            break;
        }

        case 3:
        {
            //calculate the Barycentric of closest point p in the mincowsky sum
            float   v = 0, w = 0;
            Vector3 B0 = convex.GetVertex(B[0]);
            Vector3 B1 = convex.GetVertex(B[1]);
            Vector3 B2 = convex.GetVertex(B[2]);
            barycentricCoordinates(closest, Q[0], Q[1], Q[2], ref v, ref w);
            Vector3 bv0 = B1 - B0;
            Vector3 bv1 = B2 - B0;
            closestB = B0 + bv0 * v + bv1 * w;
            break;
        }
        }
        return(closestB);
    }
コード例 #8
0
 public ConvexData(ConvexData chData)
 {
     Set(chData);
 }
コード例 #9
0
ファイル: ConvexUtil.cs プロジェクト: liuxq/GJKLearn
    public static bool MakeHull(Mesh mesh, Transform tr, string path, ref ConvexData data)
    {
        GiftWrap gw = new GiftWrap();

        gw.Reset();

        List <Vector3> vecVertex = new List <Vector3>();
        Vector3        vmin      = Vector3.zero;
        Vector3        vmax      = Vector3.zero;

        Bounds bound = mesh.bounds;

        vmin = bound.min;
        vmax = bound.max;

        Vector3[] verts = mesh.vertices;
        for (int j = 0; j < mesh.vertexCount; ++j)
        {
            Vector3 wp = verts[j];
            if (null != tr)
            {
                wp = tr.TransformPoint(wp);
            }
            bool bnear = false;
            for (int k = 0; k < (int)vecVertex.Count; k++)
            {
                if ((wp - vecVertex[k]).magnitude < CLOSE_VERTEX_DISTANCE_THRESH)
                {
                    bnear = true;
                    break;
                }
            }
            if (!bnear)
            {
                vecVertex.Add(wp);
            }
        }

        int numallvert = vecVertex.Count;

        gw.SetVertexes(vecVertex);
        gw.ComputeConvexHull();

        path += "/" + System.DateTime.Now.ToString("dd-MM-yy-HH-mm-ss") + "_vts.txt";
        if (gw.ExceptionOccur())
        {
            gw.SaveVerticesToFile(path);
            gw.Reset();
            return(false);
        }

        ConvexPolytope cp = new ConvexPolytope();

        cp.Init(gw, (vmax - vmin).magnitude);

        if (cp.ExceptionOccur && cp.MinPatchNum > 20)
        {
            gw.SaveVerticesToFile(path);
            return(false);
        }

        int patchnum = Mathf.Min(cp.OriginPatchNum, Mathf.Max(10, cp.MinPatchNum));

        if (patchnum > MAX_FACE_IN_HULL)
        {
            gw.Reset();
            return(false);
        }
        else
        {
            cp.Goto(Mathf.Min(patchnum, MAX_FACE_IN_HULL));
        }

        gw.Reset();

        data.Reset();
        cp.ExportCHData(data);

        return(true);
    }
コード例 #10
0
ファイル: GJKRaycast.cs プロジェクト: liuxq/GJKLearn
    static float GJK_RELATIVE_EPSILON = 0.0004f;    //square of 2%.
    //ML: if we are using gjk local which means one of the object will be sphere/capsule, in that case, if we define takeCoreShape is true, we just need to return the closest point as the sphere center or a point in the capsule segment. This will increase the stability
    //for the manifold recycling code
    public static GJKType GjkLocalPenetration_CapsuleConvex(CAPSULE a, ConvexData b, ref Vector3 normal, ref float penetrationDepth, ref CollidePoints points, ref Vector3 closeB)
    {
        float marginA = a.getMargin();
        float marginB = 0;    //b.getMargin();

        //float minMargin = 0;// Mathf.Min(a.getMinMargin(), b.getMinMargin());
        //float _eps2 = (minMargin * (0.1f));
        //ML: eps2 is the threshold that uses to detemine whether two (shrunk) shapes overlap. We calculate eps2 based on 10% of the minimum margin of two shapes
        float eps2 = 0;    // (_eps2 * _eps2);
        //ML: epsRel2 is the square of 1.5%. This is used to scale the the sqaure distance of a closet point to origin to detemine whether two shrunk shapes overlap in the margin, but
        //they don't overlap.
        float epsRel2 = GJK_RELATIVE_EPSILON;

        float sumOrignalMargin = marginA + marginB;

        float sDist   = float.MaxValue;
        float minDist = sDist;

        bool    bNotTerminated = true;
        bool    bCon           = true;
        Vector3 closest;

        Vector3 supportA = Vector3.zero, supportB = Vector3.zero, support = Vector3.zero;

        int size = 0;

        Vector3 _initialSearchDir = a.Center - b.GetAABB().center;

        closest = Vector3.Dot(_initialSearchDir, _initialSearchDir) > 0 ? _initialSearchDir : Vector3.right;

        Vector3 prevClosest = closest;

        int bIndex = 0;

        // ML : termination condition
        //(1)two (shrunk)shapes overlap. GJK will terminate based on sq(v) < eps2 and indicate that two shapes are overlapping.
        //(2)two (shrunk + margin)shapes separate. If sq(vw) > sqMargin * sq(v), which means the original objects do not intesect, GJK terminate with GJK_NON_INTERSECT.
        //(3)two (shrunk) shapes don't overlap. However, they interect within margin distance. if sq(v)- vw < epsRel2*sq(v), this means the shrunk shapes interect in the margin,
        //   GJK terminate with GJK_CONTACT.
        while (bNotTerminated)
        {
            //minDist, tempClosA, tempClosB are used to store the previous iteration's closest points(in A and B space) and the square distance from the closest point
            //to origin in Mincowski space
            minDist     = sDist;
            prevClosest = closest;

            supportA = a.supportSweepLocal(-closest);
            supportB = b.supportSweepLocal(closest, ref bIndex);

            //calculate the support point
            support = supportA - supportB;
            Q[size] = support;
            B[size] = bIndex;

            //ML: because we shrink the shapes by plane shifting(box and convexhull), the distance from the "shrunk" vertices to the original vertices may be larger than contact distance.
            //therefore, we need to take the largest of these 2 values into account so that we don't incorrectly declare shapes to be disjoint. If we don't do this, there is
            //an inherent inconsistency between fallback SAT tests and GJK tests that may result in popping due to SAT discovering deep penetrations that were not detected by
            //GJK operating on a shrunk shape.
            float sqMargin = (sumOrignalMargin * sumOrignalMargin);

            float vw = Vector3.Dot(closest, support);

            bool con          = (vw > 0) && (vw * vw > sDist * sqMargin); //this is the non intersect condition
            bool conGrtr      = (epsRel2 * sDist) >= (sDist - vw);        //this is the margin intersect condition
            bool conOrconGrtr = con || conGrtr;

            if (conOrconGrtr)
            {
                if (!con)     //must be true otherwise we wouldn't be in here...
                {
                    float dist = Mathf.Sqrt(sDist);
                    //PX_ASSERT(FAllGrtr(dist, FEps));
                    Vector3 n = closest / dist;    //normalise
                    normal = n;

                    closeB = getClosestPoint(closest, size, b);

                    penetrationDepth = dist - sumOrignalMargin;

                    points.size = size;
                    points.a    = B[0];
                    points.b    = B[1];
                    points.c    = B[2];

                    return(GJKType.GJK_CONTACT);
                }
                else
                {
                    return(GJKType.GJK_NON_INTERSECT);
                }
            }

            size++;
            //PX_ASSERT(size <= 4);

            //calculate the closest point between two convex hull
            closest = GJKCPairDoSimplex(support, ref size);

            sDist = Vector3.Dot(closest, closest);

            bCon           = minDist > sDist;
            bNotTerminated = sDist > eps2 && bCon;
        }

        if (!bCon)
        {
            sDist = minDist;

            float sqExpandedMargin = sumOrignalMargin * sumOrignalMargin;
            //Reset back to older closest point
            closest = prevClosest;

            closeB = getClosestPoint(closest, size, b);

            sDist = minDist;

            float dist = Mathf.Sqrt(sDist);
            //PX_ASSERT(dist > FEps);
            Vector3 n = closest / dist;    //normalise

            penetrationDepth = dist - sumOrignalMargin;

            normal = n;

            points.size = size;
            points.a    = B[0];
            points.b    = B[1];
            points.c    = B[2];

            if (sqExpandedMargin >= sDist)
            {
                return(GJKType.GJK_CONTACT);
            }

            //此时明明没有碰撞,但是误差导致的碰撞,向法线方向移动0.001f
            //penetrationDepth = -0.001f;
            return(GJKType.GJK_DEGENERATE);
        }
        else
        {
            //this two shapes are deeply intersected with each other, we need to use EPA algorithm to calculate MTD
            return(GJKType.EPA_CONTACT);
        }
    }
コード例 #11
0
ファイル: GJKRaycast.cs プロジェクト: liuxq/GJKLearn
    static public bool GjkLocalRayCast_CapsuleConvex(CAPSULE a, ConvexData b, Vector3 r, ref float lambda, ref Vector3 normal, ref bool StartSolid, ref CollidePoints points, ref Vector3 closeB)
    {
        if (b.GetVertexNum() == 0)
        {
            return(false);
        }

        bool  _StartSolid = true;
        float inflation   = a.Radius;
        float maxDist     = float.MaxValue;

        float _lambda = 0;

        r = -r;
        Vector3 x    = r * _lambda;
        int     size = 1;

        Vector3 dir = a.Center - b.GetAABB().center;
        Vector3 _initialSearchDir = (Vector3.Dot(dir, dir) > FEps) ? dir : Vector3.right;
        Vector3 initialSearchDir  = Vector3.Normalize(_initialSearchDir);

        int     bIndex          = 0;
        Vector3 initialSupportA = a.supportSweepLocal(-initialSearchDir);
        Vector3 initialSupportB = b.supportSweepLocal(initialSearchDir, ref bIndex);

        Q[0] = initialSupportA - initialSupportB; Q[1] = Vector3.zero; Q[2] = Vector3.zero; Q[3] = Vector3.zero; //simplex set
        B[0] = bIndex; B[1] = 0; B[2] = 0; B[3] = 0;                                                             //ConvexHull b simplex set

        Vector3 closest  = Q[0];
        Vector3 supportA = initialSupportA;
        Vector3 supportB = initialSupportB;
        Vector3 support  = Q[0];

        //float minMargin = Mathf.Min(a.getSweepMargin(), b.getSweepMargin());
        float eps1             = 0;//minMargin * 0.1f;
        float inflationPlusEps = eps1 + inflation;
        float eps2             = eps1 * eps1;

        float inflation2 = inflationPlusEps * inflationPlusEps;

        float sDist   = Vector3.Dot(closest, closest);
        float minDist = sDist;

        bool bNotTerminated = sDist > eps2;
        bool bCon           = true;

        Vector3 nor         = closest;
        Vector3 prevClosest = closest;

        while (bNotTerminated == true)
        {
            minDist     = sDist;
            prevClosest = closest;

            Vector3 vNorm = -Vector3.Normalize(closest);

            supportA = a.supportSweepLocal(vNorm);
            supportB = x + b.supportSweepLocal(-vNorm, ref bIndex);

            //calculate the support point
            support = supportA - supportB;
            Vector3 w  = -support;
            float   vw = Vector3.Dot(vNorm, w) - inflationPlusEps;
            float   vr = Vector3.Dot(vNorm, r);
            if (vw > 0)
            {
                if (vr >= 0)
                {
                    return(false);
                }
                else
                {
                    _StartSolid = false;
                    float _oldLambda = _lambda;
                    _lambda = _lambda - vw / vr;
                    if (_lambda > _oldLambda)
                    {
                        if (_lambda > 1)
                        {
                            return(false);
                        }
                        Vector3 bPreCenter = x;
                        x = r * _lambda;

                        Vector3 offSet = x - bPreCenter;
                        Q[0] -= offSet;
                        Q[1] -= offSet;
                        Q[2] -= offSet;

                        supportB += offSet;
                        support   = supportA - supportB;
                        minDist   = maxDist;
                        nor       = closest;
                        //size=0;
                    }
                }
            }

            //ASSERT(size < 4); lxq test
            B[size]   = bIndex;
            Q[size++] = support;

            //calculate the closest point between two convex hull
            closest = GJKCPairDoSimplex(support, ref size);
            sDist   = Vector3.Dot(closest, closest);

            bCon           = minDist > sDist;
            bNotTerminated = (sDist > inflation2) && bCon;
        }

        //bool aQuadratic = a.isMarginEqRadius();
        //ML:if the Minkowski sum of two objects are too close to the original(eps2 > sDist), we can't take v because we will lose lots of precision. Therefore, we will take
        //previous configuration's normal which should give us a reasonable approximation. This effectively means that, when we do a sweep with inflation, we always keep v because
        //the shapes converge separated. If we do a sweep without inflation, we will usually use the previous configuration's normal.
        nor    = ((sDist > eps2) && bCon) ? closest : nor;
        nor    = Vector3.Normalize(nor);
        normal = nor;

        lambda = _lambda;
        //float cosAngle = Vector3.Dot(nor, r);
        //float offset = 0.001f / cosAngle;
        //lambda -= offset;
        if (lambda < 0)
        {
            //lambda *= cosAngle;
            lambda = 0;
        }

        points.size = size;
        points.a    = B[0];
        points.b    = B[1];
        points.c    = B[2];

        Vector3 closestP = bCon? closest: prevClosest;

        closeB = getClosestPoint(closestP, size, b);
        //closestA = V3Sel(aQuadratic, V3NegScaleSub(nor, a.getMargin(), closA), closA);

        StartSolid = false;
        if (_StartSolid)
        {
            GJKType ret = GjkLocalPenetration_CapsuleConvex(a, b, ref normal, ref lambda, ref points, ref closeB);
            if (ret == GJKType.EPA_CONTACT)
            {
                StartSolid = true;
            }
            else
            {
                if (lambda > 0)
                {
                    lambda = 0;
                }
            }
        }

        return(true);
    }