From 5b1a10b70b3583f1f461d7dfc783d88f1bcd3d37 Mon Sep 17 00:00:00 2001 From: Allanis Date: Tue, 20 Feb 2018 20:09:45 +0000 Subject: [PATCH] [Add] Initial non-accelerating collision space. --- src/collider/Makefile.am | 4 +- src/collider/collision_space.cpp | 29 ++++++++++ src/collider/collision_space.h | 17 ++++++ src/collider/geom.cpp | 29 ++++++++++ src/collider/geom.h | 22 ++++++++ src/collider/geom_tree.cpp | 14 ----- src/matrix4x4.h | 3 +- src/sbre_viewer.cpp | 95 ++++++++++++++++++-------------- src/vector3.h | 3 +- 9 files changed, 156 insertions(+), 60 deletions(-) create mode 100644 src/collider/collision_space.cpp create mode 100644 src/collider/collision_space.h create mode 100644 src/collider/geom.cpp create mode 100644 src/collider/geom.h diff --git a/src/collider/Makefile.am b/src/collider/Makefile.am index 1435d45..6946719 100644 --- a/src/collider/Makefile.am +++ b/src/collider/Makefile.am @@ -1,5 +1,5 @@ noinst_LIBRARIES = libcollider.a -libcollider_a_SOURCES = geom_tree.cpp +libcollider_a_SOURCES = geom_tree.cpp geom.cpp collision_space.cpp -include_HEADERS = geom_tree.h +include_HEADERS = geom_tree.h geom.h collision_space.h diff --git a/src/collider/collision_space.cpp b/src/collider/collision_space.cpp new file mode 100644 index 0000000..9dc850a --- /dev/null +++ b/src/collider/collision_space.cpp @@ -0,0 +1,29 @@ +#include "collision_space.h" +#include "geom.h" +#include "geom_tree.h" + +CollisionSpace::CollisionSpace(void) { + +} + +void CollisionSpace::AddGeom(Geom* geom) { + m_geoms.push_back(geom); +} + +void CollisionSpace::RemoveGeom(Geom* geom) { + m_geoms.remove(geom); +} + +void CollisionSpace::TraceRay(const vector3d& start, const vector3d& dir, isect_t* isect) { + for(std::list::iterator i = m_geoms.begin(); i != m_geoms.end(); ++i) { + if((*i)->IsEnabled()) { + const matrix4x4d& invTrans = (*i)->GetInvTransform(); + vector3d ms = invTrans * start; + vector3d md = invTrans.ApplyRotationOnly(dir); + vector3f modelStart = vector3f(ms.x, ms.y, ms.z); + vector3f modelDir = vector3f(md.x, md.y, md.z); + (*i)->GetGeomTree()->TraceRay(modelStart, modelDir, isect); + } + } +} + diff --git a/src/collider/collision_space.h b/src/collider/collision_space.h new file mode 100644 index 0000000..9619719 --- /dev/null +++ b/src/collider/collision_space.h @@ -0,0 +1,17 @@ +#pragma once +#include +#include "../vector3.h" + +class Geom; +struct isect_t; + +class CollisionSpace { +public: + CollisionSpace(void); + void AddGeom(Geom*); + void RemoveGeom(Geom*); + void TraceRay(const vector3d& start, const vector3d& dir, isect_t* isect); +private: + std::list m_geoms; +}; + diff --git a/src/collider/geom.cpp b/src/collider/geom.cpp new file mode 100644 index 0000000..e316a5e --- /dev/null +++ b/src/collider/geom.cpp @@ -0,0 +1,29 @@ +#include "geom.h" + +Geom::Geom(GeomTree* geomtree) { + m_geomtree = geomtree; + m_orient = matrix4x4d::Identity(); + m_invOrient = matrix4x4d::Identity(); + m_active = true; +} + +void Geom::SetPosition(vector3d pos) { + m_orient[12] = pos.x; + m_orient[13] = pos.y; + m_orient[14] = pos.z; + m_invOrient = m_orient.InverseOf(); +} + +void Geom::SetOrientation(const matrix4x4d& rot) { + m_orient[0] = rot[0]; + m_orient[1] = rot[1]; + m_orient[2] = rot[2]; + m_orient[4] = rot[4]; + m_orient[5] = rot[5]; + m_orient[6] = rot[6]; + m_orient[8] = rot[8]; + m_orient[9] = rot[9]; + m_orient[10] = rot[10]; + m_invOrient = m_orient.InverseOf(); +} + diff --git a/src/collider/geom.h b/src/collider/geom.h new file mode 100644 index 0000000..112256e --- /dev/null +++ b/src/collider/geom.h @@ -0,0 +1,22 @@ +#pragma once +#include "../matrix4x4.h" +#include "../vector3.h" + +class GeomTree; + +class Geom { +public: + Geom(GeomTree*); + void SetPosition(vector3d pos); + void SetOrientation(const matrix4x4d& rot); + const matrix4x4d& GetInvTransform(void) { return m_invOrient; } + void Enable(void) { m_active = true; } + void Disable(void) {m_active = false; } + bool IsEnabled(void) { return m_active; } + GeomTree* GetGeomTree(void) { return m_geomtree; } +private: + matrix4x4d m_orient, m_invOrient; + bool m_active; + GeomTree* m_geomtree; +}; + diff --git a/src/collider/geom_tree.cpp b/src/collider/geom_tree.cpp index d039c35..1686754 100644 --- a/src/collider/geom_tree.cpp +++ b/src/collider/geom_tree.cpp @@ -18,7 +18,6 @@ #include "../aabb.h" #include "geom_tree.h" -#define DEBUG #define MIN(a,b) ((a)<(b) ? (a) : (b)) #define MAX(a,b) ((a)>(b) ? (a) : (b)) @@ -38,8 +37,6 @@ public: SetList(tri); } - float FindNiceSplitPos(int splitAxis, int* numPoints, int* numPrims); - void Dump(int depth, Aabb& box); void SetAxis(int axis) { m_axis = axis; } int GetAxis(void) const { return m_axis; } void SetSplitPos1(float p) { splitPos1 = p; } @@ -258,8 +255,6 @@ void GeomTree::BihTreeGhBuild(BIHNode* a_node, Aabb& a_box, Aabb& a_splitBox, in else right->SetLeaf(true); } -#define SIGN_OF(f) (*((unsigned int*)(&f)) >> 31) - void GeomTree::TraceRay(vector3f& start, vector3f& dir, isect_t* isect) { float len = dir.Length(); isect->dist = len; @@ -272,9 +267,6 @@ void GeomTree::TraverseRay(vector3f& a_origin, vector3f& a_dir, isect_t* isect) float entry_t = 0, exit_t = isect->dist; vector3f rcpD = vector3f(1.0f/a_dir.x, 1.0f/a_dir.y, 1.0f/a_dir.z); int Dneg[3]; -#ifdef DEBUG - int num_raytri_tests = 0; -#endif Dneg[0] = (a_dir.x < 0 ? 1 : 0); Dneg[1] = (a_dir.y < 0 ? 1 : 0); @@ -328,9 +320,6 @@ void GeomTree::TraverseRay(vector3f& a_origin, vector3f& a_dir, isect_t* isect) /* Traverse bih-tree. */ while(currnode) { while (!currnode->IsLeaf()) { -#ifdef DEBUG - //m_stats.treeNodeTraversals++; -#endif const int axis = currnode->GetAxis(); float d[2]; @@ -371,9 +360,6 @@ void GeomTree::TraverseRay(vector3f& a_origin, vector3f& a_dir, isect_t* isect) /* Woop, we are a leaf node. */ for(tri_t* p = currnode->GetList(); p != NULL; p = p->next) { -#ifdef DEBUG - num_raytri_tests++; -#endif RayTriIntersect(a_origin, a_dir, p->triIdx, isect); } diff --git a/src/matrix4x4.h b/src/matrix4x4.h index f90b054..abc7b5f 100644 --- a/src/matrix4x4.h +++ b/src/matrix4x4.h @@ -180,7 +180,8 @@ public: cell[14] = 0; } - T& operator[] (const int i) { return cell[i]; } + T& operator[] (const size_t i) { return cell[i]; } + const T& operator[] (const size_t i) const { return cell[i]; } friend matrix4x4 operator+(const matrix4x4& a, const matrix4x4& b) { matrix4x4 m; for(int i = 0; i < 16; i++) m.cell[i] = a.cell[i] + b.cell[i]; diff --git a/src/sbre_viewer.cpp b/src/sbre_viewer.cpp index 0627767..cacf878 100644 --- a/src/sbre_viewer.cpp +++ b/src/sbre_viewer.cpp @@ -3,6 +3,8 @@ #include "glfreetype.h" #include "gui.h" #include "collider/geom_tree.h" +#include "collider/collision_space.h" +#include "collider/geom.h" static SDL_Surface* g_screen; static int g_width, g_height; @@ -53,7 +55,7 @@ static void PollEvents(void) { static int g_wheelMoveDir = -1; static float g_wheelPos = 0; -static bool g_renderCollMesh = false; +static int g_renderType = 0; static float lightCol[4] = { 1, 1, 1, 0 }; static float lightDir[4] = { 0, 1, 0, 0 }; static float g_frameTime; @@ -100,11 +102,11 @@ public: Gui::Screen::AddBaseWidget(this, 0, 0); SetTransparency(true); { - Gui::ToggleButton* b = new Gui::ToggleButton(); + Gui::Button* b = new Gui::SolidButton(); b->SetShortcut(SDLK_c, KMOD_NONE); - b->onChange.connect(sigc::mem_fun(*this, &Viewer::OnToggleCollMesh)); + b->onClick.connect(sigc::mem_fun(*this, &Viewer::OnClickChangeView)); Add(b, 10, 10); - Add(new Gui::Label("[c] Show collision mesh."), 30, 10); + Add(new Gui::Label("[c] Change view (normal, collision mesh, raytraced collision mesh)"), 30, 10); } { Gui::Button* b = new Gui::SolidButton(); @@ -123,8 +125,9 @@ public: else g_wheelMoveDir = -1; } - void OnToggleCollMesh(Gui::ToggleButton* b, bool state) { - g_renderCollMesh = state; + void OnClickChangeView(void) { + g_renderType++; + if(g_renderType > 2) g_renderType = 0; } void MainLoop(); @@ -136,8 +139,8 @@ static void render_coll_mesh(const CollMesh* m) { glBegin(GL_TRIANGLES); glDepthRange(0.0+g_zbias, 1.0); for(int i = 0; i < m->ni; i += 3) { - glVertex3fv(&m->pVertex[3*m->pIndex[i+1]]); glVertex3fv(&m->pVertex[3*m->pIndex[i]]); + glVertex3fv(&m->pVertex[3*m->pIndex[i+1]]); glVertex3fv(&m->pVertex[3*m->pIndex[i+2]]); } glEnd(); @@ -157,14 +160,14 @@ static void render_coll_mesh(const CollMesh* m) { float foo[512][512]; float aspectRatio = 1.0; float camera_zoom = 1.0; -static void raytraceCollMesh(vector3f camPos, vector3f camera_up, vector3f camera_forward, GeomTree* geomtree) { +static void raytraceCollMesh(vector3d camPos, vector3d camera_up, vector3d camera_forward, CollisionSpace* space) { memset(foo, 0, sizeof(float)*512*512); - vector3f toPoint, xMov, yMov; + vector3d toPoint, xMov, yMov; - vector3f topLeft, topRight, botRight, cross; + vector3d topLeft, topRight, botRight, cross; topLeft = topRight = botRight = camera_forward + camera_zoom; - cross = vector3f::Cross (camera_forward, camera_up) * aspectRatio; + cross = vector3d::Cross (camera_forward, camera_up) * aspectRatio; topLeft = topLeft + camera_up - cross; topRight = topRight + camera_up + cross; botRight = botRight - camera_up + cross; @@ -185,7 +188,7 @@ static void raytraceCollMesh(vector3f camPos, vector3f camera_up, vector3f camer toPoint *= 10000; isect_t isect; - geomtree->TraceRay(camPos, toPoint, &isect); + space->TraceRay(camPos, toPoint, &isect); if(isect.triIdx != -1) { foo[x][y] = 10.0/isect.dist; @@ -213,17 +216,19 @@ static void raytraceCollMesh(vector3f camPos, vector3f camera_up, vector3f camer glBindTexture(GL_TEXTURE_2D, mytexture); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBegin(GL_TRIANGLE_FAN); - glTexCoord2i(1,1); - glVertex3f(1,1,0); glTexCoord2i(0,1); - glVertex3f(0,1,0); + glVertex3f(1,1,0); + glTexCoord2i(0,0); - glVertex3f(0,0,0); + glVertex3f(0,1,0); + glTexCoord2i(1,0); + glVertex3f(0,0,0); + + glTexCoord2i(1,1); glVertex3f(1,0,0); glEnd(); glDisable(GL_TEXTURE_2D); - printf("done..\n"); } void Viewer::MainLoop(void) { @@ -234,9 +239,18 @@ void Viewer::MainLoop(void) { CollMesh* cmesh = (CollMesh*)calloc(1, sizeof(CollMesh)); sbreGenCollMesh(cmesh, g_model, ¶ms, 1.0f); + /* TODO: Flip Z & X because sbre is in magicspace. */ + for(int i = 0; i < 3*cmesh->nv; i+=3) { + cmesh->pVertex[i] = -cmesh->pVertex[i]; + cmesh->pVertex[i+2] = -cmesh->pVertex[i+2]; + } + Uint32 t= SDL_GetTicks(); GeomTree* geomtree = new GeomTree(cmesh->ni/3, cmesh->pVertex, cmesh->pIndex); printf("Geom tree build in $dms\n", SDL_GetTicks() -t); + Geom* geom = new Geom(geomtree); + CollisionSpace* space = new CollisionSpace(); + space->AddGeom(geom); for(;;) { PollEvents(); @@ -248,8 +262,8 @@ void Viewer::MainLoop(void) { if(g_keyState[SDLK_EQUALS]) distance *= pow(0.5, g_frameTime); if(g_keyState[SDLK_MINUS]) distance *= pow(2.0, g_frameTime); if(g_mouseButton[1] || g_mouseButton[3]) { - float rx = 0.01*g_mouseMotion[1]; - float ry = 0.01*g_mouseMotion[0]; + float rx = -0.01*g_mouseMotion[1]; + float ry = -0.01*g_mouseMotion[0]; rot = matrix4x4d::RotateXMatrix(rx) * rot; rot = matrix4x4d::RotateYMatrix(ry) * rot; } @@ -263,37 +277,34 @@ void Viewer::MainLoop(void) { glClearColor(0,0,0,0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glPushAttrib(GL_ALL_ATTRIB_BITS); - if(!g_renderCollMesh) { - SetSbreParams(); - sbreSetViewport(g_width, g_height, g_width*0.5, 1.0f, 10000.0f, 0.0f, 1.0f); - sbreSetDirLight(lightCol, lightDir); + if(g_renderType == 0) { + glPushAttrib(GL_ALL_ATTRIB_BITS); + SetSbreParams(); + sbreSetViewport(g_width, g_height, g_width*0.5, 1.0f, 10000.0f, 0.0f, 1.0f); + sbreSetDirLight(lightCol, lightDir); - Matrix m; - Vector p; - m.x1 = rot[0]; m.x2 = rot[4]; m.x3 = rot[ 8]; - m.y1 = rot[1]; m.y2 = rot[5]; m.y3 = rot[ 9]; - m.z1 = rot[2]; m.z2 = rot[6]; m.z3 = rot[10]; - p.x = 0; p.y = 0; p.z = distance; - if(g_renderCollMesh) { + Matrix m; + Vector p; + m.x1 = rot[0]; m.x2 = rot[4]; m.x3 = -rot[8]; + m.y1 = rot[1]; m.y2 = rot[5]; m.y3 = -rot[9]; + m.z1 = -rot[2]; m.z2 = -rot[6]; m.z3 = rot[10]; + p.x = 0; p.y = 0; p.z = distance; + sbreRenderModel(&p, &m, g_model, ¶ms); + glPopAttrib(); + } else if(g_renderType == 1) { glPushMatrix(); - glTranslatef(p.x, p.y, p.z); + glTranslatef(0, 0, -distance); glMultMatrixd(&rot[0]); render_coll_mesh(cmesh); glPopMatrix(); //sbreRenderCollMesh(cmesh, &p, &m); - } - else sbreRenderModel(&p, &m, g_model, ¶ms); - } else { - vector3d _p = rot * vector3d(0,0,-distance); - vector3f camPos(_p.x, _p.y, _p.z); - vector3f forward = -vector3f::Normalize(camPos); - vector3f up = vector3f::Cross(vector3f(0,1,0), forward); - up.Normalize(); - raytraceCollMesh(camPos, up, forward, geomtree); + geom->SetOrientation(rot); + vector3d camPos = vector3d(0, 0, distance); + vector3d forward = vector3d(0,0,-1); + vector3d up = vector3d(0, 1, 0); + raytraceCollMesh(camPos, up, forward, space); } - glPopAttrib(); Gui::Draw(); diff --git a/src/vector3.h b/src/vector3.h index c7146b9..5a2d6b2 100644 --- a/src/vector3.h +++ b/src/vector3.h @@ -12,7 +12,8 @@ public: vector3(const double vals[3]): x(vals[0]), y(vals[1]), z(vals[2]) { } vector3(const float vals[3]) : x(vals[0]), y(vals[1]), z(vals[2]) { } - T& operator[] (const int i) { return ((T*)this)[i]; } + const T& operator[] (const size_t i) const { return ((const T*)this)[i]; } + T& operator[] (const size_t i) { return ((T*)this)[i]; } vector3 operator+ (const vector3 a) const { return vector3 (a.x+x, a.y+y, a.z+z); } vector3& operator+= (const vector3 a) { x+=a.x; y+=a.y; z+=a.z; return *this; } vector3& operator-= (const vector3 a) { x-=a.x; y-=a.y; z-=a.z; return *this; }