Game Development Community

Non-convex collision

by Dan Keller · in Torque Game Engine · 12/13/2007 (5:24 pm) · 12 replies

I'm making a procedurally generated road object that uses three triangle strips side by side. For obvious reasons, a convex collision hull won't work. How can I make players, vehicles, etc correctly collide with it?

#1
12/13/2007 (5:29 pm)
You may have more then 1 collision mesh in your shape file (I think a max of 32 but I can be wrong). Try making a few to make it accurate.
#2
12/14/2007 (7:21 am)
You could implement the polysoup resource.

EDIT:
I believe the 32 collision box limit has been out of the engine for some time, but some exporters may still have that set as the max.
#3
12/14/2007 (11:06 am)
It isn't a dts, it's just a bunch of triangles generated in real-time by the engine.
#4
12/14/2007 (11:09 am)
Ah, yes. I missed the procedural generation. I have no idea if the polysoup resource would help, but you could take a look at it and the associated code to see if you could tie it in to your algorithm.
#5
12/14/2007 (8:07 pm)
I don't know if it would be worth implementing opcode just for this, but what about a terrain-like collision system? Unfortunately, collision is one thing I know almost nothing about. Can someone point me in the right direction?
#6
12/14/2007 (8:11 pm)
Ahh a DIF file, well I guess that polysoup resource would be pretty good if you implement the correct parts.
#7
12/14/2007 (8:31 pm)
Lol, Its not a DIF either. Its made in code.

Are you generating a Shape or are you just creating triangles and drawing them yourself?

Opcode should be pretty easy to implement. If you fit within the free licensing I would say go for it.

I don't see why convex collision wont work though. The TerrainBlock uses it to provide collision information though I don't know how it works at all. Last time I checked you could make a concave terrain :) Maybe someone else will speak up and tell us all the wisdom of the Torque Collision System.
#8
12/14/2007 (8:41 pm)
Ok, this might clarify what I'm looking at here. It's not convex or even closed, it's just 3 triangle strips with a total of about 600 polygons:
66.49.245.246/road.jpg
#9
12/14/2007 (9:11 pm)
If you look at your terrain you notice it isn't convex either (see the hill?).

It still uses the same collision system though (Convex).
#10
12/15/2007 (5:28 pm)
It seems that the terrain uses a different convex object for every polygon. That's probably the best way to do this.
#11
12/20/2007 (5:04 am)
What I have now is: (it doesn't work by the way)
Box3F RoadConvex::getBoundingBox() const
{
	return box;
}

Box3F RoadConvex::getBoundingBox(const MatrixF& mat, const Point3F& scale) const
{
	Box3F newBox = box;
	newBox.min.convolve(scale);
	newBox.max.convolve(scale);
	mat.mul(newBox);
	return newBox;
}

Point3F RoadConvex::support(const VectorF& v) const
{
	Point3F ret(0.0f, 0.0f, 0.0f);
	F32 dp = 0.0f;
	F32 tp = 0.0f;

	// Loop through the points and save the furthest one
	for (U32 i = 0; i < 2; i++)
	{
		tp = mDot(v, verts[i]);
		if (tp > dp)
		{
			dp = tp;
			ret = verts[i];
		}
	}

	return ret;
}

void RoadConvex::getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf)
{
	// Fill in a few details
	cf->material = 0;          // Not really used by anything we are interested in for now
	cf->object   = mObject;    // Give it a pointer to our parent object

	// Get the starting offset
   // We can't assume that the vertexlist is empty
	S32 base = cf->mVertexList.size();

	// Insert the vertices
	cf->mVertexList.increment();
	mat.mulP(verts[0], &cf->mVertexList.last());
	cf->mVertexList.increment();
	mat.mulP(verts[1], &cf->mVertexList.last());
	cf->mVertexList.increment();
	mat.mulP(verts[2], &cf->mVertexList.last());


    cf->mEdgeList.increment();
    cf->mEdgeList.last().vertex[0] = base;
    cf->mEdgeList.last().vertex[1] = base+1;
    cf->mEdgeList.increment();
    cf->mEdgeList.last().vertex[0] = base+1;
    cf->mEdgeList.last().vertex[1] = base+2;
    cf->mEdgeList.increment();
    cf->mEdgeList.last().vertex[0] = base+2;
    cf->mEdgeList.last().vertex[1] = base;


    PlaneF plane(verts[0], verts[1], verts[2]);

	cf->mFaceList.increment();
    mat.mulV(plane, &cf->mFaceList.last().normal);
	cf->mFaceList.last().vertex[0] = base;
	cf->mFaceList.last().vertex[1] = base+1;
	cf->mFaceList.last().vertex[2] = base+2;
}


void RoadConvex::getPolyList(AbstractPolyList* list)
{
	// Be sure to transform the list into model space
	list->setTransform(&mObject->getTransform(), mObject->getScale());
   // Set the object
	list->setObject(mObject);

	// First add the first point and get the starting offset for these points in the list
	int base = list->addPoint(verts[0]);
	list->addPoint(verts[1]);
	list->addPoint(verts[2]);

    list->begin(0, 0);
        list->vertex(base);
        list->vertex(base + 1);
        list->vertex(base + 2);
        list->plane(base, base+1, base+2);
    list->end();

}

void fxRoad::buildConvex(const Box3F& box, Convex* convex)
{
    if (numverts < 3)
        return; //dont go there

    Box3F osBox = box;
    mWorldToObj.mul(osBox);

    Point3F a, b, c;

    for (int i = 0; i<numverts-2; i++)
    {
        a = verts[i];
        b = verts[i+1];
        c = verts[i+2];
        //if (triBoxOverlap(osBox, verts[i], verts[i+1], verts[i+2]))
        //{
            createConvex(a, b, c, convex, i);
        //}

    }
}

void fxRoad::createConvex(Point3F a, Point3F b, Point3F c, Convex* convex, U32 face)
{
    // See if this convex already exists
    Convex* cc = 0;
    CollisionWorkingList& wl = convex->getWorkingList();
    CollisionWorkingList* itr;
    for (itr = wl.wLink.mNext; itr != &wl; itr = itr->wLink.mNext)
    {
	    if (itr->mConvex->getType() == RoadConvexType &&
	    static_cast<RoadConvex*>(itr->mConvex)->getObject() == this &&
        static_cast<RoadConvex*>(itr->mConvex)->getFace() == face)
        {
	        cc = itr->mConvex;
	        break;
        }
    }

    if (cc)
    {
       // Already exists...don't do anything
    }
    else
    {
        // Got ourselves a new convex
        RoadConvex* cp = new RoadConvex(a, b, c);
        convex->addToWorkingList(cp);
        cp->mObject = this;

        // Give it a pointer to the "owner" object and set the bounding box
        cp->pOwner = this;
        cp->box = mObjBox;
        cp->setFace(face);
    }
}

bool fxRoad::testTri(const Point3F& start, const Point3F& end, const Point3F a, const Point3F b, const Point3F c, F32& d)
{
    PlaneF tri(a, b, c);
    F32 intersect = tri.intersect(start, end);
    F32 farpt = getMax((c - start).len(), getMax((a - start).len(), (b - start).len()));
    if (intersect >= 0.0f  && intersect <= farpt && intersect <= (end - start).len()) {
        d = intersect;
        return true;
    }
    else
        return false;
}

bool fxRoad::castRay(const Point3F& start, const Point3F& end, RayInfo* info)
{

    if (numverts < 3)
        return false; //dont go there

    if (end == start)
        return false; //wtflol

    F32 min = PARALLEL_PLANE;
    F32 cur;
    Point2F b;
    bool found = false;
    int finalI;
    for (int i = 0; i < numverts-2; i++)
    {
        found = castRayTriangle(start, end, verts[i], verts[i+1], verts[i+2], cur, b);
        if (cur < min && found) {
            min = cur;
            finalI = i;
        }
    }

    if (found)
    {
        info->t = min; //(end - start).len();
        info->normal = PlaneF(verts[finalI], verts[finalI+1], verts[finalI+2]);
        info->point.interpolate(start, end, info->t);
        info->face = -1;
        info->object = this;

        return true;
    }

    return false;
}

A lot of places aren't clear weather they have to be in object space or world space.
#12
12/20/2007 (6:32 am)
Have you reviewed the Collision article on TDN?

It gives notes as to which space some things should be in. I'm not sure how in depth it is. I'm very interested in finding out how this part of Torque works. It has eluded me so far.