[...] Bunch of collision work, pretty much broke planet landing and some
other stuff. Don't worry about it.
This commit is contained in:
parent
1b16cb2f70
commit
20906f1f0a
11
src/aabb.h
11
src/aabb.h
@ -12,5 +12,16 @@ struct Aabb {
|
||||
if(min.y > p.y) min.y = p.y;
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -28,17 +28,33 @@ void CollisionSpace::TraceRay(const vector3d& start, const vector3d& dir, isect_
|
||||
}
|
||||
}
|
||||
|
||||
void CollisionSpace::CollideGeoms(Geom* a, Geom* b, void (*callback)(CollisionContact*)) {
|
||||
a->Collide(b, callback);
|
||||
b->Collide(a, callback);
|
||||
void CollisionSpace::CollideGeoms(Geom* a, void (*callback)(CollisionContact*)) {
|
||||
/* Our big Aabb. */
|
||||
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*)) {
|
||||
/* 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 j = m_geoms.begin(); j != m_geoms.end(); ++j) {
|
||||
if((*i) != (*j))CollideGeoms(*i, *j, callback);
|
||||
}
|
||||
if((*i)->HasMoved()) CollideGeoms(*i, callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ public:
|
||||
void TraceRay(const vector3d& start, const vector3d& dir, isect_t* isect);
|
||||
void Collide(void (*callback)(CollisionContact*));
|
||||
private:
|
||||
void CollideGeoms(Geom* a, Geom* b, void (*callback)(CollisionContact*));
|
||||
void CollideGeoms(Geom* a, void (*callback)(CollisionContact*));
|
||||
std::list<Geom*> m_geoms;
|
||||
};
|
||||
|
||||
|
@ -10,6 +10,7 @@ Geom::Geom(GeomTree* geomtree) {
|
||||
m_invOrient = matrix4x4d::Identity();
|
||||
m_orientIdx = 0;
|
||||
m_active = true;
|
||||
m_moved = false;
|
||||
m_data = 0;
|
||||
}
|
||||
|
||||
@ -17,6 +18,7 @@ void Geom::MoveTo(const matrix4x4d& m) {
|
||||
m_orientIdx = !m_orientIdx;
|
||||
m_orient[m_orientIdx] = m;
|
||||
m_invOrient = m.InverseOf();
|
||||
m_moved = true;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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*)) {
|
||||
m_moved = false;
|
||||
for(int i = 0; i < m_geomtree->m_numVertices; i++) {
|
||||
vector3d v(&m_geomtree->m_vertices[3*i]);
|
||||
vector3d from = m_orient[!m_orientIdx] * v;
|
||||
|
@ -13,9 +13,11 @@ public:
|
||||
void MoveTo(const matrix4x4d& m, const vector3d pos);
|
||||
const matrix4x4d& GetInvTransform(void) { return m_invOrient; }
|
||||
const matrix4x4d& GetTransform(void) { return m_orient[m_orientIdx]; }
|
||||
vector3d GetPosition(void) const;
|
||||
void Enable(void) { m_active = true; }
|
||||
void Disable(void) {m_active = false; }
|
||||
bool IsEnabled(void) { return m_active; }
|
||||
bool HasMoved(void) { return m_moved; }
|
||||
GeomTree* GetGeomTree(void) { return m_geomtree; }
|
||||
void Collide(Geom* b, void(*callback)(CollisionContact*));
|
||||
void SetUserData(void* d) { m_data = d; }
|
||||
@ -25,6 +27,7 @@ private:
|
||||
matrix4x4d m_orient[2], m_invOrient;
|
||||
int m_orientIdx;
|
||||
bool m_active;
|
||||
bool m_moved;
|
||||
GeomTree* m_geomtree;
|
||||
void* m_data;
|
||||
};
|
||||
|
@ -80,9 +80,11 @@ GeomTree::~GeomTree(void) {
|
||||
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_indices = indices;
|
||||
m_triFlags = triflags;
|
||||
m_aabb.min = 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;
|
||||
|
||||
/* 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("Aabb: %f,%f,%f -> %f,%f,%f\n",
|
||||
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.y,
|
||||
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_nodesAllocSize = numTris*4;
|
||||
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);
|
||||
/* Cut off whitespace. */
|
||||
if((bestCost > MIN_SPACE_CUTOFF) && (bestCost < 1.0f)) {
|
||||
printf("Clicing off %f%%\n", bestCost*100);
|
||||
a_node->SetLeaf(false);
|
||||
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 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 float nominator = vector3f::Dot(n, (a-origin));
|
||||
const float dist = nominator / vector3f::Dot(dir, n);
|
||||
if((dist > EPSILON) && (dist < isect->dist)) {
|
||||
isect->dist = dist;
|
||||
isect->triIdx = triIdx;
|
||||
isect->triIdx = triIdx/3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector3f GeomTree::GetTriNormal(int triIdx) const {
|
||||
const vector3f a(&m_vertices[3*m_indices[triIdx]]);
|
||||
const vector3f b(&m_vertices[3*m_indices[triIdx+1]]);
|
||||
const vector3f c(&m_vertices[3*m_indices[triIdx+2]]);
|
||||
const vector3f a(&m_vertices[3*m_indices[3*triIdx]]);
|
||||
const vector3f b(&m_vertices[3*m_indices[3*triIdx+1]]);
|
||||
const vector3f c(&m_vertices[3*m_indices[3*triIdx+2]]);
|
||||
|
||||
return vector3f::Normalize(vector3f::Cross(b-a, c-a));
|
||||
}
|
||||
|
@ -12,9 +12,10 @@ struct isect_t {
|
||||
|
||||
class GeomTree {
|
||||
public:
|
||||
GeomTree(int numVerts, int numTris, float* vertices, int* indices);
|
||||
GeomTree(int numVerts, int numTris, float* vertices, int* indices, int* triflags);
|
||||
~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,
|
||||
* isect.dist should be ray length.
|
||||
@ -22,6 +23,7 @@ public:
|
||||
*/
|
||||
void TraceRay(const vector3f& start, const vector3f& dir, isect_t* isect);
|
||||
vector3f GetTriNormal(int triIdx) const;
|
||||
int GetTriFlag(int triIdx) const { return m_triFlags[triIdx]; }
|
||||
|
||||
const int m_numVertices;
|
||||
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);
|
||||
|
||||
Aabb m_aabb;
|
||||
Aabb m_maxAabb; /* An aabb that still contains the object regardless of rotation. */
|
||||
BIHNode* m_nodes;
|
||||
int m_nodesAllocPos;
|
||||
int m_nodesAllocSize;
|
||||
@ -42,5 +45,6 @@ private:
|
||||
int m_triAllocSize;
|
||||
|
||||
const int* m_indices;
|
||||
const int* m_triFlags;
|
||||
};
|
||||
|
||||
|
11
src/main.cpp
11
src/main.cpp
@ -168,18 +168,17 @@ void L3D::HandleEvents(void) {
|
||||
#ifdef DEBUG
|
||||
if(event.key.keysym.sym == SDLK_F12) {
|
||||
/* Add test object. */
|
||||
Ship* body = new Ship(ShipType::LADYBIRD);
|
||||
/*Ship* body = new Ship(ShipType::LADYBIRD);
|
||||
body->SetLabel("A friend");
|
||||
body->SetFrame(L3D::player->GetFrame());
|
||||
body->SetPosition(L3D::player->GetPosition()+vector3d(0,0,-1000));
|
||||
Space::AddBody(body);
|
||||
#if 0
|
||||
Space::AddBody(body);*/
|
||||
SpaceStation* station = new SpaceStation(SpaceStation::JJHOOP);
|
||||
station->SetLabel("Poemi-chan's Folly");
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
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();
|
||||
/* Fixed 62.5hz physics. */
|
||||
int num_steps = 0;
|
||||
while(time_before_frame - last_phys_update > 16) {
|
||||
last_phys_update += 16;
|
||||
const float step = L3D::GetTimeStep();
|
||||
if(step) Space::TimeStep(step);
|
||||
gameTime += step;
|
||||
phys_stat++;
|
||||
if(++num_steps > 3) break;
|
||||
}
|
||||
currentView->Update();
|
||||
|
||||
|
@ -60,6 +60,7 @@ void ModelBody::SetModel(int sbreModel) {
|
||||
CollMeshSet* mset = GetModelCollMeshSet(sbreModel);
|
||||
|
||||
m_geom = new Geom(mset->m_geomTree);
|
||||
m_geom->SetUserData((void*)this);
|
||||
|
||||
geomColl.resize(mset->numMeshParts);
|
||||
geoms.resize(mset->numMeshParts);
|
||||
@ -77,6 +78,7 @@ void ModelBody::SetPosition(vector3d p) {
|
||||
matrix4x4d m;
|
||||
GetRotMatrix(m);
|
||||
m_geom->MoveTo(m, p);
|
||||
m_geom->MoveTo(m, p);
|
||||
|
||||
for(unsigned int i = 0; i < geoms.size(); i++) {
|
||||
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++) {
|
||||
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 {
|
||||
@ -172,7 +177,6 @@ void ModelBody::TriMeshUpdateLastPos(void) {
|
||||
matrix4x4d wtf;
|
||||
memcpy(&wtf[0], t, 16*sizeof(double));
|
||||
m_geom->MoveTo(wtf);
|
||||
m_geom->SetUserData(dGeomGetBody(geoms[0]));
|
||||
|
||||
m_triMeshLastMatrixIndex = !m_triMeshLastMatrixIndex;
|
||||
for(unsigned int i = 0; i < geoms.size(); i++) {
|
||||
|
@ -82,7 +82,8 @@ CollMeshSet::CollMeshSet(int sbreModel) {
|
||||
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];
|
||||
int tidx = 0;
|
||||
|
@ -159,6 +159,7 @@ static void render_coll_mesh(const CollMesh* m) {
|
||||
float foo[TEXSIZE][TEXSIZE];
|
||||
float aspectRatio = 1.0;
|
||||
float camera_zoom = 1.0;
|
||||
float distance = 100;
|
||||
static void raytraceCollMesh(vector3d camPos, vector3d camera_up, vector3d camera_forward, CollisionSpace* space) {
|
||||
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);
|
||||
|
||||
if(isect.triIdx != -1) {
|
||||
foo[x][y] = 10.0/isect.dist;
|
||||
foo[x][y] = distance/(10*isect.dist);
|
||||
} else {
|
||||
foo[x][y] = 0;
|
||||
}
|
||||
@ -238,7 +239,6 @@ static void onCollision(CollisionContact* c) {
|
||||
|
||||
void Viewer::MainLoop(void) {
|
||||
matrix4x4d rot = matrix4x4d::Identity();
|
||||
float distance = 100;
|
||||
Uint32 lastFoo = SDL_GetTicks();
|
||||
|
||||
CollMesh* cmesh = (CollMesh*)calloc(1, sizeof(CollMesh));
|
||||
@ -251,15 +251,16 @@ void Viewer::MainLoop(void) {
|
||||
}
|
||||
|
||||
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);
|
||||
Geom* geom = new Geom(geomtree);
|
||||
Geom* geom2 = new Geom(geomtree);
|
||||
//Geom* geom2 = new Geom(geomtree);
|
||||
CollisionSpace* space = new CollisionSpace();
|
||||
space->AddGeom(geom2);
|
||||
//space->AddGeom(geom2);
|
||||
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(;;) {
|
||||
PollEvents();
|
||||
|
@ -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]);
|
||||
}
|
||||
|
||||
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
|
||||
static int contact_num;
|
||||
static void hitCallback(CollisionContact* c) {
|
||||
|
Loading…
Reference in New Issue
Block a user