[...] Bunch of collision work, pretty much broke planet landing and some

other stuff. Don't worry about it.
This commit is contained in:
Rtch90 2018-03-17 18:41:12 +00:00
parent a9c2abdb71
commit 9e6b365f9d
12 changed files with 116 additions and 30 deletions

View File

@ -12,5 +12,16 @@ struct Aabb {
if(min.y > p.y) min.y = p.y; if(min.y > p.y) min.y = p.y;
if(min.z > p.z) min.z = p.z; if(min.z > p.z) min.z = p.z;
} }
template<typename T>
bool IsIn(const vector3<T> p) const {
return ((p.x >= min.x) && (p.x <= max.x) &&
(p.y >= min.y) && (p.y <= max.y) &&
(p.z >= min.z) && (p.z <= max.z));
}
bool Intersects(const Aabb& o) const {
return (min.x < o.max.x) && (max.x > o.min.x) &&
(min.y < o.max.y) && (max.y > o.min.y) &&
(min.z < o.max.z) && (max.z > o.min.z);
}
}; };

View File

@ -28,17 +28,33 @@ void CollisionSpace::TraceRay(const vector3d& start, const vector3d& dir, isect_
} }
} }
void CollisionSpace::CollideGeoms(Geom* a, Geom* b, void (*callback)(CollisionContact*)) { void CollisionSpace::CollideGeoms(Geom* a, void (*callback)(CollisionContact*)) {
a->Collide(b, callback); /* Our big Aabb. */
b->Collide(a, callback); vector3d pos = a->GetPosition();
Aabb bigAabb;
bigAabb = a->GetGeomTree()->GetMaxAabb();
bigAabb.min += pos;
bigAabb.max += pos;
for(std::list<Geom*>::iterator i = m_geoms.begin(); i != m_geoms.end(); ++i) {
if((*i) != a) {
Aabb bigAabb2;
bigAabb2 = (*i)->GetGeomTree()->GetMaxAabb();
vector3d pos2 = (*i)->GetPosition();
bigAabb2.min += pos2;
bigAabb2.max += pos2;
if(bigAabb.Intersects(bigAabb2)) {
a->Collide(*i, callback);
if(!(*i)->HasMoved()) (*i)->Collide(a, callback);
}
}
}
} }
void CollisionSpace::Collide(void (*callback)(CollisionContact*)) { void CollisionSpace::Collide(void (*callback)(CollisionContact*)) {
/* For now, do a totally stupid intersection of every body on every other. */ /* For now, do a totally stupid intersection of every body on every other. */
for(std::list<Geom*>::iterator i = m_geoms.begin(); i != m_geoms.end(); ++i) { for(std::list<Geom*>::iterator i = m_geoms.begin(); i != m_geoms.end(); ++i) {
for(std::list<Geom*>::iterator j = m_geoms.begin(); j != m_geoms.end(); ++j) { if((*i)->HasMoved()) CollideGeoms(*i, callback);
if((*i) != (*j))CollideGeoms(*i, *j, callback);
}
} }
} }

View File

@ -14,7 +14,7 @@ public:
void TraceRay(const vector3d& start, const vector3d& dir, isect_t* isect); void TraceRay(const vector3d& start, const vector3d& dir, isect_t* isect);
void Collide(void (*callback)(CollisionContact*)); void Collide(void (*callback)(CollisionContact*));
private: private:
void CollideGeoms(Geom* a, Geom* b, void (*callback)(CollisionContact*)); void CollideGeoms(Geom* a, void (*callback)(CollisionContact*));
std::list<Geom*> m_geoms; std::list<Geom*> m_geoms;
}; };

View File

@ -10,6 +10,7 @@ Geom::Geom(GeomTree* geomtree) {
m_invOrient = matrix4x4d::Identity(); m_invOrient = matrix4x4d::Identity();
m_orientIdx = 0; m_orientIdx = 0;
m_active = true; m_active = true;
m_moved = false;
m_data = 0; m_data = 0;
} }
@ -17,6 +18,7 @@ void Geom::MoveTo(const matrix4x4d& m) {
m_orientIdx = !m_orientIdx; m_orientIdx = !m_orientIdx;
m_orient[m_orientIdx] = m; m_orient[m_orientIdx] = m;
m_invOrient = m.InverseOf(); m_invOrient = m.InverseOf();
m_moved = true;
} }
void Geom::MoveTo(const matrix4x4d& m, const vector3d pos) { void Geom::MoveTo(const matrix4x4d& m, const vector3d pos) {
@ -28,7 +30,14 @@ void Geom::MoveTo(const matrix4x4d& m, const vector3d pos) {
m_invOrient = m_orient[m_orientIdx].InverseOf(); m_invOrient = m_orient[m_orientIdx].InverseOf();
} }
vector3d Geom::GetPosition(void) const {
return vector3d(m_orient[m_orientIdx][12],
m_orient[m_orientIdx][13],
m_orient[m_orientIdx][14]);
}
void Geom::Collide(Geom* b, void(*callback)(CollisionContact*)) { void Geom::Collide(Geom* b, void(*callback)(CollisionContact*)) {
m_moved = false;
for(int i = 0; i < m_geomtree->m_numVertices; i++) { for(int i = 0; i < m_geomtree->m_numVertices; i++) {
vector3d v(&m_geomtree->m_vertices[3*i]); vector3d v(&m_geomtree->m_vertices[3*i]);
vector3d from = m_orient[!m_orientIdx] * v; vector3d from = m_orient[!m_orientIdx] * v;

View File

@ -13,9 +13,11 @@ public:
void MoveTo(const matrix4x4d& m, const vector3d pos); void MoveTo(const matrix4x4d& m, const vector3d pos);
const matrix4x4d& GetInvTransform(void) { return m_invOrient; } const matrix4x4d& GetInvTransform(void) { return m_invOrient; }
const matrix4x4d& GetTransform(void) { return m_orient[m_orientIdx]; } const matrix4x4d& GetTransform(void) { return m_orient[m_orientIdx]; }
vector3d GetPosition(void) const;
void Enable(void) { m_active = true; } void Enable(void) { m_active = true; }
void Disable(void) {m_active = false; } void Disable(void) {m_active = false; }
bool IsEnabled(void) { return m_active; } bool IsEnabled(void) { return m_active; }
bool HasMoved(void) { return m_moved; }
GeomTree* GetGeomTree(void) { return m_geomtree; } GeomTree* GetGeomTree(void) { return m_geomtree; }
void Collide(Geom* b, void(*callback)(CollisionContact*)); void Collide(Geom* b, void(*callback)(CollisionContact*));
void SetUserData(void* d) { m_data = d; } void SetUserData(void* d) { m_data = d; }
@ -25,6 +27,7 @@ private:
matrix4x4d m_orient[2], m_invOrient; matrix4x4d m_orient[2], m_invOrient;
int m_orientIdx; int m_orientIdx;
bool m_active; bool m_active;
bool m_moved;
GeomTree* m_geomtree; GeomTree* m_geomtree;
void* m_data; void* m_data;
}; };

View File

@ -80,9 +80,11 @@ GeomTree::~GeomTree(void) {
delete [] m_triAlloc; delete [] m_triAlloc;
} }
GeomTree::GeomTree(int numVerts, int numTris, float* vertices, int* indices) : m_numVertices(numVerts) { GeomTree::GeomTree(int numVerts, int numTris, float* vertices, int* indices,
int* triflags) : m_numVertices(numVerts) {
m_vertices = vertices; m_vertices = vertices;
m_indices = indices; m_indices = indices;
m_triFlags = triflags;
m_aabb.min = vector3d(FLT_MAX, FLT_MAX, FLT_MAX); m_aabb.min = vector3d(FLT_MAX, FLT_MAX, FLT_MAX);
m_aabb.max = vector3d(FLT_MAX, FLT_MAX, FLT_MAX); m_aabb.max = vector3d(FLT_MAX, FLT_MAX, FLT_MAX);
@ -94,6 +96,15 @@ GeomTree::GeomTree(int numVerts, int numTris, float* vertices, int* indices) : m
} }
m_triAlloc[numTris-1].next = 0; m_triAlloc[numTris-1].next = 0;
/* Make big rotation aabb. */
{
vector3d cent = 0.5*(m_aabb.min+m_aabb.max);
double mdim = (cent - m_aabb.min).Length();
mdim = MAX(mdim,(m_aabb.max - cent).Length());
m_maxAabb.min = vector3d(cent.x - mdim, cent.y - mdim, cent.z - mdim);
m_maxAabb.max = vector3d(cent.x + mdim, cent.y + mdim, cent.z + mdim);
}
printf("Building BIHTree of %d triangles\n", numTris); printf("Building BIHTree of %d triangles\n", numTris);
printf("Aabb: %f,%f,%f -> %f,%f,%f\n", printf("Aabb: %f,%f,%f -> %f,%f,%f\n",
m_aabb.min.x, m_aabb.min.x,
@ -102,6 +113,13 @@ GeomTree::GeomTree(int numVerts, int numTris, float* vertices, int* indices) : m
m_aabb.max.x, m_aabb.max.x,
m_aabb.max.y, m_aabb.max.y,
m_aabb.max.z); m_aabb.max.z);
printf("MaxAabb: %f,%f,%f -> %f,%f,%f\n",
m_maxAabb.min.x,
m_maxAabb.min.y,
m_maxAabb.min.z,
m_maxAabb.max.x,
m_maxAabb.max.y,
m_maxAabb.max.z);
m_nodes = new BIHNode[numTris*4]; m_nodes = new BIHNode[numTris*4];
m_nodesAllocSize = numTris*4; m_nodesAllocSize = numTris*4;
m_nodesAllocPos = 0; m_nodesAllocPos = 0;
@ -183,7 +201,6 @@ void GeomTree::BihTreeGhBuild(BIHNode* a_node, Aabb& a_box, Aabb& a_splitBox, in
//if(axis != -1) printf("Best is axis %d on %s (cost %f%%)\n", axis, (isTop ? "top" : "botton"), bestCost*100); //if(axis != -1) printf("Best is axis %d on %s (cost %f%%)\n", axis, (isTop ? "top" : "botton"), bestCost*100);
/* Cut off whitespace. */ /* Cut off whitespace. */
if((bestCost > MIN_SPACE_CUTOFF) && (bestCost < 1.0f)) { if((bestCost > MIN_SPACE_CUTOFF) && (bestCost < 1.0f)) {
printf("Clicing off %f%%\n", bestCost*100);
a_node->SetLeaf(false); a_node->SetLeaf(false);
a_node->SetAxis(axis); a_node->SetAxis(axis);
@ -465,21 +482,22 @@ void GeomTree::RayTriIntersect(const vector3f& origin, const vector3f& dir, int
const float v1d = vector3f::Dot(v1_cross,dir); const float v1d = vector3f::Dot(v1_cross,dir);
const float v2d = vector3f::Dot(v2_cross,dir); const float v2d = vector3f::Dot(v2_cross,dir);
if((v0d > 0) && (v1d > 0) && (v2d > 0)) { if(((v0d > 0) && (v1d > 0) && (v2d > 0)) ||
((v0d < 0) && (v1d < 0) && (v2d < 0))) {
const vector3f n = vector3f::Cross(c-a, b-a); const vector3f n = vector3f::Cross(c-a, b-a);
const float nominator = vector3f::Dot(n, (a-origin)); const float nominator = vector3f::Dot(n, (a-origin));
const float dist = nominator / vector3f::Dot(dir, n); const float dist = nominator / vector3f::Dot(dir, n);
if((dist > EPSILON) && (dist < isect->dist)) { if((dist > EPSILON) && (dist < isect->dist)) {
isect->dist = dist; isect->dist = dist;
isect->triIdx = triIdx; isect->triIdx = triIdx/3;
} }
} }
} }
vector3f GeomTree::GetTriNormal(int triIdx) const { vector3f GeomTree::GetTriNormal(int triIdx) const {
const vector3f a(&m_vertices[3*m_indices[triIdx]]); const vector3f a(&m_vertices[3*m_indices[3*triIdx]]);
const vector3f b(&m_vertices[3*m_indices[triIdx+1]]); const vector3f b(&m_vertices[3*m_indices[3*triIdx+1]]);
const vector3f c(&m_vertices[3*m_indices[triIdx+2]]); const vector3f c(&m_vertices[3*m_indices[3*triIdx+2]]);
return vector3f::Normalize(vector3f::Cross(b-a, c-a)); return vector3f::Normalize(vector3f::Cross(b-a, c-a));
} }

View File

@ -12,9 +12,10 @@ struct isect_t {
class GeomTree { class GeomTree {
public: public:
GeomTree(int numVerts, int numTris, float* vertices, int* indices); GeomTree(int numVerts, int numTris, float* vertices, int* indices, int* triflags);
~GeomTree(void); ~GeomTree(void);
Aabb GetAabb(void) { return m_aabb; } const Aabb& GetAabb(void) { return m_aabb; }
const Aabb& GetMaxAabb(void) { return m_maxAabb; }
/* /*
* dir should be unit length, * dir should be unit length,
* isect.dist should be ray length. * isect.dist should be ray length.
@ -22,6 +23,7 @@ public:
*/ */
void TraceRay(const vector3f& start, const vector3f& dir, isect_t* isect); void TraceRay(const vector3f& start, const vector3f& dir, isect_t* isect);
vector3f GetTriNormal(int triIdx) const; vector3f GetTriNormal(int triIdx) const;
int GetTriFlag(int triIdx) const { return m_triFlags[triIdx]; }
const int m_numVertices; const int m_numVertices;
const float* m_vertices; const float* m_vertices;
@ -34,6 +36,7 @@ private:
void BihTreeGhBuild(BIHNode* a_node, Aabb& a_box, Aabb& a_splitBox, int a_depth, int a_prims); void BihTreeGhBuild(BIHNode* a_node, Aabb& a_box, Aabb& a_splitBox, int a_depth, int a_prims);
Aabb m_aabb; Aabb m_aabb;
Aabb m_maxAabb; /* An aabb that still contains the object regardless of rotation. */
BIHNode* m_nodes; BIHNode* m_nodes;
int m_nodesAllocPos; int m_nodesAllocPos;
int m_nodesAllocSize; int m_nodesAllocSize;
@ -42,5 +45,6 @@ private:
int m_triAllocSize; int m_triAllocSize;
const int* m_indices; const int* m_indices;
const int* m_triFlags;
}; };

View File

@ -168,18 +168,17 @@ void L3D::HandleEvents(void) {
#ifdef DEBUG #ifdef DEBUG
if(event.key.keysym.sym == SDLK_F12) { if(event.key.keysym.sym == SDLK_F12) {
/* Add test object. */ /* Add test object. */
Ship* body = new Ship(ShipType::LADYBIRD); /*Ship* body = new Ship(ShipType::LADYBIRD);
body->SetLabel("A friend"); body->SetLabel("A friend");
body->SetFrame(L3D::player->GetFrame()); body->SetFrame(L3D::player->GetFrame());
body->SetPosition(L3D::player->GetPosition()+vector3d(0,0,-1000)); body->SetPosition(L3D::player->GetPosition()+vector3d(0,0,-1000));
Space::AddBody(body); Space::AddBody(body);*/
#if 0
SpaceStation* station = new SpaceStation(SpaceStation::JJHOOP); SpaceStation* station = new SpaceStation(SpaceStation::JJHOOP);
station->SetLabel("Poemi-chan's Folly"); station->SetLabel("Poemi-chan's Folly");
station->SetFrame(L3D::player->GetFrame()); station->SetFrame(L3D::player->GetFrame());
station->SetPosition(L3D::player->GetPosition()+vector3d(0,0,-1000)); station->SetRotMatrix(matrix4x4d::RotateZMatrix(M_PI));
station->SetPosition(L3D::player->GetPosition() + vector3d(0, 0, -5000));
Space::AddBody(station); Space::AddBody(station);
#endif
} }
#endif #endif
if(event.key.keysym.sym == SDLK_F11) SDL_WM_ToggleFullScreen(L3D::scrSurface); if(event.key.keysym.sym == SDLK_F11) SDL_WM_ToggleFullScreen(L3D::scrSurface);
@ -394,12 +393,14 @@ void L3D::MainLoop(void) {
time_before_frame = SDL_GetTicks(); time_before_frame = SDL_GetTicks();
/* Fixed 62.5hz physics. */ /* Fixed 62.5hz physics. */
int num_steps = 0;
while(time_before_frame - last_phys_update > 16) { while(time_before_frame - last_phys_update > 16) {
last_phys_update += 16; last_phys_update += 16;
const float step = L3D::GetTimeStep(); const float step = L3D::GetTimeStep();
if(step) Space::TimeStep(step); if(step) Space::TimeStep(step);
gameTime += step; gameTime += step;
phys_stat++; phys_stat++;
if(++num_steps > 3) break;
} }
currentView->Update(); currentView->Update();

View File

@ -60,6 +60,7 @@ void ModelBody::SetModel(int sbreModel) {
CollMeshSet* mset = GetModelCollMeshSet(sbreModel); CollMeshSet* mset = GetModelCollMeshSet(sbreModel);
m_geom = new Geom(mset->m_geomTree); m_geom = new Geom(mset->m_geomTree);
m_geom->SetUserData((void*)this);
geomColl.resize(mset->numMeshParts); geomColl.resize(mset->numMeshParts);
geoms.resize(mset->numMeshParts); geoms.resize(mset->numMeshParts);
@ -77,6 +78,7 @@ void ModelBody::SetPosition(vector3d p) {
matrix4x4d m; matrix4x4d m;
GetRotMatrix(m); GetRotMatrix(m);
m_geom->MoveTo(m, p); m_geom->MoveTo(m, p);
m_geom->MoveTo(m, p);
for(unsigned int i = 0; i < geoms.size(); i++) { for(unsigned int i = 0; i < geoms.size(); i++) {
dGeomSetPosition(geoms[i], p.x, p.y, p.z); dGeomSetPosition(geoms[i], p.x, p.y, p.z);
@ -120,6 +122,9 @@ void ModelBody::SetRotMatrix(const matrix4x4d& r) {
for(unsigned int i = 0; i < geoms.size(); i++) { for(unsigned int i = 0; i < geoms.size(); i++) {
dGeomSetRotation(geoms[i], _m); dGeomSetRotation(geoms[i], _m);
} }
vector3d pos = m_geom->GetPosition();
m_geom->MoveTo(r, pos);
m_geom->MoveTo(r, pos);
} }
void ModelBody::GetRotMatrix(matrix4x4d& m) const { void ModelBody::GetRotMatrix(matrix4x4d& m) const {
@ -172,7 +177,6 @@ void ModelBody::TriMeshUpdateLastPos(void) {
matrix4x4d wtf; matrix4x4d wtf;
memcpy(&wtf[0], t, 16*sizeof(double)); memcpy(&wtf[0], t, 16*sizeof(double));
m_geom->MoveTo(wtf); m_geom->MoveTo(wtf);
m_geom->SetUserData(dGeomGetBody(geoms[0]));
m_triMeshLastMatrixIndex = !m_triMeshLastMatrixIndex; m_triMeshLastMatrixIndex = !m_triMeshLastMatrixIndex;
for(unsigned int i = 0; i < geoms.size(); i++) { for(unsigned int i = 0; i < geoms.size(); i++) {

View File

@ -82,7 +82,8 @@ CollMeshSet::CollMeshSet(int sbreModel) {
aabb.max[a] = sbreCollMesh->pVertex[i+a]; aabb.max[a] = sbreCollMesh->pVertex[i+a];
} }
} }
m_geomTree = new GeomTree(sbreCollMesh->nv, sbreCollMesh->ni/3, sbreCollMesh->pVertex, sbreCollMesh->pIndex); m_geomTree = new GeomTree(sbreCollMesh->nv, sbreCollMesh->ni/3,
sbreCollMesh->pVertex, sbreCollMesh->pIndex, sbreCollMesh->pFlag);
triIndices = new coltri_t[sbreCollMesh->ni/3]; triIndices = new coltri_t[sbreCollMesh->ni/3];
int tidx = 0; int tidx = 0;

View File

@ -159,6 +159,7 @@ static void render_coll_mesh(const CollMesh* m) {
float foo[TEXSIZE][TEXSIZE]; float foo[TEXSIZE][TEXSIZE];
float aspectRatio = 1.0; float aspectRatio = 1.0;
float camera_zoom = 1.0; float camera_zoom = 1.0;
float distance = 100;
static void raytraceCollMesh(vector3d camPos, vector3d camera_up, vector3d camera_forward, CollisionSpace* space) { static void raytraceCollMesh(vector3d camPos, vector3d camera_up, vector3d camera_forward, CollisionSpace* space) {
memset(foo, 0, sizeof(float)*TEXSIZE*TEXSIZE); memset(foo, 0, sizeof(float)*TEXSIZE*TEXSIZE);
@ -191,7 +192,7 @@ static void raytraceCollMesh(vector3d camPos, vector3d camera_up, vector3d camer
space->TraceRay(camPos, toPoint, &isect); space->TraceRay(camPos, toPoint, &isect);
if(isect.triIdx != -1) { if(isect.triIdx != -1) {
foo[x][y] = 10.0/isect.dist; foo[x][y] = distance/(10*isect.dist);
} else { } else {
foo[x][y] = 0; foo[x][y] = 0;
} }
@ -238,7 +239,6 @@ static void onCollision(CollisionContact* c) {
void Viewer::MainLoop(void) { void Viewer::MainLoop(void) {
matrix4x4d rot = matrix4x4d::Identity(); matrix4x4d rot = matrix4x4d::Identity();
float distance = 100;
Uint32 lastFoo = SDL_GetTicks(); Uint32 lastFoo = SDL_GetTicks();
CollMesh* cmesh = (CollMesh*)calloc(1, sizeof(CollMesh)); CollMesh* cmesh = (CollMesh*)calloc(1, sizeof(CollMesh));
@ -251,15 +251,16 @@ void Viewer::MainLoop(void) {
} }
Uint32 t= SDL_GetTicks(); Uint32 t= SDL_GetTicks();
GeomTree* geomtree = new GeomTree(cmesh->nv, cmesh->ni/3, cmesh->pVertex, cmesh->pIndex); GeomTree* geomtree = new GeomTree(cmesh->nv, cmesh->ni/3, cmesh->pVertex,
cmesh->pIndex, cmesh->pFlag);
printf("Geom tree build in $dms\n", SDL_GetTicks() -t); printf("Geom tree build in $dms\n", SDL_GetTicks() -t);
Geom* geom = new Geom(geomtree); Geom* geom = new Geom(geomtree);
Geom* geom2 = new Geom(geomtree); //Geom* geom2 = new Geom(geomtree);
CollisionSpace* space = new CollisionSpace(); CollisionSpace* space = new CollisionSpace();
space->AddGeom(geom2); //space->AddGeom(geom2);
space->AddGeom(geom); space->AddGeom(geom);
geom2->MoveTo(rot, vector3d(80,0,0)); //geom2->MoveTo(rot, vector3d(80,0,0));
geom2->MoveTo(rot, vector3d(80,0,0)); //geom2->MoveTo(rot, vector3d(80,0,0));
for(;;) { for(;;) {
PollEvents(); PollEvents();

View File

@ -324,6 +324,24 @@ static void dump_contact(const dContact* c) {
printf("fdir1 %f,%f,%f\n", c->fdir1[0], c->fdir1[1], c->fdir1[2]); printf("fdir1 %f,%f,%f\n", c->fdir1[0], c->fdir1[1], c->fdir1[2]);
} }
static bool _OnCollision2(Object* o1, Object* o2, CollisionContact* c) {
Body* pb1, *pb2;
int flags = c->g2->GetGeomTree()->GetTriFlag(c->triIdx);
//printf("Collision flags %x (triIdx %d)\n", flags, c->triIdx);
/* Geom bodies point to their parents. */
if(o1->IsType(Object::GEOM)) {
pb1 = static_cast<ModelBody::GeomBit*>(o1)->parent;
flags |= static_cast<ModelBody::GeomBit*>(o1)->flags;
} else pb1 = static_cast<Body*>(o1);
if(o2->IsType(Object::GEOM)) {
pb2 = static_cast<ModelBody::GeomBit*>(o2)->parent;
flags |= static_cast<ModelBody::GeomBit*>(o2)->flags;
} else pb2 = static_cast<Body*>(o2);
if((pb1 && !pb1->OnCollision(pb2, flags)) || (pb2 && !pb2->OnCollision(pb1, flags))) return false;
return true;
}
#define MAX_CONTACTS 10 #define MAX_CONTACTS 10
static int contact_num; static int contact_num;
static void hitCallback(CollisionContact* c) { static void hitCallback(CollisionContact* c) {