added actual creation of navigation mesh for navmesh modifier

This commit is contained in:
Nick Samarin 2010-06-25 21:08:23 +00:00
parent 543e64c601
commit 4fb80f36e2
4 changed files with 394 additions and 202 deletions

@ -182,7 +182,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories="..\..\..\..\lib\windows\zlib\include;..\..\..\..\build\msvc_9\intern\bsp\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\decimation\include;..\..\..\..\build\msvc_9\intern\elbeem\include;..\..\..\..\build\msvc_9\intern\iksolver\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenkernel\intern;..\..\..\source\blender\makesdna;..\..\..\source\blender\modifiers;..\..\..\source\blender\render\extern\include"
AdditionalIncludeDirectories="..\..\..\..\lib\windows\zlib\include;..\..\..\..\build\msvc_9\intern\bsp\include;..\..\..\..\build\msvc_9\intern\guardedalloc\include;..\..\..\..\build\msvc_9\intern\decimation\include;..\..\..\..\build\msvc_9\intern\elbeem\include;..\..\..\..\build\msvc_9\intern\iksolver\include;..\..\..\source\blender\blenlib;..\..\..\source\blender\blenkernel;..\..\..\source\blender\blenkernel\intern;..\..\..\source\blender\makesdna;..\..\..\source\blender\modifiers;..\..\..\source\blender\render\extern\include;..\..\..\..\build\msvc_9\extern\recastnavigation\Recast\Include"
PreprocessorDefinitions="_DEBUG;WIN32;_LIB;WITH_LZO;WITH_LZMA"
MinimalRebuild="false"
BasicRuntimeChecks="3"
@ -395,7 +395,7 @@
>
</File>
<File
RelativePath="..\..\..\source\blender\modifiers\intern\MOD_navmesh.c"
RelativePath="..\..\..\source\blender\modifiers\intern\MOD_navmesh.cpp"
>
</File>
<File

@ -1,198 +0,0 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2005 by the Blender Foundation.
* All rights reserved.
*
* Contributor(s):
*
* ***** END GPL LICENSE BLOCK *****
*
*/
#include "DNA_meshdata_types.h"
#include "BLI_math.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
static void initData(ModifierData *md)
{
NavMeshModifierData *nmmd = (NavMeshModifierData*) md;
nmmd->cellsize = 0.3f;
nmmd->cellheight = 0.2f;
nmmd->agentmaxslope = 45.0f;
nmmd->agentmaxclimb = 0.9f;
nmmd->agentheight = 2.0f;
nmmd->agentradius = 0.6f;
nmmd->edgemaxlen = 12.0f;
nmmd->edgemaxerror = 1.3f;
nmmd->regionminsize = 50.f;
nmmd->regionmergesize = 20.f;
nmmd->vertsperpoly = 6;
nmmd->detailsampledist = 6.0f;
nmmd->detailsamplemaxerror = 1.0f;
}
static void copyData(ModifierData *md, ModifierData *target)
{
NavMeshModifierData *nmmd = (NavMeshModifierData*) md;
NavMeshModifierData *tnmmd = (NavMeshModifierData*) target;
}
static DerivedMesh *createNavMesh(NavMeshModifierData *mmd,DerivedMesh *dm)
{
int i;
DerivedMesh *result;
int numVerts, numEdges, numFaces;
int maxVerts = dm->getNumVerts(dm);
int maxEdges = dm->getNumEdges(dm);
int maxFaces = dm->getNumFaces(dm);
numVerts = numEdges = numFaces = 0;
result = CDDM_from_template(dm, maxVerts * 2, maxEdges * 2, maxFaces * 2);
for(i = 0; i < maxVerts; i++) {
MVert inMV;
MVert *mv = CDDM_get_vert(result, numVerts);
float co[3];
dm->getVert(dm, i, &inMV);
copy_v3_v3(co, inMV.co);
DM_copy_vert_data(dm, result, i, numVerts, 1);
*mv = inMV;
numVerts++;
{
MVert *mv2 = CDDM_get_vert(result, numVerts);
DM_copy_vert_data(dm, result, i, numVerts, 1);
*mv2 = *mv;
co[2] +=.5f;
copy_v3_v3(mv2->co, co);
numVerts++;
}
}
for(i = 0; i < maxEdges; i++) {
MEdge inMED;
MEdge *med = CDDM_get_edge(result, numEdges);
dm->getEdge(dm, i, &inMED);
DM_copy_edge_data(dm, result, i, numEdges, 1);
*med = inMED;
numEdges++;
med->v1 = inMED.v1*2;
med->v2 = inMED.v2*2;
//med->flag |= ME_EDGEDRAW | ME_EDGERENDER;
{
MEdge *med2 = CDDM_get_edge(result, numEdges);
DM_copy_edge_data(dm, result, i, numEdges, 1);
*med2 = *med;
numEdges++;
med2->v1 += 1;
med2->v2 += 1;
}
}
for(i = 0; i < maxFaces; i++) {
MFace inMF;
MFace *mf = CDDM_get_face(result, numFaces);
dm->getFace(dm, i, &inMF);
DM_copy_face_data(dm, result, i, numFaces, 1);
*mf = inMF;
numFaces++;
mf->v1 = inMF.v1*2;
mf->v2 = inMF.v2*2;
mf->v3 = inMF.v3*2;
mf->v4 = inMF.v4*2;
{
MFace *mf2 = CDDM_get_face(result, numFaces);
DM_copy_face_data(dm, result, i, numFaces, 1);
*mf2 = *mf;
mf2->v1 += 1;
mf2->v2 += 1;
mf2->v3 += 1;
if(inMF.v4) mf2->v4 += 1;
//test_index_face(mf2, &result->faceData, numFaces, inMF.v4?4:3);
numFaces++;
}
}
/*
CDDM_lower_num_verts(result, numVerts);
CDDM_lower_num_edges(result, numEdges);
CDDM_lower_num_faces(result, numFaces);*/
return result;
}
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
int useRenderParams, int isFinalCalc)
{
DerivedMesh *result;
NavMeshModifierData *nmmd = (NavMeshModifierData*) md;
result = createNavMesh(nmmd, derivedData);
return result;
}
ModifierTypeInfo modifierType_NavMesh = {
/* name */ "NavMesh",
/* structName */ "NavMeshModifierData",
/* structSize */ sizeof(NavMeshModifierData),
/* type */ eModifierTypeType_Constructive,
/* flags */ eModifierTypeFlag_AcceptsMesh,
/* copyData */ copyData,
/* deformVerts */ 0,
/* deformVertsEM */ 0,
/* deformMatricesEM */ 0,
/* applyModifier */ applyModifier,
/* applyModifierEM */ 0,
/* initData */ initData,
/* requiredDataMask */ 0,
/* freeData */ 0,
/* isDisabled */ 0,
/* updateDepgraph */ 0,
/* dependsOnTime */ 0,
/* foreachObjectLink */ 0,
/* foreachIDLink */ 0,
};

@ -0,0 +1,392 @@
/*
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2005 by the Blender Foundation.
* All rights reserved.
*
* Contributor(s):
*
* ***** END GPL LICENSE BLOCK *****
*
*/
#include <math.h>
#include "Recast.h"
extern "C"{
#include "DNA_meshdata_types.h"
#include "BLI_math.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
#include "MEM_guardedalloc.h"
static void initData(ModifierData *md)
{
NavMeshModifierData *nmmd = (NavMeshModifierData*) md;
nmmd->cellsize = 0.3f;
nmmd->cellheight = 0.2f;
nmmd->agentmaxslope = 45.0f;
nmmd->agentmaxclimb = 0.9f;
nmmd->agentheight = 2.0f;
nmmd->agentradius = 0.6f;
nmmd->edgemaxlen = 12.0f;
nmmd->edgemaxerror = 1.3f;
nmmd->regionminsize = 50.f;
nmmd->regionmergesize = 20.f;
nmmd->vertsperpoly = 6;
nmmd->detailsampledist = 6.0f;
nmmd->detailsamplemaxerror = 1.0f;
}
static void copyData(ModifierData *md, ModifierData *target)
{
NavMeshModifierData *nmmd = (NavMeshModifierData*) md;
NavMeshModifierData *tnmmd = (NavMeshModifierData*) target;
//.todo - deep copy
}
static DerivedMesh *buildNavMesh(NavMeshModifierData *mmd,DerivedMesh *dm)
{
const int nverts = dm->getNumVerts(dm);
MVert *mvert = dm->getVertArray(dm);
const int nfaces = dm->getNumFaces(dm);
MFace *mface = dm->getFaceArray(dm);
float* verts;
int *tris, *tri;
float bmin[3], bmax[3];
int i,j;
DerivedMesh* result = NULL;
rcHeightfield* solid;
unsigned char *triflags;
rcCompactHeightfield* chf;
rcContourSet *cset;
rcPolyMesh* pmesh;
rcPolyMeshDetail* dmesh;
int numVerts, numEdges, numFaces;
//calculate count of tris
int ntris = nfaces;
for (i=0; i<nfaces; i++)
{
MFace* mf = &mface[i];
if (mf->v4)
ntris+=1;
}
//create verts
verts = (float*) MEM_mallocN(sizeof(float)*3*nverts, "verts");
for (i=0; i<nverts; i++)
{
MVert *v = &mvert[i];
verts[3*i+0] = v->co[0];
verts[3*i+1] = v->co[2];
verts[3*i+2] = v->co[1];
}
//create tris
tris = (int*) MEM_mallocN(sizeof(int)*3*ntris, "faces");
tri = tris;
for (i=0; i<nfaces; i++)
{
MFace* mf = &mface[i];
tri[0]= mf->v1; tri[1]= mf->v3; tri[2]= mf->v2;
tri += 3;
if (mf->v4)
{
tri[0]= mf->v1; tri[1]= mf->v4; tri[2]= mf->v3;
tri += 3;
}
}
rcCalcBounds(verts, nverts, bmin, bmax);
//
// Step 1. Initialize build config.
//
rcConfig cfg;
memset(&cfg, 0, sizeof(cfg));
cfg.cs = mmd->cellsize;
cfg.ch = mmd->cellheight;
cfg.walkableSlopeAngle = mmd->agentmaxslope;
cfg.walkableHeight = (int)ceilf(mmd->agentheight/ cfg.ch);
cfg.walkableClimb = (int)floorf(mmd->agentmaxclimb / cfg.ch);
cfg.walkableRadius = (int)ceilf(mmd->agentradius / cfg.cs);
cfg.maxEdgeLen = (int)(mmd->edgemaxlen/ mmd->cellsize);
cfg.maxSimplificationError = mmd->edgemaxerror;
cfg.minRegionSize = (int)rcSqr(mmd->regionminsize);
cfg.mergeRegionSize = (int)rcSqr(mmd->regionmergesize);
cfg.maxVertsPerPoly = mmd->vertsperpoly;
cfg.detailSampleDist = mmd->detailsampledist< 0.9f ? 0 : mmd->cellsize * mmd->detailsampledist;
cfg.detailSampleMaxError = mmd->cellheight * mmd->detailsamplemaxerror;
// Set the area where the navigation will be build.
vcopy(cfg.bmin, bmin);
vcopy(cfg.bmax, bmax);
rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height);
//
// Step 2. Rasterize input polygon soup.
//
// Allocate voxel heightfield where we rasterize our input data to.
solid = new rcHeightfield;
if (!solid)
return NULL;
if (!rcCreateHeightfield(*solid, cfg.width, cfg.height, cfg.bmin, cfg.bmax, cfg.cs, cfg.ch))
return NULL;
// Allocate array that can hold triangle flags.
triflags = (unsigned char*) MEM_mallocN(sizeof(unsigned char)*ntris, "triflags");
if (!triflags)
return NULL;
// Find triangles which are walkable based on their slope and rasterize them.
memset(triflags, 0, ntris*sizeof(unsigned char));
rcMarkWalkableTriangles(cfg.walkableSlopeAngle, verts, nverts, tris, ntris, triflags);
rcRasterizeTriangles(verts, nverts, tris, triflags, ntris, *solid);
MEM_freeN(triflags);
MEM_freeN(verts);
MEM_freeN(tris);
//
// Step 3. Filter walkables surfaces.
//
rcFilterLedgeSpans(cfg.walkableHeight, cfg.walkableClimb, *solid);
rcFilterWalkableLowHeightSpans(cfg.walkableHeight, *solid);
//
// Step 4. Partition walkable surface to simple regions.
//
chf = new rcCompactHeightfield;
if (!chf)
return NULL;
if (!rcBuildCompactHeightfield(cfg.walkableHeight, cfg.walkableClimb, RC_WALKABLE, *solid, *chf))
return NULL;
delete solid;
// Prepare for region partitioning, by calculating distance field along the walkable surface.
if (!rcBuildDistanceField(*chf))
return NULL;
// Partition the walkable surface into simple regions without holes.
if (!rcBuildRegions(*chf, cfg.walkableRadius, cfg.borderSize, cfg.minRegionSize, cfg.mergeRegionSize))
return NULL;
//
// Step 5. Trace and simplify region contours.
//
// Create contours.
cset = new rcContourSet;
if (!cset)
return NULL;
if (!rcBuildContours(*chf, cfg.maxSimplificationError, cfg.maxEdgeLen, *cset))
return NULL;
//
// Step 6. Build polygons mesh from contours.
//
pmesh = new rcPolyMesh;
if (!pmesh)
return NULL;
if (!rcBuildPolyMesh(*cset, cfg.maxVertsPerPoly, *pmesh))
return NULL;
//
// Step 7. Create detail mesh which allows to access approximate height on each polygon.
//
dmesh = new rcPolyMeshDetail;
if (!dmesh)
return NULL;
if (!rcBuildPolyMeshDetail(*pmesh, *chf, cfg.detailSampleDist, cfg.detailSampleMaxError, *dmesh))
return NULL;
delete chf;
delete cset;
//
// Create blender mesh from detail poly mesh
//
numVerts = dmesh->nverts;
numFaces = dmesh->ntris;
numEdges = dmesh->ntris*3;
result = CDDM_new(numVerts, numEdges, numFaces);
//copy verts
for(i = 0; i < numVerts; i++) {
MVert *mv = CDDM_get_vert(result, i);
copy_v3_v3(mv->co, &dmesh->verts[3*i]);
SWAP(float, mv->co[1], mv->co[2]);
}
//create faces and edges
numFaces = numEdges = 0;
for (i=0; i<dmesh->nmeshes; i++)
{
unsigned short vbase = dmesh->meshes[4*i+0];
unsigned short vnum = dmesh->meshes[4*i+1];
unsigned short tribase = dmesh->meshes[4*i+2];
unsigned short trinum = dmesh->meshes[4*i+3];
for (j=0; j<trinum; j++)
{
unsigned char* tri = &dmesh->tris[4*(tribase+j)];
MFace *mf = CDDM_get_face(result, numFaces);
MEdge *med;
mf->v1 = vbase + tri[0];
mf->v2 = vbase + tri[1];
mf->v3 = vbase + tri[2];
numFaces++;
{
int e1=0, e2=2;
for (;e1<3; e2=e1++)
{
med = CDDM_get_edge(result, numEdges);
med->v1 = vbase + tri[e2];
med->v2 = vbase + tri[e1];
numEdges++;
}
}
}
}
delete pmesh;
delete dmesh;
return result;
}
static DerivedMesh *testCreateNavMesh(NavMeshModifierData *mmd,DerivedMesh *dm)
{
int i;
DerivedMesh *result;
int numVerts, numEdges, numFaces;
int maxVerts = dm->getNumVerts(dm);
int maxEdges = dm->getNumEdges(dm);
int maxFaces = dm->getNumFaces(dm);
/* MVert *mv;
MEdge *med;
MFace *mf;
numVerts = numEdges = numFaces = 0;
result = CDDM_new(3, 3, 1);
mv = CDDM_get_vert(result, 0);
mv->co[0] = -10; mv->co[1] = -10; mv->co[2] = 0;
mv = CDDM_get_vert(result, 1);
mv->co[0] = -10; mv->co[1] = 10; mv->co[2] = 0;
mv = CDDM_get_vert(result, 2);
mv->co[0] = 10; mv->co[1] = -10; mv->co[2] = 0;
med = CDDM_get_edge(result, 0);
med->v1 = 0; med->v1 = 1;
med = CDDM_get_edge(result, 1);
med->v1 = 1; med->v1 = 2;
med = CDDM_get_edge(result, 2);
med->v1 = 2; med->v1 = 0;
mf = CDDM_get_face(result, 0);
mf->v1 = 0; mf->v2 = 1; mf->v3 = 2;
*/
result = CDDM_new(maxVerts, maxEdges, maxFaces);
numVerts = numEdges = numFaces = 0;
for(i = 0; i < maxVerts; i++) {
MVert inMV;
MVert *mv = CDDM_get_vert(result, numVerts);
float co[3];
dm->getVert(dm, i, &inMV);
copy_v3_v3(co, inMV.co);
SWAP(float, co[1], co[2]);
*mv = inMV;
mv->co[2] +=.5f;
numVerts++;
}
for(i = 0; i < maxEdges; i++) {
MEdge inMED;
MEdge *med = CDDM_get_edge(result, numEdges);
dm->getEdge(dm, i, &inMED);
*med = inMED;
numEdges++;
}
for(i = 0; i < maxFaces; i++) {
MFace inMF;
MFace *mf = CDDM_get_face(result, numFaces);
dm->getFace(dm, i, &inMF);
*mf = inMF;
numFaces++;
}
return result;
}
static DerivedMesh *applyModifier(ModifierData *md, Object *ob, DerivedMesh *derivedData,
int useRenderParams, int isFinalCalc)
{
DerivedMesh *result;
NavMeshModifierData *nmmd = (NavMeshModifierData*) md;
//for test
//result = testCreateNavMesh(nmmd, derivedData);
result = buildNavMesh(nmmd, derivedData);
return result;
}
ModifierTypeInfo modifierType_NavMesh = {
/* name */ "NavMesh",
/* structName */ "NavMeshModifierData",
/* structSize */ sizeof(NavMeshModifierData),
/* type */ eModifierTypeType_Constructive,
/* flags */ eModifierTypeFlag_AcceptsMesh,
/* copyData */ copyData,
/* deformVerts */ 0,
/* deformVertsEM */ 0,
/* deformMatricesEM */ 0,
/* applyModifier */ applyModifier,
/* applyModifierEM */ 0,
/* initData */ initData,
/* requiredDataMask */ 0,
/* freeData */ 0,
/* isDisabled */ 0,
/* updateDepgraph */ 0,
/* dependsOnTime */ 0,
/* foreachObjectLink */ 0,
/* foreachIDLink */ 0,
};
};

@ -115,8 +115,6 @@ bool KX_NavMeshObject::BuildVertIndArrays(RAS_MeshObject* meshobj, float *&verti
MFace *mface = dm->getFaceArray(dm);
int numpolys = dm->getNumFaces(dm);
int numverts = dm->getNumVerts(dm);
int* index = (int*)dm->getFaceDataArray(dm, CD_ORIGINDEX);
MTFace *tface = (MTFace *)dm->getFaceDataArray(dm, CD_MTFACE);
nverts = numverts;
if (nverts >= 0xffff)