Work on conversion of the navigation mesh: we build navmesh directly from blender mesh using custom face data, when no custom data provided we use RAS_MeshObject interface

This commit is contained in:
Nick Samarin
2010-07-09 22:22:51 +00:00
parent 36e27b0765
commit 852b84745c
6 changed files with 476 additions and 148 deletions

View File

@@ -102,7 +102,7 @@ KX_GameObject::KX_GameObject(
m_pGraphicController(NULL),
m_xray(false),
m_pHitObject(NULL),
m_pObstacle(NULL),
m_pObstacleSimulation(NULL),
m_isDeformable(false)
#ifndef DISABLE_PYTHON
, m_attr_dict(NULL)
@@ -151,11 +151,9 @@ KX_GameObject::~KX_GameObject()
delete m_pGraphicController;
}
if (m_pObstacle)
if (m_pObstacleSimulation)
{
KX_Scene *scene = KX_GetActiveScene();
KX_ObstacleSimulation* obstacleSimulation = scene->GetObstacleSimulation();
obstacleSimulation->DestroyObstacle(m_pObstacle);
m_pObstacleSimulation->DestroyObstacleForObj(this);
}
#ifndef DISABLE_PYTHON

View File

@@ -59,7 +59,7 @@ class KX_IPhysicsController;
class PHY_IGraphicController;
class PHY_IPhysicsEnvironment;
struct Object;
struct KX_Obstacle;
class KX_ObstacleSimulation;
#ifndef DISABLE_PYTHON
/* utility conversion function */
@@ -109,7 +109,7 @@ protected:
MT_CmMatrix4x4 m_OpenGL_4x4Matrix;
KX_Obstacle* m_pObstacle;
KX_ObstacleSimulation* m_pObstacleSimulation;
public:
bool m_isDeformable;
@@ -794,14 +794,14 @@ public:
m_bSuspendDynamics = false;
}
void RegisterObstacle(KX_Obstacle* obstacle)
void RegisterObstacle(KX_ObstacleSimulation* obstacleSimulation)
{
m_pObstacle = obstacle;
m_pObstacleSimulation = obstacleSimulation;
}
void UnregisterObstacle()
{
m_pObstacle = NULL;
m_pObstacleSimulation = NULL;
}

View File

@@ -36,6 +36,7 @@ extern "C" {
#include "BKE_customdata.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_DerivedMesh.h"
#include "BLI_math_vector.h"
}
#include "KX_PythonInit.h"
#include "KX_PyMath.h"
@@ -102,66 +103,316 @@ void KX_NavMeshObject::ProcessReplica()
}
bool KX_NavMeshObject::BuildVertIndArrays(RAS_MeshObject* meshobj, float *&vertices, int& nverts,
unsigned short* &faces, int& npolys)
unsigned short* &polys, int& npolys, unsigned short *&dmeshes,
float *&dvertices, int &ndvertsuniq, unsigned short *&dtris,
int& ndtris, int &vertsPerPoly)
{
if (!meshobj)
{
return false;
}
DerivedMesh* dm = CDDM_from_mesh(meshobj->GetMesh(), NULL);
MVert *mvert = dm->getVertArray(dm);
MFace *mface = dm->getFaceArray(dm);
int numpolys = dm->getNumFaces(dm);
int numverts = dm->getNumVerts(dm);
nverts = numverts;
if (nverts >= 0xffff)
return false;
//calculate count of tris
npolys = numpolys;
for (int p2=0; p2<numpolys; p2++)
DerivedMesh* dm = mesh_create_derived_no_virtual(KX_GetActiveScene()->GetBlenderScene(), GetBlenderObject(),
NULL, CD_MASK_MESH);
int* recastData = (int*) dm->getFaceDataArray(dm, CD_PROP_INT);
if (recastData)
{
MFace* mf = &mface[p2];
if (mf->v4)
npolys+=1;
}
//create from blender mesh using recast data to build navigation
//polygon mesh from detailed triangle mesh
MVert *mvert = dm->getVertArray(dm);
MFace *mface = dm->getFaceArray(dm);
int numfaces = dm->getNumFaces(dm);
int numverts = dm->getNumVerts(dm);
//create verts
vertices = new float[nverts*3];
for (int vi=0; vi<nverts; vi++)
{
MVert *v = &mvert[vi];
for (int j=0; j<3; j++)
vertices[3*vi+j] = v->co[j];
}
//create tris
faces = new unsigned short[npolys*3*2];
memset(faces,0xff,sizeof(unsigned short)*3*2*npolys);
unsigned short *face = faces;
for (int p2=0; p2<numpolys; p2++)
{
MFace* mf = &mface[p2];
face[0]= mf->v1;
face[1]= mf->v2;
face[2]= mf->v3;
face += 6;
if (mf->v4)
if (numfaces==0)
{
face[0]= mf->v1;
face[1]= mf->v3;
face[2]= mf->v4;
face += 6;
return true;
}
//build detailed mesh adjacency
ndtris = numfaces;
dtris = new unsigned short[numfaces*3*2];
memset(dtris, 0xffff, sizeof(unsigned short)*3*2*numfaces);
for (int i=0; i<numfaces;i++)
{
MFace* mf = &mface[i];
dtris[i*3*2+0] = mf->v1;
dtris[i*3*2+1] = mf->v2;
dtris[i*3*2+2] = mf->v3;
}
buildMeshAdjacency(dtris, numfaces, numverts, 3);
//assumption: detailed mesh triangles are sorted by polygon idx
npolys = recastData[numfaces-1] + 1;
dmeshes = new unsigned short[npolys*4];
memset(dmeshes, 0, npolys*4*sizeof(unsigned short));
unsigned short *dmesh = NULL;
int prevpolyidx = -1;
for (int i=0; i<numfaces; i++)
{
int curpolyidx = recastData[i];
if (curpolyidx!=prevpolyidx)
{
if (curpolyidx!=prevpolyidx+1)
{
//error - wrong order of detailed mesh faces
return false;
}
dmesh = dmesh==NULL ? dmeshes : dmesh+4;
dmesh[2] = i; //tbase
dmesh[3] = 0; //tnum
prevpolyidx = curpolyidx;
}
dmesh[3]++;
}
vertsPerPoly = 6;
polys = new unsigned short[npolys*vertsPerPoly*2];
memset(polys, 0xff, sizeof(unsigned short)*vertsPerPoly*2*npolys);
int curpolytri = 0;
for (int polyidx=0; polyidx<npolys; polyidx++)
{
vector<int> poly;
//search border
int btri = -1;
int bedge = -1;
for (int j=0; j<dmeshes[polyidx*4+3] && btri==-1;j++)
{
int curpolytri = dmeshes[polyidx*4+2]+j;
for (int k=0; k<3; k++)
{
unsigned short neighbortri = dtris[curpolytri*3*2+3+k];
if ( neighbortri==0xffff || recastData[neighbortri]!=polyidx)
{
btri = curpolytri;
bedge = k;
break;
}
}
}
if (btri==-1 || bedge==-1)
{
//can't find triangle with border edge
return false;
}
poly.push_back(dtris[btri*3*2+bedge]);
//poly.push_back(detailedpolys[btri*3*2+(bedge+1)%3]);
int tri = btri;
int edge = (bedge+1)%3;
while (tri!=btri || edge!=bedge)
{
int neighbortri = dtris[tri*3*2+3+edge];
if (neighbortri==0xffff || recastData[neighbortri]!=polyidx)
{
//add vertex to current edge
poly.push_back(dtris[tri*3*2+edge]);
//move to next edge
edge = (edge+1)%3;
}
else
{
//move to next tri
int twinedge = -1;
for (int k=0; k<3; k++)
{
if (dtris[neighbortri*3*2+3+k] == tri)
{
twinedge = k;
break;
}
}
if (twinedge==-1)
{
//can't find neighbor edge - invalid adjacency info
return false;
}
tri = neighbortri;
edge = (twinedge+1)%3;
}
}
//.todo: process poly to remove degenerate vertices
if (poly.size()>=vertsPerPoly)
{
printf("Error! Polygon size exceeds max verts count");
return false;
}
for (int i=0; i<poly.size(); i++)
{
polys[polyidx*vertsPerPoly*2+i] = poly[i];
}
}
//assumption: vertices in mesh are stored in following order:
//navigation mesh vertices - unique detailed mesh vertex
unsigned short maxidx = 0;
for (int polyidx=0; polyidx<npolys; polyidx++)
{
for (int i=0; i<vertsPerPoly; i++)
{
unsigned short idx = polys[polyidx*vertsPerPoly*2+i];
if (idx==0xffff)
break;
if (idx>maxidx)
maxidx=idx;
}
}
//create navigation mesh verts
nverts = maxidx+1;
vertices = new float[nverts*3];
for (int vi=0; vi<nverts; vi++)
{
MVert *v = &mvert[vi];
copy_v3_v3(&vertices[3*vi], v->co);
}
//create unique detailed mesh verts
ndvertsuniq = numverts - nverts;
if (ndvertsuniq>0)
{
dvertices = new float[ndvertsuniq*3];
for (int vi=0; vi<ndvertsuniq; vi++)
{
MVert *v = &mvert[nverts+vi];
copy_v3_v3(&dvertices[3*vi], v->co);
}
}
for (int polyIdx=0; polyIdx<npolys; polyIdx++)
{
unsigned short *dmesh = &dmeshes[4*polyIdx];
unsigned short minvert = 0xffff, maxvert = 0;
for (int j=0; j<dmesh[3]; j++)
{
unsigned short* dtri = &dtris[dmesh[2]*3*2+j];
for (int k=0; k<3; k++)
{
if (dtri[k]<nverts)
continue;
minvert = std::min(minvert, dtri[k]);
maxvert = std::max(maxvert, dtri[k]);
}
}
dmesh[0] = minvert; //vbase
dmesh[1] = minvert != 0xffff ? maxvert - minvert + 1 : 0; //vnum
}
//recalculate detailed mesh indices (it must be local)
for (int polyIdx=0; polyIdx<npolys; polyIdx++)
{
unsigned short * poly = &polys[polyIdx*vertsPerPoly*2];
int nv=0;
for (int vi=0; vi<vertsPerPoly; vi++)
{
if (poly[vi]==0xffff)
break;
nv++;
}
unsigned short *dmesh = &dmeshes[4*polyIdx];
for (int j=0; j<dmesh[3]; j++)
{
unsigned short* dtri = &dtris[(dmesh[2]+j)*3*2];
for (int k=0; k<3; k++)
{
if (dtri[k]<nverts)
{
//shared vertex from polygon
unsigned short idx = 0xffff;
for (int vi=0; vi<nv; vi++)
{
if (poly[vi]==dtri[k])
{
idx = vi;
break;
}
}
if (idx==0xffff)
{
printf("Can't find vertex in navigation polygon");
return false;
}
dtri[k] = idx;
}
else
{
dtri[k] = dtri[k]-dmesh[0]+nv;
}
}
}
}
}
else
{
//create from RAS_MeshObject (detailed mesh is fake)
vertsPerPoly = 3;
nverts = meshobj->m_sharedvertex_map.size();
if (nverts >= 0xffff)
return false;
//calculate count of tris
int nmeshpolys = meshobj->NumPolygons();
npolys = nmeshpolys;
for (int p=0; p<nmeshpolys; p++)
{
int vertcount = meshobj->GetPolygon(p)->VertexCount();
npolys+=vertcount-3;
}
//create verts
vertices = new float[nverts*3];
float* vert = vertices;
for (int vi=0; vi<nverts; vi++)
{
const float* pos = !meshobj->m_sharedvertex_map[vi].empty() ? meshobj->GetVertexLocation(vi) : NULL;
if (pos)
copy_v3_v3(vert, pos);
else
{
memset(vert, NULL, 3*sizeof(float)); //vertex isn't in any poly, set dummy zero coordinates
}
vert+=3;
}
//create tris
polys = new unsigned short[npolys*3*2];
memset(polys, 0xff, sizeof(unsigned short)*3*2*npolys);
unsigned short *poly = polys;
RAS_Polygon* raspoly;
for (int p=0; p<nmeshpolys; p++)
{
raspoly = meshobj->GetPolygon(p);
for (int v=0; v<raspoly->VertexCount()-2; v++)
{
poly[0]= raspoly->GetVertex(0)->getOrigIndex();
for (size_t i=1; i<3; i++)
{
poly[i]= raspoly->GetVertex(v+i)->getOrigIndex();
}
poly += 6;
}
}
dmeshes = NULL;
dvertices = NULL;
ndvertsuniq = 0;
dtris = NULL;
ndtris = npolys;
}
dm->release(dm);
dm = NULL;
return true;
}
bool KX_NavMeshObject::BuildNavMesh()
{
if (GetMeshCount()==0)
@@ -169,42 +420,30 @@ bool KX_NavMeshObject::BuildNavMesh()
RAS_MeshObject* meshobj = GetMesh(0);
float* vertices = NULL;
unsigned short* faces = NULL;
int nverts = 0, npolys = 0;
if (!BuildVertIndArrays(meshobj, vertices, nverts, faces, npolys))
float *vertices = NULL, *dvertices = NULL;
unsigned short *polys = NULL, *dtris = NULL, *dmeshes = NULL;
int nverts = 0, npolys = 0, ndvertsuniq = 0, ndtris = 0;
int vertsPerPoly = 0;
if (!BuildVertIndArrays(meshobj, vertices, nverts, polys, npolys,
dmeshes, dvertices, ndvertsuniq, dtris, ndtris, vertsPerPoly )
|| vertsPerPoly<3)
return false;
//prepare vertices and indices
struct Object* blenderobject = GetBlenderObject();
MT_Point3 posobj;
posobj.setValue(blenderobject->loc[0]+blenderobject->dloc[0],
blenderobject->loc[1]+blenderobject->dloc[1],
blenderobject->loc[2]+blenderobject->dloc[2]);
MT_Vector3 eulxyzobj(blenderobject->rot);
MT_Vector3 scaleobj(blenderobject->size);
MT_Matrix3x3 rotMatrix(eulxyzobj);
MT_Transform worldTransform(posobj, rotMatrix.scaled(scaleobj[0], scaleobj[1], scaleobj[2]));
MT_Point3 pos;
for (int i=0; i<nverts; i++)
{
pos.setValue(&vertices[i*3]);
//add world transform
pos = worldTransform(pos);
pos.getValue(&vertices[i*3]);
flipAxes(&vertices[i*3]);
}
/*
//reorder tris
for (int i=0; i<npolys; i++)
{
std::swap(faces[6*i+1], faces[6*i+2]);
std::swap(polys[6*i+1], polys[6*i+2]);
}
const int vertsPerPoly = 3;
buildMeshAdjacency(faces, npolys, nverts, vertsPerPoly);
*/
buildMeshAdjacency(polys, npolys, nverts, vertsPerPoly);
int ndtris = npolys;
int uniqueDetailVerts = 0;
float cs = 0.2f;
if (!nverts || !npolys)
@@ -228,7 +467,7 @@ bool KX_NavMeshObject::BuildNavMesh()
const int polysSize = sizeof(dtStatPoly)*npolys;
const int nodesSize = sizeof(dtStatBVNode)*npolys*2;
const int detailMeshesSize = sizeof(dtStatPolyDetail)*npolys;
const int detailVertsSize = sizeof(float)*3*uniqueDetailVerts;
const int detailVertsSize = sizeof(float)*3*ndvertsuniq;
const int detailTrisSize = sizeof(unsigned char)*4*ndtris;
const int dataSize = headerSize + vertsSize + polysSize + nodesSize +
@@ -260,7 +499,7 @@ bool KX_NavMeshObject::BuildNavMesh()
header->bmax[1] = bmax[1];
header->bmax[2] = bmax[2];
header->ndmeshes = npolys;
header->ndverts = uniqueDetailVerts;
header->ndverts = ndvertsuniq;
header->ndtris = ndtris;
// Store vertices
@@ -275,49 +514,76 @@ bool KX_NavMeshObject::BuildNavMesh()
//memcpy(navVerts, vertices, nverts*3*sizeof(float));
// Store polygons
const int nvp = 3;
const unsigned short* src = faces;
const unsigned short* src = polys;
for (int i = 0; i < npolys; ++i)
{
dtStatPoly* p = &navPolys[i];
p->nv = 0;
for (int j = 0; j < nvp; ++j)
for (int j = 0; j < vertsPerPoly; ++j)
{
if (src[j] == 0xffff) break;
p->v[j] = src[j];
p->n[j] = src[nvp+j]+1;
p->n[j] = src[vertsPerPoly+j]+1;
p->nv++;
}
src += nvp*2;
src += vertsPerPoly*2;
}
header->nnodes = createBVTree(vertsi, nverts, faces, npolys, nvp,
header->nnodes = createBVTree(vertsi, nverts, polys, npolys, vertsPerPoly,
cs, cs, npolys*2, navNodes);
//create fake detail meshes
unsigned short vbase = 0;
for (int i = 0; i < npolys; ++i)
if (dmeshes==NULL)
{
dtStatPolyDetail& dtl = navDMeshes[i];
dtl.vbase = 0;
dtl.nverts = 0;
dtl.tbase = i;
dtl.ntris = 1;
//create fake detail meshes
for (int i = 0; i < npolys; ++i)
{
dtStatPolyDetail& dtl = navDMeshes[i];
dtl.vbase = 0;
dtl.nverts = 0;
dtl.tbase = i;
dtl.ntris = 1;
}
// setup triangles.
unsigned char* tri = navDTris;
for(size_t i=0; i<ndtris; i++)
{
for (size_t j=0; j<3; j++)
tri[4*i+j] = j;
}
}
// setup triangles.
unsigned char* tri = navDTris;
const unsigned short* face = faces;
for(size_t i=0; i<ndtris; i++)
else
{
for (size_t j=0; j<3; j++)
tri[4*i+j] = j;
//verts
memcpy(navDVerts, dvertices, ndvertsuniq*3*sizeof(float));
//tris
unsigned char* tri = navDTris;
for(size_t i=0; i<ndtris; i++)
{
for (size_t j=0; j<3; j++)
tri[4*i+j] = dtris[6*i+j];
}
//detailed meshes
for (int i = 0; i < npolys; ++i)
{
dtStatPolyDetail& dtl = navDMeshes[i];
dtl.vbase = dmeshes[i*4+0];
dtl.nverts = dmeshes[i*4+1];
dtl.tbase = dmeshes[i*4+2];
dtl.ntris = dmeshes[i*4+3];
}
}
m_navMesh = new dtStatNavMesh;
m_navMesh->init(data, dataSize, true);
m_navMesh->init(data, dataSize, true);
delete [] vertices;
delete [] faces;
delete [] polys;
if (dvertices)
{
delete [] dvertices;
}
return true;
}
@@ -332,10 +598,11 @@ void KX_NavMeshObject::DrawNavMesh()
return;
MT_Vector3 color(0.f, 0.f, 0.f);
enum RenderMode {DETAILED_TRIS, WALLS};
static const RenderMode renderMode = DETAILED_TRIS;
enum RenderMode {POLYS ,DETAILED_TRIS, WALLS};
static const RenderMode renderMode = DETAILED_TRIS;//POLYS;
switch (renderMode)
{
case POLYS :
case WALLS :
for (int pi=0; pi<m_navMesh->getPolyCount(); pi++)
{
@@ -343,10 +610,15 @@ void KX_NavMeshObject::DrawNavMesh()
for (int i = 0, j = (int)poly->nv-1; i < (int)poly->nv; j = i++)
{
if (poly->n[j]) continue;
const float* vj = m_navMesh->getVertex(poly->v[j]);
const float* vi = m_navMesh->getVertex(poly->v[i]);
KX_RasterizerDrawDebugLine(MT_Vector3(vj[0], vj[2], vj[1]), MT_Vector3(vi[0], vi[2], vi[1]), color);
if (poly->n[j] && renderMode==DETAILED_TRIS)
continue;
const float* vif = m_navMesh->getVertex(poly->v[i]);
const float* vjf = m_navMesh->getVertex(poly->v[j]);
MT_Point3 vi(vif[0], vif[2], vif[1]);
MT_Point3 vj(vjf[0], vjf[2], vjf[1]);
vi = TransformToWorldCoords(vi);
vj = TransformToWorldCoords(vj);
KX_RasterizerDrawDebugLine(vi, vj, color);
}
}
break;
@@ -359,7 +631,7 @@ void KX_NavMeshObject::DrawNavMesh()
for (int j = 0; j < pd->ntris; ++j)
{
const unsigned char* t = m_navMesh->getDetailTri(pd->tbase+j);
MT_Vector3 tri[3];
MT_Point3 tri[3];
for (int k = 0; k < 3; ++k)
{
const float* v;
@@ -373,6 +645,9 @@ void KX_NavMeshObject::DrawNavMesh()
tri[k].setValue(pos);
}
for (int k=0; k<3; k++)
tri[k] = TransformToWorldCoords(tri[k]);
for (int k=0; k<3; k++)
KX_RasterizerDrawDebugLine(tri[k], tri[(k+1)%3], color);
}
@@ -381,13 +656,37 @@ void KX_NavMeshObject::DrawNavMesh()
}
}
MT_Point3 KX_NavMeshObject::TransformToLocalCoords(const MT_Point3& wpos)
{
MT_Matrix3x3 orientation = NodeGetWorldOrientation();
const MT_Vector3& scaling = NodeGetWorldScaling();
orientation.scale(scaling[0], scaling[1], scaling[2]);
MT_Transform worldtr(NodeGetWorldPosition(), orientation);
MT_Transform invworldtr;
invworldtr.invert(worldtr);
MT_Point3 lpos = invworldtr(wpos);
return lpos;
}
MT_Point3 KX_NavMeshObject::TransformToWorldCoords(const MT_Point3& lpos)
{
MT_Matrix3x3 orientation = NodeGetWorldOrientation();
const MT_Vector3& scaling = NodeGetWorldScaling();
orientation.scale(scaling[0], scaling[1], scaling[2]);
MT_Transform worldtr(NodeGetWorldPosition(), orientation);
MT_Point3 wpos = worldtr(lpos);
return wpos;
}
int KX_NavMeshObject::FindPath(const MT_Point3& from, const MT_Point3& to, float* path, int maxPathLen)
{
if (!m_navMesh)
return 0;
MT_Point3 localfrom = TransformToLocalCoords(from);
MT_Point3 localto = TransformToLocalCoords(to);
float spos[3], epos[3];
from.getValue(spos); flipAxes(spos);
to.getValue(epos); flipAxes(epos);
localfrom.getValue(spos); flipAxes(spos);
localto.getValue(epos); flipAxes(epos);
dtStatPolyRef sPolyRef = m_navMesh->findNearestPoly(spos, polyPickExt);
dtStatPolyRef ePolyRef = m_navMesh->findNearestPoly(epos, polyPickExt);
@@ -401,7 +700,12 @@ int KX_NavMeshObject::FindPath(const MT_Point3& from, const MT_Point3& to, float
{
pathLen = m_navMesh->findStraightPath(spos, epos, polys, npolys, path, maxPathLen);
for (int i=0; i<pathLen; i++)
{
flipAxes(&path[i*3]);
MT_Point3 waypoint(&path[i*3]);
waypoint = TransformToWorldCoords(waypoint);
waypoint.getValue(&path[i*3]);
}
}
}
@@ -412,9 +716,11 @@ float KX_NavMeshObject::Raycast(const MT_Point3& from, const MT_Point3& to)
{
if (!m_navMesh)
return 0.f;
MT_Point3 localfrom = TransformToLocalCoords(from);
MT_Point3 localto = TransformToLocalCoords(to);
float spos[3], epos[3];
from.getValue(spos); flipAxes(spos);
to.getValue(epos); flipAxes(epos);
localfrom.getValue(spos); flipAxes(spos);
localto.getValue(epos); flipAxes(epos);
dtStatPolyRef sPolyRef = m_navMesh->findNearestPoly(spos, polyPickExt);
float t=0;
static dtStatPolyRef polys[MAX_PATH_LEN];

View File

@@ -44,8 +44,10 @@ protected:
dtStatNavMesh* m_navMesh;
bool BuildVertIndArrays(RAS_MeshObject* meshobj, float *&vertices, int& nverts,
unsigned short *&faces, int& npolys);
unsigned short* &polys, int& npolys, unsigned short *&dmeshes,
float *&dvertices, int &ndvertsuniq, unsigned short* &dtris,
int& ndtris, int &vertsPerPoly);
public:
KX_NavMeshObject(void* sgReplicationInfo, SG_Callbacks callbacks);
~KX_NavMeshObject();
@@ -61,7 +63,8 @@ public:
void DrawNavMesh();
void DrawPath(const float *path, int pathLen, const MT_Vector3& color);
MT_Point3 TransformToLocalCoords(const MT_Point3& wpos);
MT_Point3 TransformToWorldCoords(const MT_Point3& lpos);
#ifndef DISABLE_PYTHON
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */

View File

@@ -181,36 +181,22 @@ KX_ObstacleSimulation::~KX_ObstacleSimulation()
}
m_obstacles.clear();
}
KX_Obstacle* KX_ObstacleSimulation::CreateObstacle()
KX_Obstacle* KX_ObstacleSimulation::CreateObstacle(KX_GameObject* gameobj)
{
KX_Obstacle* obstacle = new KX_Obstacle();
obstacle->m_gameObj = gameobj;
gameobj->RegisterObstacle(this);
m_obstacles.push_back(obstacle);
return obstacle;
}
void KX_ObstacleSimulation::AddObstacleForObj(KX_GameObject* gameobj)
{
KX_Obstacle* obstacle = CreateObstacle();
KX_Obstacle* obstacle = CreateObstacle(gameobj);
struct Object* blenderobject = gameobj->GetBlenderObject();
obstacle->m_type = KX_OBSTACLE_OBJ;
obstacle->m_shape = KX_OBSTACLE_CIRCLE;
obstacle->m_rad = blenderobject->obstacleRad;
obstacle->m_gameObj = gameobj;
gameobj->RegisterObstacle(obstacle);
}
void KX_ObstacleSimulation::DestroyObstacle(KX_Obstacle* obstacle)
{
for (size_t i=0; i<m_obstacles.size(); i++)
{
if (m_obstacles[i] == obstacle)
{
obstacle->m_gameObj->UnregisterObstacle();
m_obstacles[i] = m_obstacles.back();
m_obstacles.pop_back();
delete obstacle;
}
}
}
void KX_ObstacleSimulation::AddObstaclesForNavMesh(KX_NavMeshObject* navmeshobj)
@@ -229,12 +215,11 @@ void KX_ObstacleSimulation::AddObstaclesForNavMesh(KX_NavMeshObject* navmeshobj)
const float* vj = navmesh->getVertex(poly->v[j]);
const float* vi = navmesh->getVertex(poly->v[i]);
KX_Obstacle* obstacle = CreateObstacle();
KX_Obstacle* obstacle = CreateObstacle(navmeshobj);
obstacle->m_type = KX_OBSTACLE_NAV_MESH;
obstacle->m_shape = KX_OBSTACLE_SEGMENT;
obstacle->m_gameObj = navmeshobj;
obstacle->m_pos = MT_Vector3(vj[0], vj[2], vj[1]);
obstacle->m_pos2 = MT_Vector3(vi[0], vi[2], vi[1]);
obstacle->m_pos = MT_Point3(vj[0], vj[2], vj[1]);
obstacle->m_pos2 = MT_Point3(vi[0], vi[2], vi[1]);
obstacle->m_rad = 0;
obstacle->m_vel = MT_Vector2(0,0);
}
@@ -242,11 +227,28 @@ void KX_ObstacleSimulation::AddObstaclesForNavMesh(KX_NavMeshObject* navmeshobj)
}
}
void KX_ObstacleSimulation::DestroyObstacleForObj(KX_GameObject* gameobj)
{
for (size_t i=0; i<m_obstacles.size(); )
{
if (m_obstacles[i]->m_gameObj == gameobj)
{
KX_Obstacle* obstacle = m_obstacles[i];
obstacle->m_gameObj->UnregisterObstacle();
m_obstacles[i] = m_obstacles.back();
m_obstacles.pop_back();
delete obstacle;
}
else
i++;
}
}
void KX_ObstacleSimulation::UpdateObstacles()
{
for (size_t i=0; i<m_obstacles.size(); i++)
{
if (m_obstacles[i]->m_shape==KX_OBSTACLE_NAV_MESH || m_obstacles[i]->m_shape==KX_OBSTACLE_SEGMENT)
if (m_obstacles[i]->m_type==KX_OBSTACLE_NAV_MESH || m_obstacles[i]->m_shape==KX_OBSTACLE_SEGMENT)
continue;
KX_Obstacle* obs = m_obstacles[i];
@@ -281,7 +283,17 @@ void KX_ObstacleSimulation::DrawObstacles()
{
if (m_obstacles[i]->m_shape==KX_OBSTACLE_SEGMENT)
{
KX_RasterizerDrawDebugLine(m_obstacles[i]->m_pos, m_obstacles[i]->m_pos2, bluecolor);
MT_Point3 p1 = m_obstacles[i]->m_pos;
MT_Point3 p2 = m_obstacles[i]->m_pos2;
//apply world transform
if (m_obstacles[i]->m_type == KX_OBSTACLE_NAV_MESH)
{
KX_NavMeshObject* navmeshobj = static_cast<KX_NavMeshObject*>(m_obstacles[i]->m_gameObj);
p1 = navmeshobj->TransformToWorldCoords(p1);
p2 = navmeshobj->TransformToWorldCoords(p2);
}
KX_RasterizerDrawDebugLine(p1, p2, bluecolor);
}
else if (m_obstacles[i]->m_shape==KX_OBSTACLE_CIRCLE)
{
@@ -351,9 +363,9 @@ KX_ObstacleSimulationTOI::~KX_ObstacleSimulationTOI()
m_toiCircles.clear();
}
KX_Obstacle* KX_ObstacleSimulationTOI::CreateObstacle()
KX_Obstacle* KX_ObstacleSimulationTOI::CreateObstacle(KX_GameObject* gameobj)
{
KX_Obstacle* obstacle = KX_ObstacleSimulation::CreateObstacle();
KX_Obstacle* obstacle = KX_ObstacleSimulation::CreateObstacle(gameobj);
m_toiCircles.push_back(new TOICircle());
return obstacle;
}
@@ -406,7 +418,7 @@ void KX_ObstacleSimulationTOI::AdjustObstacleVelocity(KX_Obstacle* activeObst, K
float htmin,htmax;
if (ob->m_type == KX_OBSTACLE_CIRCLE)
if (ob->m_shape == KX_OBSTACLE_CIRCLE)
{
MT_Vector2 vab;
if (ob->m_vel.length2() < 0.01f*0.01f)
@@ -424,10 +436,19 @@ void KX_ObstacleSimulationTOI::AdjustObstacleVelocity(KX_Obstacle* activeObst, K
vab, ob->m_pos, ob->m_rad, htmin, htmax))
continue;
}
else if (ob->m_type == KX_OBSTACLE_SEGMENT)
else if (ob->m_shape == KX_OBSTACLE_SEGMENT)
{
MT_Point3 p1 = ob->m_pos;
MT_Point3 p2 = ob->m_pos2;
//apply world transform
if (ob->m_type == KX_OBSTACLE_NAV_MESH)
{
KX_NavMeshObject* navmeshobj = static_cast<KX_NavMeshObject*>(ob->m_gameObj);
p1 = navmeshobj->TransformToWorldCoords(p1);
p2 = navmeshobj->TransformToWorldCoords(p2);
}
if (!sweepCircleSegment(activeObst->m_pos, activeObst->m_rad, svel,
ob->m_pos, ob->m_pos2, ob->m_rad, htmin, htmax))
p1, p2, ob->m_rad, htmin, htmax))
continue;
}

View File

@@ -75,7 +75,7 @@ protected:
MT_Scalar m_levelHeight;
virtual KX_Obstacle* CreateObstacle();
virtual KX_Obstacle* CreateObstacle(KX_GameObject* gameobj);
bool FilterObstacle(KX_Obstacle* activeObstacle, KX_NavMeshObject* activeNavMeshObj, KX_Obstacle* otherObstacle);
public:
KX_ObstacleSimulation(MT_Scalar levelHeight);
@@ -84,7 +84,7 @@ public:
void DrawObstacles();
void AddObstacleForObj(KX_GameObject* gameobj);
void DestroyObstacle(KX_Obstacle* obstacle);
void DestroyObstacleForObj(KX_GameObject* gameobj);
void AddObstaclesForNavMesh(KX_NavMeshObject* navmesh);
KX_Obstacle* GetObstacle(KX_GameObject* gameobj);
void UpdateObstacles();
@@ -115,7 +115,7 @@ protected:
float m_collisionWeight; // Sample selection collision weight
std::vector<TOICircle*> m_toiCircles; // TOI circles (one per active agent)
virtual KX_Obstacle* CreateObstacle();
virtual KX_Obstacle* CreateObstacle(KX_GameObject* gameobj);
public:
KX_ObstacleSimulationTOI(MT_Scalar levelHeight);
~KX_ObstacleSimulationTOI();