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?
About the author
Recent Threads
#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
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.
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:
#9
It still uses the same collision system though (Convex).
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
A lot of places aren't clear weather they have to be in object space or world space.
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.
Torque Owner Tyler Slabinski