c++ - 3D Barycentric point Intersection -
i'm first going start saying, yes have looked not days or hours, literally months in problem. tackle problems head on, today i'm absolutely stuck.
i'm trying determine if point within triangle in 3d space, , have following code in place attempt detect it.
the test:
bool d3dhandler::iscollidingwithterrain(d3dxvector3 pos){ (unsigned int = 1; < chunk.at(0).getwidth()-1; i++){ (unsigned int ii = 1; ii < chunk.at(0).getwidth()-1; ii++){ if (physics::polypointcollision( normalvertex{ chunk.at(0).getvertex(i, ii).x, chunk.at(0).getvertex(i, ii).y, chunk.at(0).getvertex(i, ii).z, { 0, 0, 0 } }, normalvertex{ chunk.at(0).getvertex(i + 1, ii).x, chunk.at(0).getvertex(i + 1, ii).y, chunk.at(0).getvertex(i + 1, ii).z, { 0, 0, 0 } }, normalvertex{ chunk.at(0).getvertex(i, ii + 1).x, chunk.at(0).getvertex(i, ii + 1).y, chunk.at(0).getvertex(i, ii + 1).z, { 0, 0, 0 } }, normalvertex{ pos.x, pos.y, pos.z, { 0, 0, 0 } }) || physics::polypointcollision( normalvertex{ chunk.at(0).getvertex(i, ii).x, chunk.at(0).getvertex(i, ii).y, chunk.at(0).getvertex(i, ii).z, { 0, 0, 0 } }, normalvertex{ chunk.at(0).getvertex(i - 1, ii).x, chunk.at(0).getvertex(i - 1, ii).y, chunk.at(0).getvertex(i - 1, ii).z, { 0, 0, 0 } }, normalvertex{ chunk.at(0).getvertex(i, ii - 1).x, chunk.at(0).getvertex(i, ii - 1).y, chunk.at(0).getvertex(i, ii - 1).z, { 0, 0, 0 } }, normalvertex{ pos.x, pos.y, pos.z, { 0, 0, 0 } })){ return true; } } } return false; }
the function in question:
bool physics::polypointcollision(normalvertex a, normalvertex b, normalvertex c, normalvertex p){ normalvertex v0 = { c.x - a.x, c.y - a.y, c.z - a.z, { 0, 0, 0 } }; normalvertex v1 = { b.x - a.x, b.y - a.y, b.z - a.z, { 0, 0, 0 } }; normalvertex v2 = { p.x - a.x, p.y - a.y, p.z - a.z, { 0, 0, 0 } }; float dot00 = (v0.x*v0.x) + (v0.y*v0.y) + (v0.z * v0.z); float dot01 = (v0.x*v1.x) + (v0.y*v1.y) + (v0.z * v1.z); float dot02 = (v0.x*v2.x) + (v0.y*v2.y) + (v0.z * v2.z); float dot11 = (v1.x*v1.x) + (v1.y*v1.y) + (v1.z * v1.z); float dot12 = (v1.x*v2.x) + (v1.y*v2.y) + (v1.z * v2.z); float invdenom = 1 / ((dot00*dot11) - (dot01*dot01)); float u = ((dot11*dot02) - (dot01*dot12))*invdenom; float v = ((dot00*dot12) - (dot01*dot02))*invdenom; if (u >= 0 && v >= 0 && (v + u)<1){ return true; } return false; }
what doing here converting 3 points in mesh terrain converted in triangles, sending function convert in test determine if point within triangle using barycentric coordinates. however, works extent, if enter x-z plane of triangle, test return true, not detect along y axis. question how function detect z axis know point within triangle's bounds in axis.
here screenshot of engine making exact situation i'm trying explain.
http://i.stack.imgur.com/kfqnl.png
edit:
d3dhandler.h class:
class d3dhandler{ public: d3dhandler(hwnd hwnd,int winx,int winy,hinstance hinstance, hinstance hprevinstance, lpstr lpcmdline, int ncmdshow); ~d3dhandler(); bool iscollidingwithterrain(d3dxvector3 pos); bool devicecheck(); void unlockbuffer(); void lockbuffer(); void print2dpixel(int x,int y,int r,int g,int b); void print2dpixel(int x,int y,d3dcolor c); void printvertexarray(normalvertex *vertex,int length); void printindexarray(normalvertex *vertex,short *indicies,int vlength,int ilength); void printvertexarraywireframe(normalvertex *vertex,int length); void printindexarraywireframe(normalvertex *vertex,short *indicies,int vlength,int ilength); void prepareframe(player p); void setuplight(); void addobjecttoroom(normalvertex* model,int mlength,short *modelindices,int ilength,d3dxcolor dcol,d3dxcolor acol); void addobjecttoroom(texvertex* model,int mlength,short *modelindices,int ilength,d3dxcolor dcol,d3dxcolor acol,int texid); void addobjecttoroom(float xpos,float ypos,float zpos,wchar_t meshname); boolean checkroom(); void renderroom(); void renderterrain(); void clearbuffer(); void setrenders(); void loadroom(); void presentparams(); void newfont(lpctstr facename,int size,int thickness, bool italic); idirect3ddevice9* getdevice(); lpdirect3dtexture9 grabtexture(int index); void presentframe(); d3dmesh* grabmesh(wchar_t meshname); void renderfont(int fontid,char* text,int x,int y,d3dcolor colour,lpd3dxsprite sprite,dword alignment); void resetdevice(hwnd hwnd); void rebootdevice(hwnd hwnd); bool isactive; private: d3dviewport9 viewport; d3dpresent_parameters d3dpp; d3droom *room; d3dxmatrix matrotatex,matrotatey,matrotatez,mattranslate,matscale,matview,matprojection; d3dlight9 light; d3dmaterial9 material; idirect3d9* pdirect3d; idirect3ddevice9* pdevice; idirect3dsurface9* pbackbuffer; d3dlocked_rect backrect; lpdirect3dvertexbuffer9 vbuffer; lpdirect3dindexbuffer9 ibuffer; hwnd hwind; std::vector<d3dterrain> chunk; std::vector<d3dfont> font; std::vector<lpdirect3dtexture9> texture; std::vector<d3dmesh> mesh; int winx,winy; hinstance hinst; hinstance hprev; lpstr lpcmdlne; int ncmdshw; };
d3dterrain class (it "chunk" is):
class d3dterrain{ public: d3dterrain(float xpos,float ypos,float zpos); ~d3dterrain(); void render(lpdirect3ddevice9 pdevice); void load(lpdirect3ddevice9 pdevice); void load(lpdirect3ddevice9 pdevice,char* fname,wchar_t* tname); void release(){vbuffer->release();ibuffer->release();m_texture->release();m_texturedetail->release();m_vertecies=null;m_indices=null;m_height=null;} tex2vertex getvertex(unsigned int x,unsigned int y){return m_vertex[x*(int)m_width+y];} uint getwidth(){return m_width;} private: idirect3dvertexbuffer9 *vbuffer; idirect3dindexbuffer9 *ibuffer; tex2vertex *m_vertex; uchar* m_height; uint m_vertecies; uint m_indices; uint m_width; char m_fileloc[128]; wchar_t m_texturename[128]; lpdirect3dtexture9 m_texture,m_texturedetail; d3dxmatrix m_rotx,m_roty,m_rotz,m_translate,m_scale,m_texturecords; };
vertex types:
struct normalvertex{ float x, y, z; d3dvector normal; }; struct t_normalvertex{ float x, y, z; d3dvector normal; float u, v; }; struct texvertex{ float x, y, z; float u, v; }; struct tex2vertex{ float x, y, z; float u1, u2, v1, v2; };
i'm not here critique on programming, it's messy trying major function working , optimize , reorganize code, it's personal project, , know it's rough.
alright, whatever reason previous way approached incorrect, looked mathematical definition of how find barycentric coordinates, involved vector lengths , cross product. while square rooting slow, works, tweaking way function works in future , trying clean , optimize best ability, how went fixing issue.
utilityfunctions.h
#include "datatypes.h" namespace util{ float map(float in, float mina, float maxa, float minb, float maxb); float dot(float ax, float ay, float az, float bx, float by, float bz); float dot(point3d a, point3d b); float length(point3d p); point3d sub(point3d a, point3d b); point3d tobarycentric(point3d a, point3d b, point3d c, point3d p); point3d cross(point3d a, point3d b); };
utilityfunctions.cpp
#include <vector> #include <stdio.h> #include <math.h> #include "utilityfunctions.h" float util::map(float in, float mina, float maxa, float minb, float maxb){ float ratio = 0.0f; if (abs(maxa - mina)>0){ ratio = (maxb - minb) / (maxa - mina); } return (in - mina)*ratio + minb; } float util::dot(float ax, float ay, float az, float bx, float by, float bz){ return (ax*bx) + (ay*by) + (az*bz); } float util::dot(point3d a, point3d b){ return (a.x*b.x) + (a.y*b.y) + (a.z*b.z); } float util::length(point3d p){ return ((p.x*p.x) + (p.y*p.y) + (p.z*p.z)); } point3d util::cross(point3d a, point3d b){ return{ ((a.y*b.z) - (a.z*b.y)), ((a.x*b.z) - (a.z*b.x)), ((a.x*b.y) - (a.y*b.x)) }; } point3d util::sub(point3d a, point3d b){ return{ a.x - b.x, a.y - b.y, a.z - b.z }; } point3d util::tobarycentric(point3d a, point3d b, point3d c, point3d p){ point3d v0 = sub(c, a); point3d v1 = sub(b, a); point3d v2 = sub(p, a); point3d v12 = cross(v1, v2); point3d v10 = cross(v1, v0); if (dot(v12, v10) < 0){ return{ 0, 0, -1 }; } point3d v02 = cross(v0, v2); point3d v01 = cross(v0, v1); if (dot(v02, v01) < 0){ return{ 0, 0, -1 }; } float denom = length(v01); return{ length(v12) / denom, length(v02) / denom, 0 }; }
physicsfunctions.cpp
#include "physicshandler.h" bool physics::polypointcollision(point3d a,point3d b,point3d c,point3d p){ point3d w = util::tobarycentric(a, b, c, p); if (w.x+w.y<=1&&w.z>=0){ return true; } return false; }
the topmost function:
bool d3dhandler::iscollidingwithterrain(d3dxvector3 pos){ point3d pointpos = { pos.x, pos.y, pos.z }; (unsigned int = 1; < chunk.at(0).getwidth() - 1; i++){ (unsigned int ii = 1; ii < chunk.at(0).getwidth() - 1; ii++){ point3d originvertex = chunk.at(0).getvertex(i, ii); if (physics::polypointcollision(originvertex,chunk.at(0).getvertex(i + 1, ii), chunk.at(0).getvertex(i, ii + 1),pointpos)){ return true; } if (physics::polypointcollision(originvertex,chunk.at(0).getvertex(i - 1, ii), chunk.at(0).getvertex(i, ii - 1),pointpos)){ return true; } } } return false; }
proof / test results: http://imgur.com/a/hh2pp
Comments
Post a Comment