void Foam::patchInjectionBase::updateMesh(const polyMesh& mesh)
{
    // Set/cache the injector cells
    const polyPatch& patch = mesh.boundaryMesh()[patchId_];
    const pointField& points = patch.points();

    cellOwners_ = patch.faceCells();

    // Triangulate the patch faces and create addressing
    DynamicList<label> triToFace(2*patch.size());
    DynamicList<scalar> triMagSf(2*patch.size());
    DynamicList<face> triFace(2*patch.size());
    DynamicList<face> tris(5);

    // Set zero value at the start of the tri area list
    triMagSf.append(0.0);

    forAll(patch, facei)
    {
        const face& f = patch[facei];

        tris.clear();
        f.triangles(points, tris);

        forAll(tris, i)
        {
            triToFace.append(facei);
            triFace.append(tris[i]);
            triMagSf.append(tris[i].mag(points));
        }
    }
void Foam::stl<Type>::write
(
    const fileName& samplePath,
    const fileName& timeDir,
    const fileName& surfaceName,
    const pointField& points,
    const faceList& faces,
    const fileName& fieldName,
    const Field<Type>& values,
    const bool verbose
) const
{
    fileName surfaceDir(samplePath/timeDir);

    if (!exists(surfaceDir))
    {
        mkDir(surfaceDir);
    }

    fileName planeFName(surfaceDir/fieldName + '_' + surfaceName + ".stl");

    if (verbose)
    {
        Info<< "Writing field " << fieldName << " to " << planeFName << endl;
    }

    // Convert faces to triangles.
    DynamicList<labelledTri> tris(faces.size());

    forAll(faces, i)
    {
        const face& f = faces[i];

        faceList triFaces(f.nTriangles(points));
        label nTris = 0;
        f.triangles(points, nTris, triFaces);

        forAll(triFaces, triI)
        {
            const face& tri = triFaces[triI];
            tris.append(labelledTri(tri[0], tri[1], tri[2], 0));
        }
    }

    triSurface
    (
        tris.shrink(),
        geometricSurfacePatchList
        (
            1,
            geometricSurfacePatch
            (
                "patch",                            // geometricType
                string::validate<word>(fieldName),  // fieldName
                0                                   // index
            )
        ),
        points
    ).write(planeFName);
}
Beispiel #3
0
void csBSPTree::Build (CS::TriangleIndicesStream<int>& triangles,
	               const csVector3* vertices)
{
  const size_t triComponents = triangles.GetRemainingComponents();
  csDirtyAccessArray<csPlane3> planes ((triComponents+2)/3);
  csArray<int> triidx;
  csDirtyAccessArray<csTriangle> tris ((triComponents+2)/3);
  while (triangles.HasNext())
  {
    CS::TriangleT<int> t (triangles.Next());
    planes.Push (csPlane3 (vertices[t.a], vertices[t.b], vertices[t.c]));
    triidx.Push (int (tris.Push (t)));
  }

  Build (tris.GetArray(), planes.GetArray(), tris.GetSize(), vertices, triidx);
}
	bool PhysicsGeometry::load(FS::IFile& file)
	{
		Header header;
		file.read(&header, sizeof(header));
		if (header.m_magic != HEADER_MAGIC || header.m_version > (uint32)Versions::LAST)
		{
			return false;
		}

		auto* phy_manager = m_resource_manager.get(ResourceManager::PHYSICS);
		PhysicsSystem& system = static_cast<PhysicsGeometryManager*>(phy_manager)->getSystem();

		uint32 num_verts;
		Array<Vec3> verts(getAllocator());
		file.read(&num_verts, sizeof(num_verts));
		verts.resize(num_verts);
		file.read(&verts[0], sizeof(verts[0]) * verts.size());

		m_is_convex = header.m_convex != 0;
		if (!m_is_convex)
		{
			physx::PxTriangleMeshGeometry* geom =
				LUMIX_NEW(getAllocator(), physx::PxTriangleMeshGeometry)();
			m_geometry = geom;
			uint32 num_indices;
			Array<uint32> tris(getAllocator());
			file.read(&num_indices, sizeof(num_indices));
			tris.resize(num_indices);
			file.read(&tris[0], sizeof(tris[0]) * tris.size());

			physx::PxTriangleMeshDesc meshDesc;
			meshDesc.points.count = num_verts;
			meshDesc.points.stride = sizeof(physx::PxVec3);
			meshDesc.points.data = &verts[0];

			meshDesc.triangles.count = num_indices / 3;
			meshDesc.triangles.stride = 3 * sizeof(physx::PxU32);
			meshDesc.triangles.data = &tris[0];

			OutputStream writeBuffer(getAllocator());
			system.getCooking()->cookTriangleMesh(meshDesc, writeBuffer);

			InputStream readBuffer(writeBuffer.data, writeBuffer.size);
			geom->triangleMesh = system.getPhysics()->createTriangleMesh(readBuffer);
		}
		else
		{
			physx::PxConvexMeshGeometry* geom =
				LUMIX_NEW(getAllocator(), physx::PxConvexMeshGeometry)();
			m_geometry = geom;
			physx::PxConvexMeshDesc meshDesc;
			meshDesc.points.count = verts.size();
			meshDesc.points.stride = sizeof(Vec3);
			meshDesc.points.data = &verts[0];
			meshDesc.flags = physx::PxConvexFlag::eCOMPUTE_CONVEX;

			OutputStream writeBuffer(getAllocator());
			bool status = system.getCooking()->cookConvexMesh(meshDesc, writeBuffer);
			if (!status)
			{
				LUMIX_DELETE(getAllocator(), geom);
				m_geometry = nullptr;
				return false;
			}

			InputStream readBuffer(writeBuffer.data, writeBuffer.size);
			physx::PxConvexMesh* mesh = system.getPhysics()->createConvexMesh(readBuffer);
			geom->convexMesh = mesh;
		}

		m_size = file.size();
		return true;
	}
/// @par
///
/// See the #rcConfig documentation for more information on the configuration parameters.
///
/// @see rcAllocPolyMeshDetail, rcPolyMesh, rcCompactHeightfield, rcPolyMeshDetail, rcConfig
bool rcBuildPolyMeshDetail(rcContext* ctx, const rcPolyMesh& mesh, const rcCompactHeightfield& chf,
						   const float sampleDist, const float sampleMaxError,
						   rcPolyMeshDetail& dmesh)
{
	rcAssert(ctx);
	
	ctx->startTimer(RC_TIMER_BUILD_POLYMESHDETAIL);
	
	if (mesh.nverts == 0 || mesh.npolys == 0)
		return true;
	
	const int nvp = mesh.nvp;
	const float cs = mesh.cs;
	const float ch = mesh.ch;
	const float* orig = mesh.bmin;
	const int borderSize = mesh.borderSize;
	
	rcIntArray edges(64);
	rcIntArray tris(512);
	rcIntArray stack(512);
	rcIntArray samples(512);
	float verts[256*3];
	rcHeightPatch hp;
	int nPolyVerts = 0;
	int maxhw = 0, maxhh = 0;
	
	rcScopedDelete<int> bounds = (int*)rcAlloc(sizeof(int)*mesh.npolys*4, RC_ALLOC_TEMP);
	if (!bounds)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'bounds' (%d).", mesh.npolys*4);
		return false;
	}
	rcScopedDelete<float> poly = (float*)rcAlloc(sizeof(float)*nvp*3, RC_ALLOC_TEMP);
	if (!poly)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'poly' (%d).", nvp*3);
		return false;
	}
	
	// Find max size for a polygon area.
	for (int i = 0; i < mesh.npolys; ++i)
	{
		const unsigned short* p = &mesh.polys[i*nvp*2];
		int& xmin = bounds[i*4+0];
		int& xmax = bounds[i*4+1];
		int& ymin = bounds[i*4+2];
		int& ymax = bounds[i*4+3];
		xmin = chf.width;
		xmax = 0;
		ymin = chf.height;
		ymax = 0;
		for (int j = 0; j < nvp; ++j)
		{
			if(p[j] == RC_MESH_NULL_IDX) break;
			const unsigned short* v = &mesh.verts[p[j]*3];
			xmin = rcMin(xmin, (int)v[0]);
			xmax = rcMax(xmax, (int)v[0]);
			ymin = rcMin(ymin, (int)v[2]);
			ymax = rcMax(ymax, (int)v[2]);
			nPolyVerts++;
		}
		xmin = rcMax(0,xmin-1);
		xmax = rcMin(chf.width,xmax+1);
		ymin = rcMax(0,ymin-1);
		ymax = rcMin(chf.height,ymax+1);
		if (xmin >= xmax || ymin >= ymax) continue;
		maxhw = rcMax(maxhw, xmax-xmin);
		maxhh = rcMax(maxhh, ymax-ymin);
	}
	
	hp.data = (unsigned short*)rcAlloc(sizeof(unsigned short)*maxhw*maxhh, RC_ALLOC_TEMP);
	if (!hp.data)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'hp.data' (%d).", maxhw*maxhh);
		return false;
	}
	
	dmesh.nmeshes = mesh.npolys;
	dmesh.nverts = 0;
	dmesh.ntris = 0;
	dmesh.meshes = (unsigned int*)rcAlloc(sizeof(unsigned int)*dmesh.nmeshes*4, RC_ALLOC_PERM);
	if (!dmesh.meshes)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.meshes' (%d).", dmesh.nmeshes*4);
		return false;
	}
	
	int vcap = nPolyVerts+nPolyVerts/2;
	int tcap = vcap*2;
	
	dmesh.nverts = 0;
	dmesh.verts = (float*)rcAlloc(sizeof(float)*vcap*3, RC_ALLOC_PERM);
	if (!dmesh.verts)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.verts' (%d).", vcap*3);
		return false;
	}
	dmesh.ntris = 0;
	dmesh.tris = (unsigned char*)rcAlloc(sizeof(unsigned char)*tcap*4, RC_ALLOC_PERM);
	if (!dmesh.tris)
	{
		ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", tcap*4);
		return false;
	}
	
	for (int i = 0; i < mesh.npolys; ++i)
	{
		const unsigned short* p = &mesh.polys[i*nvp*2];
		
		// Store polygon vertices for processing.
		int npoly = 0;
		for (int j = 0; j < nvp; ++j)
		{
			if(p[j] == RC_MESH_NULL_IDX) break;
			const unsigned short* v = &mesh.verts[p[j]*3];
			poly[j*3+0] = v[0]*cs;
			poly[j*3+1] = v[1]*ch;
			poly[j*3+2] = v[2]*cs;
			npoly++;
		}
		
		// Get the height data from the area of the polygon.
		hp.xmin = bounds[i*4+0];
		hp.ymin = bounds[i*4+2];
		hp.width = bounds[i*4+1]-bounds[i*4+0];
		hp.height = bounds[i*4+3]-bounds[i*4+2];
		getHeightData(chf, p, npoly, mesh.verts, borderSize, hp, stack, mesh.regs[i]);
		
		// Build detail mesh.
		int nverts = 0;
		if (!buildPolyDetail(ctx, poly, npoly,
							 sampleDist, sampleMaxError,
							 chf, hp, verts, nverts, tris,
							 edges, samples))
		{
			return false;
		}
		
		// Move detail verts to world space.
		for (int j = 0; j < nverts; ++j)
		{
			verts[j*3+0] += orig[0];
			verts[j*3+1] += orig[1] + chf.ch; // Is this offset necessary?
			verts[j*3+2] += orig[2];
		}
		// Offset poly too, will be used to flag checking.
		for (int j = 0; j < npoly; ++j)
		{
			poly[j*3+0] += orig[0];
			poly[j*3+1] += orig[1];
			poly[j*3+2] += orig[2];
		}
		
		// Store detail submesh.
		const int ntris = tris.size()/4;
		
		dmesh.meshes[i*4+0] = (unsigned int)dmesh.nverts;
		dmesh.meshes[i*4+1] = (unsigned int)nverts;
		dmesh.meshes[i*4+2] = (unsigned int)dmesh.ntris;
		dmesh.meshes[i*4+3] = (unsigned int)ntris;
		
		// Store vertices, allocate more memory if necessary.
		if (dmesh.nverts+nverts > vcap)
		{
			while (dmesh.nverts+nverts > vcap)
				vcap += 256;
			
			float* newv = (float*)rcAlloc(sizeof(float)*vcap*3, RC_ALLOC_PERM);
			if (!newv)
			{
				ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newv' (%d).", vcap*3);
				return false;
			}
			if (dmesh.nverts)
				memcpy(newv, dmesh.verts, sizeof(float)*3*dmesh.nverts);
			rcFree(dmesh.verts);
			dmesh.verts = newv;
		}
		for (int j = 0; j < nverts; ++j)
		{
			dmesh.verts[dmesh.nverts*3+0] = verts[j*3+0];
			dmesh.verts[dmesh.nverts*3+1] = verts[j*3+1];
			dmesh.verts[dmesh.nverts*3+2] = verts[j*3+2];
			dmesh.nverts++;
		}
		
		// Store triangles, allocate more memory if necessary.
		if (dmesh.ntris+ntris > tcap)
		{
			while (dmesh.ntris+ntris > tcap)
				tcap += 256;
			unsigned char* newt = (unsigned char*)rcAlloc(sizeof(unsigned char)*tcap*4, RC_ALLOC_PERM);
			if (!newt)
			{
				ctx->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newt' (%d).", tcap*4);
				return false;
			}
			if (dmesh.ntris)
				memcpy(newt, dmesh.tris, sizeof(unsigned char)*4*dmesh.ntris);
			rcFree(dmesh.tris);
			dmesh.tris = newt;
		}
		for (int j = 0; j < ntris; ++j)
		{
			const int* t = &tris[j*4];
			dmesh.tris[dmesh.ntris*4+0] = (unsigned char)t[0];
			dmesh.tris[dmesh.ntris*4+1] = (unsigned char)t[1];
			dmesh.tris[dmesh.ntris*4+2] = (unsigned char)t[2];
			dmesh.tris[dmesh.ntris*4+3] = getTriFlags(&verts[t[0]*3], &verts[t[1]*3], &verts[t[2]*3], poly, npoly);
			dmesh.ntris++;
		}
	}
	
	ctx->stopTimer(RC_TIMER_BUILD_POLYMESHDETAIL);
	
	return true;
}
Beispiel #6
0
// error: !=0 si erreur fatale
static RESP_STRUCT readtable(htsmoduleStruct * str, FILE * fp,
                             RESP_STRUCT trans, int *error) {
  char rname[1024];
  unsigned short int length;
  int j;

  *error = 0;                   // pas d'erreur
  trans.file_position = -1;
  trans.type = (int) (unsigned char) fgetc(fp);
  switch (trans.type) {
  case HTS_CLASS:
    strcpy(trans.name, "Class");
    trans.index1 = readshort(fp);
    break;

  case HTS_FIELDREF:
    strcpy(trans.name, "Field Reference");
    trans.index1 = readshort(fp);
    readshort(fp);
    break;

  case HTS_METHODREF:
    strcpy(trans.name, "Method Reference");
    trans.index1 = readshort(fp);
    readshort(fp);
    break;

  case HTS_INTERFACE:
    strcpy(trans.name, "Interface Method Reference");
    trans.index1 = readshort(fp);
    readshort(fp);
    break;
  case HTS_NAMEANDTYPE:
    strcpy(trans.name, "Name and Type");
    trans.index1 = readshort(fp);
    readshort(fp);
    break;

  case HTS_STRING:             // CONSTANT_String
    strcpy(trans.name, "String");
    trans.index1 = readshort(fp);
    break;

  case HTS_INTEGER:
    strcpy(trans.name, "Integer");
    for(j = 0; j < 4; j++)
      fgetc(fp);
    break;

  case HTS_FLOAT:
    strcpy(trans.name, "Float");
    for(j = 0; j < 4; j++)
      fgetc(fp);
    break;

  case HTS_LONG:
    strcpy(trans.name, "Long");
    for(j = 0; j < 8; j++)
      fgetc(fp);
    break;
  case HTS_DOUBLE:
    strcpy(trans.name, "Double");
    for(j = 0; j < 8; j++)
      fgetc(fp);
    break;

  case HTS_ASCIZ:
  case HTS_UNICODE:

    if (trans.type == HTS_ASCIZ)
      strcpy(trans.name, "HTS_ASCIZ");
    else
      strcpy(trans.name, "HTS_UNICODE");

    {
      char BIGSTK buffer[1024];
      char *p;

      p = &buffer[0];

      //fflush(fp); 
      trans.file_position = ftell(fp);
      length = readshort(fp);
      if (length < HTS_URLMAXSIZE) {
        // while ((length > 0) && (length<500)) {
        while(length > 0) {
          *p++ = fgetc(fp);

          length--;
        }
        *p = '\0';

        //#if JDEBUG
        //      if(tris(buffer)==1) printf("%s\n ",buffer);
        //      if(tris(buffer)==2)  printf("%s\n ",printname(buffer));
        //#endif
        if (tris(str->opt, buffer) == 1)
          str->addLink(str, buffer);    /* trans.file_position */
        else if (tris(str->opt, buffer) == 2)
          str->addLink(str, printname(rname, buffer));

        strcpy(trans.name, buffer);
      } else {                  // gros pb
        while((length > 0) && (!feof(fp))) {
          fgetc(fp);
          length--;
        }
        if (!feof(fp)) {
          trans.type = -1;
        } else {
          sprintf(str->err_msg, "Internal stucture error (ASCII)");
          *error = 1;
        }
        return (trans);
      }
    }
    break;
  default:
    // printf("Type inconnue\n");
    // on arrête tout 
    sprintf(str->err_msg, "Internal structure unknown (type %d)", trans.type);
    *error = 1;
    return (trans);
    break;
  }
  return (trans);
}
bool rcBuildPolyMeshDetail(const rcPolyMesh& mesh, const rcCompactHeightfield& chf,
						   const float sampleDist, const float sampleMaxError,
						   rcPolyMeshDetail& dmesh)
{
	rcTimeVal startTime = rcGetPerformanceTimer();
	
	if (mesh.nverts == 0 || mesh.npolys == 0)
		return true;
	
	const int nvp = mesh.nvp;
	const float cs = mesh.cs;
	const float ch = mesh.ch;
	const float* orig = mesh.bmin;
	
	rcIntArray edges(64);
	rcIntArray tris(512);
	rcIntArray idx(512);
	rcIntArray stack(512);
	rcIntArray samples(512);
	float verts[256*3];
	float* poly = 0;
	int* bounds = 0;
	rcHeightPatch hp;
	int nPolyVerts = 0;
	int maxhw = 0, maxhh = 0;
	
	bounds = new int[mesh.npolys*4];
	if (!bounds)
	{
		if (rcGetLog())
			rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'bounds' (%d).", mesh.npolys*4);
		goto failure;
	}
	poly = new float[nvp*3];
	if (!bounds)
	{
		if (rcGetLog())
			rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'poly' (%d).", nvp*3);
		goto failure;
	}
	
	// Find max size for a polygon area.
	for (int i = 0; i < mesh.npolys; ++i)
	{
		const unsigned short* p = &mesh.polys[i*nvp*2];
		int& xmin = bounds[i*4+0];
		int& xmax = bounds[i*4+1];
		int& ymin = bounds[i*4+2];
		int& ymax = bounds[i*4+3];
		xmin = chf.width;
		xmax = 0;
		ymin = chf.height;
		ymax = 0;
		for (int j = 0; j < nvp; ++j)
		{
			if(p[j] == 0xffff) break;
			const unsigned short* v = &mesh.verts[p[j]*3];
			xmin = rcMin(xmin, (int)v[0]);
			xmax = rcMax(xmax, (int)v[0]);
			ymin = rcMin(ymin, (int)v[2]);
			ymax = rcMax(ymax, (int)v[2]);
			nPolyVerts++;
		}
		xmin = rcMax(0,xmin-1);
		xmax = rcMin(chf.width,xmax+1);
		ymin = rcMax(0,ymin-1);
		ymax = rcMin(chf.height,ymax+1);
		if (xmin >= xmax || ymin >= ymax) continue;
		maxhw = rcMax(maxhw, xmax-xmin);
		maxhh = rcMax(maxhh, ymax-ymin);
	}
	
	hp.data = new unsigned short[maxhw*maxhh];
	if (!hp.data)
	{
		if (rcGetLog())
			rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'hp.data' (%d).", maxhw*maxhh);
		goto failure;
	}
		
	dmesh.nmeshes = mesh.npolys;
	dmesh.nverts = 0;
	dmesh.ntris = 0;
	dmesh.meshes = new unsigned short[dmesh.nmeshes*4];
	if (!dmesh.meshes)
	{
		if (rcGetLog())
			rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.meshes' (%d).", dmesh.nmeshes*4);
		goto failure;
	}

	int vcap = nPolyVerts+nPolyVerts/2;
	int tcap = vcap*2;

	dmesh.nverts = 0;
	dmesh.verts = new float[vcap*3];
	if (!dmesh.verts)
	{
		if (rcGetLog())
			rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.verts' (%d).", vcap*3);
		goto failure;
	}
	dmesh.ntris = 0;
	dmesh.tris = new unsigned char[tcap*4];
	if (!dmesh.tris)
	{
		if (rcGetLog())
			rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'dmesh.tris' (%d).", tcap*4);
		goto failure;
	}
	
	for (int i = 0; i < mesh.npolys; ++i)
	{
		const unsigned short* p = &mesh.polys[i*nvp*2];
		
		// Find polygon bounding box.
		int npoly = 0;
		for (int j = 0; j < nvp; ++j)
		{
			if(p[j] == 0xffff) break;
			const unsigned short* v = &mesh.verts[p[j]*3];
			poly[j*3+0] = orig[0] + v[0]*cs;
			poly[j*3+1] = orig[1] + v[1]*ch;
			poly[j*3+2] = orig[2] + v[2]*cs;
			npoly++;
		}
		
		// Get the height data from the area of the polygon.
		hp.xmin = bounds[i*4+0];
		hp.ymin = bounds[i*4+2];
		hp.width = bounds[i*4+1]-bounds[i*4+0];
		hp.height = bounds[i*4+3]-bounds[i*4+2];
		getHeightData(chf, p, npoly, mesh.verts, hp, stack);
		
		// Build detail mesh.
		int nverts = 0;
		if (!buildPolyDetail(poly, npoly, mesh.regs[i],
							 sampleDist, sampleMaxError,
							 chf, hp, verts, nverts, tris,
							 edges, idx, samples))
		{
			goto failure;
		}

		// Offset detail vertices, unnecassary?
		for (int j = 0; j < nverts; ++j)
			verts[j*3+1] += chf.ch;
	
		// Store detail submesh.
		const int ntris = tris.size()/4;
		
		dmesh.meshes[i*4+0] = dmesh.nverts;
		dmesh.meshes[i*4+1] = (unsigned short)nverts;
		dmesh.meshes[i*4+2] = dmesh.ntris;
		dmesh.meshes[i*4+3] = (unsigned short)ntris;
		
		// Store vertices, allocate more memory if necessary.
		if (dmesh.nverts+nverts > vcap)
		{
			while (dmesh.nverts+nverts > vcap)
				vcap += 256;
				
			float* newv = new float[vcap*3];
			if (!newv)
			{
				if (rcGetLog())
					rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newv' (%d).", vcap*3);
				goto failure;
			}
			if (dmesh.nverts)
				memcpy(newv, dmesh.verts, sizeof(float)*3*dmesh.nverts);
			delete [] dmesh.verts;
			dmesh.verts = newv;
		}
		for (int j = 0; j < nverts; ++j)
		{
			dmesh.verts[dmesh.nverts*3+0] = verts[j*3+0];
			dmesh.verts[dmesh.nverts*3+1] = verts[j*3+1];
			dmesh.verts[dmesh.nverts*3+2] = verts[j*3+2];
			dmesh.nverts++;
		}
		
		// Store triangles, allocate more memory if necessary.
		if (dmesh.ntris+ntris > tcap)
		{
			while (dmesh.ntris+ntris > tcap)
				tcap += 256;
			unsigned char* newt = new unsigned char[tcap*4];
			if (!newt)
			{
				if (rcGetLog())
					rcGetLog()->log(RC_LOG_ERROR, "rcBuildPolyMeshDetail: Out of memory 'newt' (%d).", tcap*4);
				goto failure;
			}
			if (dmesh.ntris)
				memcpy(newt, dmesh.tris, sizeof(unsigned char)*4*dmesh.ntris);
			delete [] dmesh.tris;
			dmesh.tris = newt;
		}
		for (int j = 0; j < ntris; ++j)
		{
			const int* t = &tris[j*4];
			dmesh.tris[dmesh.ntris*4+0] = (unsigned char)t[0];
			dmesh.tris[dmesh.ntris*4+1] = (unsigned char)t[1];
			dmesh.tris[dmesh.ntris*4+2] = (unsigned char)t[2];
			dmesh.tris[dmesh.ntris*4+3] = getTriFlags(&verts[t[0]*3], &verts[t[1]*3], &verts[t[2]*3], poly, npoly);
			dmesh.ntris++;
		}
	}
	
	delete [] bounds;
	delete [] poly;
	
	rcTimeVal endTime = rcGetPerformanceTimer();
	
	if (rcGetBuildTimes())
		rcGetBuildTimes()->buildDetailMesh += rcGetDeltaTimeUsec(startTime, endTime);

	return true;

failure:

	delete [] bounds;
	delete [] poly;

	return false;
}
// returns the verts of an empty box, centered on the origin which is surrounded by triangles
void generate_box_space( moab::EntityHandle surf, double A_f, std::vector<moab::EntityHandle> &box_verts, int axis )
{
  int x_idx, y_idx;
  //set the indices of the cartesian vectors based on the constant axis for this surface 
  switch(axis){
  case 0:
    x_idx = 1; 
    y_idx = 2; 
    break;
  case 1:
    x_idx = 0;
    y_idx = 2; 
    break; 
  case 2:
    x_idx = 0;
    y_idx = 1;
    break;
  default:
    std::cout << "Value of axis muxt be 0, 1, or 2" << std::endl; 
    assert(false); 
  }

  std::vector<moab::EntityHandle> corners;
  moab::ErrorCode rval = mbi->get_entities_by_type( surf, MBVERTEX, corners );
  MB_CHK_ERR_CONT(rval);

  double surface_area = polygon_area( corners );
  //going to start taking advantage of knowing the geometry here...
  double surface_side = sqrt(surface_area);
  double cube_area = 6*surface_area;

  //now create the vertices for the new regions
  
  //based on surface area, get the length of one of the center-square sides
  if( A_f == 1 )
    {
      std::vector<moab::EntityHandle> ordered_corners;
      order_corner_verts(corners, ordered_corners);
      box_verts = ordered_corners;
      return;
    }

  double hv_area = A_f*cube_area/6; //divide by 6 because this surface represents all surfaces of the cube
  if ( hv_area >= surface_area ) std::cout << "ERROR: Area fraction must be less than 1/6 for now. " << surf << std::endl;
  assert( hv_area < surface_area );
  double hv_side = sqrt(hv_area);

  //get the move distance for the given area. 
  double box_bump_dist = 0.5 * (surface_side - hv_side);
  double dam_bump_short = 0.25 * (surface_side - hv_side);
  double dam_bump_long = 0.5 * surface_side;

  //vectors for the dam nodes and the inner vert points
  
  std::vector<moab::EntityHandle> 
    nd, /*north dam tri verts*/ 
    sd, /*south dam tri verts*/ 
    ed, /*east dam tri verts*/ 
    wd; /*west dam tri verts*/ 
  moab::EntityHandle 
    ndv, /*north dam vertex*/ 
    sdv, /*south dam vertex*/ 
    edv, /*east dam vertex*/ 
    wdv; /*west dam vertex*/

  std::vector<moab::EntityHandle> box; /* inner box vert list */


  //loop over the original verts (corners) and create the needed vertices
  for(std::vector<moab::EntityHandle>::iterator i=corners.begin(); i!=corners.end(); i++)
    {
      //first get the coordinates of this corner
      moab::CartVect coords;
      mbi->get_coords( &(*i), 1, coords.array() );
      
      //need three cartesian vectors telling us where to put the verts, two for the dam points, one for the inner point.
      moab::CartVect to_ewdam, to_nsdam, to_box;
      to_ewdam[axis] = 0; to_nsdam[axis] = 0; to_box[axis] = 0; //only moving on the x-y plane here
      
      //always want to create this vert
      //using the fact that we're centered on the origin here...
      //x-points
      if( coords[x_idx] < 0 ){ 
	to_box[x_idx] = box_bump_dist; }
      else  { 
	to_box[x_idx] = -box_bump_dist; }
      //y-points
      if( coords[y_idx] < 0 ){ 
	to_box[y_idx]= box_bump_dist; }
      else  { 
	to_box[y_idx] = -box_bump_dist; }

      //create the inner point
      moab::EntityHandle box_vert;
      mbi->create_vertex( (coords+to_box).array(), box_vert);
      box.push_back(box_vert);
      

      //figure out which dams we're adjacent to
      std::vector<moab::EntityHandle> *nsdam = &nd, *ewdam = &ed;
      moab::EntityHandle *nsdam_vert = &ndv, *ewdam_vert = &edv;

      //set the north-south dam based on our y location
      if( coords[y_idx] < 0) { nsdam_vert = &sdv; nsdam = &sd; }
      else { nsdam_vert = &ndv; nsdam = &nd; }

      //set the east-west dam based on our x location
      if( coords[x_idx] < 0) { ewdam_vert = &wdv; ewdam = &wd; }
      else { ewdam_vert = &edv; ewdam = &ed; }

      //////NORTH-SOUTH DAM\\\\\\\

      //if the dams already have info from another corner, no need to create it's point,
      //just add this corner to the dam triangle
      if( 0 != nsdam->size() && NULL != nsdam_vert ) { nsdam->push_back(*i); }
      // if the dam has no info, then we'll create it
      else {
	
	//set the dam coordinates
	if ( coords[x_idx] < 0 ) to_nsdam[x_idx] = dam_bump_long;
	else to_nsdam[x_idx] = -dam_bump_long;
	if ( coords[y_idx] < 0 ) to_nsdam[y_idx] = dam_bump_short;
	else to_nsdam[y_idx] = -dam_bump_short;

	//create the dam vertex 
	mbi->create_vertex( (coords+to_nsdam).array(), *nsdam_vert);
	
	//now add this corner and the dam vert to the dam verts list
	nsdam->push_back(*nsdam_vert); nsdam->push_back(*i);

      } 
	
      //////EAST-WEST DAM\\\\\\\

      //if the dams already have info from another corner, no need to create it's point,
      //just add this corner to the dam triangle
      if( 0 != ewdam->size() && NULL != ewdam_vert ) { ewdam->push_back(*i); }
      // if the dam has no info, then we'll create it
      else {
	
	//set the dam coordinates
	if ( coords[x_idx] < 0 ) to_ewdam[x_idx] = dam_bump_short;
	else to_ewdam[x_idx] = -dam_bump_short;
	if ( coords[y_idx] < 0 ) to_ewdam[y_idx] = dam_bump_long;
	else to_ewdam[y_idx] = -dam_bump_long;

	//create the dam vertex 
	mbi->create_vertex( (coords+to_ewdam).array(), *ewdam_vert);
	
	//now add this corner and the dam vert to the dam verts list
	//order of push back is reversed here in comparison to north-south dam for correct normal
	ewdam->push_back(*i); ewdam->push_back(*ewdam_vert); 

      } 
	
      //dam info should now all be set

      //there are always two triangles to create that connect the dam
      //to the corner, we'll do that now
      moab::CartVect corner_coords;
      mbi->get_coords(&(*i), 1, corner_coords.array());
      moab::EntityHandle tri1_verts[3] = {*i, *nsdam_vert, box_vert};
      moab::EntityHandle tri2_verts[3] = {*i, *ewdam_vert, box_vert};
      if( coords[x_idx] < 0 ) {
	if ( coords[y_idx] > 0 ) {
	  tri1_verts[1] = *nsdam_vert;
	  tri1_verts[2] = box_vert;
	  tri2_verts[1] = box_vert;
	  tri2_verts[2] = *ewdam_vert;
	}
	else {
	  tri1_verts[1] = box_vert;
	  tri1_verts[2] = *nsdam_vert;
	}
      }
      else {
	if ( coords[y_idx] > 0 ) {
	  tri1_verts[1] = box_vert;
	  tri1_verts[2] = *nsdam_vert;
	}
	else {
	  tri2_verts[1] = box_vert;
	  tri2_verts[2] = *ewdam_vert;
	}
      }
      std::vector<moab::EntityHandle> tris(2);
      mbi->create_element( MBTRI, &tri1_verts[0], 3, tris[0] );
      mbi->create_element( MBTRI, &tri2_verts[0], 3, tris[1] );
      
      //now we'll add these to the set
      mbi->add_entities( surf, &tri1_verts[0], 3 );
      mbi->add_entities( surf, &tri2_verts[0], 3 );      
      mbi->add_entities( surf, &(tris[0]), tris.size() );
    }

  //now we should have all of the info needed to create our dam triangles
  std::vector<moab::EntityHandle> dam_tris(4);
  assert( nd.size()==3 );
  moab::EntityHandle temp = nd[1];
  nd[1] = nd[2];
  nd[2] = temp;
  temp = wd[1];
  wd[1] = wd[2];
  wd[2] = temp;
  mbi->create_element( MBTRI, &(nd[0]), nd.size(), dam_tris[0]);
  mbi->create_element( MBTRI, &(sd[0]), sd.size(), dam_tris[1]);
  mbi->create_element( MBTRI, &(ed[0]), ed.size(), dam_tris[2]);
  mbi->create_element( MBTRI, &(wd[0]), wd.size(), dam_tris[3]);

  //add these to the surface
  mbi->add_entities( surf, &(dam_tris[0]), dam_tris.size() );

  
  //re-order the M verts
  std::vector<moab::EntityHandle> ordered_box(4);
  order_corner_verts(box, ordered_box);

  box_verts = ordered_box;
  //now that the middle box is ordered we can add the triangles that 
  //connect the dams to to the box

  box_verts.push_back(box_verts[0]); // psuedo-loop to make creating these tris easier
  moab::EntityHandle all_dam_verts[4] = { wdv, ndv, edv, sdv };
  std::vector<moab::EntityHandle> last_few_tris(4);

  //create triangle that connect the box to the dams
  for(unsigned int i = 0; i < last_few_tris.size(); i++)
    {
      moab::EntityHandle tri_verts[3] = { box_verts[i], all_dam_verts[i], box_verts[i+1] };
      mbi->create_element( MBTRI, &(tri_verts[0]), 3, last_few_tris[i]);
    }
      
  //now add these to the surface
  mbi->add_entities( surf, &last_few_tris[0], 4);

  box_verts = ordered_box;
  
} // end generate_box_space