[Add] Planet sphere geom in new collider. A little suspect..

This commit is contained in:
Rtch90 2018-03-21 20:43:52 +00:00
parent 9e6b365f9d
commit b738fb63e1
12 changed files with 140 additions and 14 deletions

View File

@ -11,6 +11,7 @@ struct CollisionContact {
vector3d normal;
double depth;
int triIdx;
Geom* g1, *g2;
void* userData1, *userData2;
int geomFlag;
};

View File

@ -3,7 +3,7 @@
#include "geom_tree.h"
CollisionSpace::CollisionSpace(void) {
sphere.radius = 0;
}
void CollisionSpace::AddGeom(Geom* geom) {
@ -15,6 +15,35 @@ void CollisionSpace::RemoveGeom(Geom* geom) {
m_geoms.remove(geom);
}
void CollisionSpace::CollideRaySphere(const vector3d& start, const vector3d& dir, isect_t* isect) {
if(sphere.radius != 0) {
/* Collide with lovely sphere! */
const vector3d v = start - sphere.pos;
const double b = -vector3d::Dot(v, dir);
double det = (b*b) - vector3d::Dot(v, v) + (sphere.radius*sphere.radius);
if(det > 0) {
det = sqrt(det);
const double i1 = b - det;
const double i2 = b + det;
if(i2 > 0) {
/*if(i1 < 0) {
if(i2 < *dist) {
*dist = i2;
//retval = INPRIM;
retval = true;
}
}*/
if(i2 > 0) {
if(i1 < isect->dist) {
isect->dist = i1;
isect->triIdx = 0;
}
}
}
}
}
}
void CollisionSpace::TraceRay(const vector3d& start, const vector3d& dir, isect_t* isect) {
for(std::list<Geom*>::iterator i = m_geoms.begin(); i != m_geoms.end(); ++i) {
if((*i)->IsEnabled()) {
@ -26,6 +55,7 @@ void CollisionSpace::TraceRay(const vector3d& start, const vector3d& dir, isect_
(*i)->GetGeomTree()->TraceRay(modelStart, modelDir, isect);
}
}
CollideRaySphere(start, dir, isect);
}
void CollisionSpace::CollideGeoms(Geom* a, void (*callback)(CollisionContact*)) {
@ -36,6 +66,11 @@ void CollisionSpace::CollideGeoms(Geom* a, void (*callback)(CollisionContact*))
bigAabb.min += pos;
bigAabb.max += pos;
/* First test this reested sh*t against the planet sphere thing. */
if(sphere.radius != 0) {
a->CollideSphere(sphere, callback);
}
for(std::list<Geom*>::iterator i = m_geoms.begin(); i != m_geoms.end(); ++i) {
if((*i) != a) {
Aabb bigAabb2;

View File

@ -6,6 +6,14 @@ class Geom;
struct isect_t;
class CollisionContact;
struct Sphere {
vector3d pos;
double radius;
void* userData;
};
/* Collision spaces have a bunch of geoms and at most one sphere (for a planet). */
class CollisionSpace {
public:
CollisionSpace(void);
@ -13,8 +21,15 @@ public:
void RemoveGeom(Geom*);
void TraceRay(const vector3d& start, const vector3d& dir, isect_t* isect);
void Collide(void (*callback)(CollisionContact*));
void SetSphere(const vector3d& pos, double radius, void* user_data) {
sphere.pos = pos; sphere.radius = radius; sphere.userData = user_data;
}
private:
void CollideGeoms(Geom* a, void (*callback)(CollisionContact*));
void CollideRaySphere(const vector3d& start, const vector3d& dir, isect_t* isect);
std::list<Geom*> m_geoms;
Sphere sphere;
};

View File

@ -36,6 +36,47 @@ vector3d Geom::GetPosition(void) const {
m_orient[m_orientIdx][14]);
}
void Geom::CollideSphere(Sphere& sphere, void(*callback)(CollisionContact*)) {
for(int i = 0; i < m_geomtree->m_numVertices; i++) {
vector3d vtx(&m_geomtree->m_vertices[3*i]);
vector3d from = m_orient[!m_orientIdx] * vtx;
vector3d to = m_orient[m_orientIdx] * vtx;
vector3d dir = to - from;
const double len = dir.Length();
dir *= 1.0f/len;
vector3d _from(from.x, from.y, from.z);
vector3d _dir(dir.x, dir.y, dir.z);
_dir.Normalize();
/* Collide with lovely sphere! */
const vector3d v = _from - sphere.pos;
const double b = -vector3d::Dot(v, dir);
double det = (b*b) - vector3d::Dot(v,v) + (sphere.radius*sphere.radius);
if(det > 0) {
det = sqrt(det);
const double i1 = b - det;
const double i2 = b + det;
if(i2 > 0) {
if(i1 > 0) {
if(i1 < len) {
CollisionContact c;
c.pos = _from + _dir*i1;
c.normal = vector3d::Normalize(v);
c.depth = len - i1;
c.triIdx = 0;
c.userData1 = this->m_data;
c.userData2 = sphere.userData;
c.geomFlag = 0;
(*callback)(&c);
}
}
}
}
}
}
void Geom::Collide(Geom* b, void(*callback)(CollisionContact*)) {
m_moved = false;
for(int i = 0; i < m_geomtree->m_numVertices; i++) {
@ -66,8 +107,9 @@ void Geom::Collide(Geom* b, void(*callback)(CollisionContact*)) {
c.depth = len - isect.dist;
c.triIdx = isect.triIdx;
c.g1 = this;
c.g2 = b;
c.userData1 = m_data;
c.userData2 = b->m_data;
c.geomFlag = b->m_geomtree->GetTriFlag(isect.triIdx);
(*callback)(&c);
}
}

View File

@ -5,6 +5,7 @@
class GeomTree;
class isect_t;
class CollisionContact;
class Sphere;
class Geom {
public:
@ -20,6 +21,7 @@ public:
bool HasMoved(void) { return m_moved; }
GeomTree* GetGeomTree(void) { return m_geomtree; }
void Collide(Geom* b, void(*callback)(CollisionContact*));
void CollideSphere(Sphere& sphere, void (*callback)(CollisionContact*));
void SetUserData(void* d) { m_data = d; }
void* GetUserData(void) { return m_data; }
private:

View File

@ -7,10 +7,12 @@
* You don't need a 'mailbox' as objects only appear once in the hierarchy.
* single ray traversal performance is comparable to kd-tree and way faster than bvh.
*/
#define MAX_LEAF_PRIMS 2
#define MAX_LEAF_PRIMS 1
#define MAX_DEPTH 20
#define MAX_SPLITPOS_RETRIES 32
#define MIN_SPACE_CUTOFF 0.33
#define MIN_SPACE_CUTOFF 0.5
//#define DO_SPACE_CUTOFF
#define NODE_ALLOC_MULT 8
#define EPSILON 0.00001
#include <float.h>
@ -24,6 +26,7 @@
#define MAX(a,b) ((a)>(b) ? (a) : (b))
class DisplayList;
int GeomTree::stats_rayTriIntersections;
struct tri_t {
int triIdx;
@ -120,8 +123,8 @@ GeomTree::GeomTree(int numVerts, int numTris, float* vertices, int* indices,
m_maxAabb.max.x,
m_maxAabb.max.y,
m_maxAabb.max.z);
m_nodes = new BIHNode[numTris*4];
m_nodesAllocSize = numTris*4;
m_nodes = new BIHNode[numTris*NODE_ALLOC_MULT];
m_nodesAllocSize = numTris*NODE_ALLOC_MULT;
m_nodesAllocPos = 0;
m_triAllocPos = 0;
@ -153,6 +156,7 @@ void GeomTree::BihTreeGhBuild(BIHNode* a_node, Aabb& a_box, Aabb& a_splitBox, in
int s1count, s2count, splitAxis, attempt;
attempt = 0;
#ifdef DO_SPACE_CUTOFF
Aabb realAabb;
realAabb.min = vector3d(FLT_MAX, FLT_MAX, FLT_MAX);
realAabb.max = vector3d(-FLT_MAX, -FLT_MAX, -FLT_MAX);
@ -227,7 +231,7 @@ void GeomTree::BihTreeGhBuild(BIHNode* a_node, Aabb& a_box, Aabb& a_splitBox, in
return;
}
}
#endif /* DO_SPACE_CUTOFF */
for(;;) {
splitAxis = 0;
vector3d splitBoxSize = a_splitBox.max - a_splitBox.min;
@ -468,6 +472,7 @@ pop_bstack:
}
void GeomTree::RayTriIntersect(const vector3f& origin, const vector3f& dir, int triIdx, isect_t* isect) {
stats_rayTriIntersections++;
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]]);

View File

@ -27,6 +27,7 @@ public:
const int m_numVertices;
const float* m_vertices;
static int stats_rayTriIntersections;
private:
friend class BIHNode;

View File

@ -91,6 +91,10 @@ Frame::~Frame(void) {
void Frame::AddGeom(Geom* g) { m_collisionSpace->AddGeom(g); }
void Frame::RemoveGeom(Geom* g) { m_collisionSpace->RemoveGeom(g); }
void Frame::SetPlanetGeom(double radius, Body* obj) {
m_collisionSpace->SetSphere(vector3d(0,0,0), radius, static_cast<void*>(obj));
}
void Frame::ApplyLeavingTransform(matrix4x4d& m) const {
m = matrix4x4d::Translation(m_pos) * m_orient * m;
}

View File

@ -36,6 +36,7 @@ public:
void _RemoveGeom(dGeomID g) { dSpaceRemove(m_dSpaceID, g); }
void AddGeom(Geom*);
void RemoveGeom(Geom*);
void SetPlanetGeom(double radius, Body*);
dSpaceID GetSpaceID(void) const { return m_dSpaceID; }
CollisionSpace* GetCollisionSpace(void) const { return m_collisionSpace; }
void RotateInTimestep(double step);

View File

@ -911,8 +911,14 @@ void Planet::Render(const Frame* a_camFrame) {
}
void Planet::SetFrame(Frame* f) {
if(GetFrame()) GetFrame()->_RemoveGeom(geom);
if(GetFrame()) {
GetFrame()->_RemoveGeom(geom);
GetFrame()->SetPlanetGeom(0,0);
}
Body::SetFrame(f);
if(f) f->_AddGeom(geom);
if(f) {
f->_AddGeom(geom);
GetFrame()->SetPlanetGeom(GetRadius(), this);
}
}

View File

@ -160,6 +160,7 @@ float foo[TEXSIZE][TEXSIZE];
float aspectRatio = 1.0;
float camera_zoom = 1.0;
float distance = 100;
extern int stat_rayTriIntersections;
static void raytraceCollMesh(vector3d camPos, vector3d camera_up, vector3d camera_forward, CollisionSpace* space) {
memset(foo, 0, sizeof(float)*TEXSIZE*TEXSIZE);
@ -178,6 +179,7 @@ static void raytraceCollMesh(vector3d camPos, vector3d camera_up, vector3d camer
float ystep = 1.0f / TEXSIZE;
float xpos, ypos;
ypos = 0.0f;
GeomTree::stats_rayTriIntersections = 0;
Uint32 t = SDL_GetTicks();
for(int y = 0; y < TEXSIZE; y++, ypos += ystep) {
@ -198,7 +200,8 @@ static void raytraceCollMesh(vector3d camPos, vector3d camera_up, vector3d camer
}
}
}
printf("%3f million rays/sec\n", (TEXSIZE*TEXSIZE)/(1000.0*(SDL_GetTicks()-t)));
printf("%.3f million rays/sec, %.2f tri isect tests per ray\n", (TEXSIZE*TEXSIZE)/(1000.0*(SDL_GetTicks()-t)),
GeomTree::stats_rayTriIntersections/(float)(TEXSIZE*TEXSIZE));
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_LUMINANCE, GL_FLOAT, foo);
glDisable(GL_DEPTH_TEST);

View File

@ -326,7 +326,7 @@ static void dump_contact(const dContact* c) {
static bool _OnCollision2(Object* o1, Object* o2, CollisionContact* c) {
Body* pb1, *pb2;
int flags = c->g2->GetGeomTree()->GetTriFlag(c->triIdx);
int flags = c->geomFlag;
//printf("Collision flags %x (triIdx %d)\n", flags, c->triIdx);
/* Geom bodies point to their parents. */
if(o1->IsType(Object::GEOM)) {
@ -369,8 +369,19 @@ static void hitCallback(CollisionContact* c) {
contact.fdir1[1] = 0;
contact.fdir1[2] = 0;
Object* po1 = static_cast<Object*>(c->userData1);
Object* po2 = static_cast<Object*>(c->userData2);
if(!_OnCollision2(po1, po2, c)) return;
dBodyID b1 = 0;
dBodyID b2 = 0;
/* Get the dynamics body for each geom. */
if(po1->IsType(Object::DYNAMICBODY)) b1 = static_cast<DynamicBody*>(po1)->m_body;
if(po2->IsType(Object::DYNAMICBODY)) b2 = static_cast<DynamicBody*>(po2)->m_body;
dJointID j = dJointCreateContact(Space::world, _contactgroup, &contact);
dJointAttach(j, (dBodyID)c->g1->GetUserData(), (dBodyID)c->g2->GetUserData());
dJointAttach(j, b1, b2);
}
#if 0