void IsotropicParticleMesher::_computeSliceScalarField(int startidx, int endidx, 
	                                                   FragmentedVector<MarkerParticle> &markerParticles,
	                                                   FluidMaterialGrid &materialGrid,
	                                                   ImplicitSurfaceScalarField &field) {
	
	FragmentedVector<vmath::vec3> sliceParticles;
	_getSliceParticles(startidx, endidx, markerParticles, sliceParticles);

	int width, height, depth;
	field.getGridDimensions(&width, &height, &depth);

	FluidMaterialGrid sliceMaterialGrid(width - 1, height - 1, depth - 1);
	_getSliceMaterialGrid(startidx, endidx, materialGrid, sliceMaterialGrid);

	field.setMaterialGrid(sliceMaterialGrid);

	vmath::vec3 fieldOffset = _getSliceGridPositionOffset(startidx, endidx);
	field.setOffset(fieldOffset);
	field.setPointRadius(_particleRadius);

	for (unsigned int i = 0; i < sliceParticles.size(); i++) {
        field.addPoint(sliceParticles[i]);
    }

    _updateScalarFieldSeam(startidx, endidx, field);
}
void IsotropicParticleMesher::_addPointsToScalarFieldAccelerator(FragmentedVector<MarkerParticle> &points,
                                                                 ImplicitSurfaceScalarField &field) {
	bool isThresholdSet = _scalarFieldAccelerator->isMaxScalarFieldValueThresholdSet();
	bool origThreshold = _scalarFieldAccelerator->getMaxScalarFieldValueThreshold();
	_scalarFieldAccelerator->setMaxScalarFieldValueThreshold(_maxScalarFieldValueThreshold);

	int n = _maxParticlesPerScalarFieldAddition;
	std::vector<vmath::vec3> positions;
    positions.reserve(fmin(n, points.size()));

    for (int startidx = 0; startidx < (int)points.size(); startidx += n) {
        int endidx = startidx + n - 1;
        if (endidx >= (int)points.size()) {
            endidx = points.size() - 1;
        }

        positions.clear();
        for (int i = startidx; i <= endidx; i++) {
            positions.push_back(points[i].position);
        }

        _scalarFieldAccelerator->addPoints(positions, field);
    }

    if (!isThresholdSet) {
    	_scalarFieldAccelerator->setMaxScalarFieldValueThreshold();
    } else {
    	_scalarFieldAccelerator->setMaxScalarFieldValueThreshold(origThreshold);
    }
}
void DiffuseParticleSimulation::
        addDiffuseParticles(FragmentedVector<DiffuseParticle> &particles) {
    _diffuseParticles.reserve(_diffuseParticles.size() + particles.size());
    for (unsigned int i = 0; i < particles.size(); i++) {
        _diffuseParticles.push_back(particles[i]);
    }
}
void DiffuseParticleSimulation::
        setDiffuseParticles(FragmentedVector<DiffuseParticle> &particles) {
    _diffuseParticles.clear();
    _diffuseParticles.shrink_to_fit();
    _diffuseParticles.reserve(particles.size());
    for (unsigned int i = 0; i < particles.size(); i++) {
        _diffuseParticles.push_back(particles[i]);
    }
}
void IsotropicParticleMesher::_getSliceParticles(int startidx, int endidx, 
	                                             FragmentedVector<MarkerParticle> &markerParticles,
		                                         FragmentedVector<vmath::vec3> &sliceParticles) {
	AABB bbox = _getSliceAABB(startidx, endidx);
	for (unsigned int i = 0; i < markerParticles.size(); i++) {
		if (bbox.isPointInside(markerParticles[i].position)) {
			sliceParticles.push_back(markerParticles[i].position);
		}
	}
}
TriangleMesh IsotropicParticleMesher::_polygonizeAll(FragmentedVector<MarkerParticle> &particles, 
	                                                 FluidMaterialGrid &materialGrid) {
	int subd = _subdivisionLevel;
	int width = _isize*subd;
	int height = _jsize*subd;
	int depth = _ksize*subd;
	double dx = _dx / (double)subd;

	ImplicitSurfaceScalarField field(width + 1, height + 1, depth + 1, dx);

	int origsubd = materialGrid.getSubdivisionLevel();
	materialGrid.setSubdivisionLevel(subd);
	field.setMaterialGrid(materialGrid);
	materialGrid.setSubdivisionLevel(origsubd);

	field.setPointRadius(_particleRadius);

    for (unsigned int i = 0; i < particles.size(); i++) {
        field.addPoint(particles[i].position);
    }

    Polygonizer3d polygonizer(&field);
    polygonizer.polygonizeSurface();

    return polygonizer.getTriangleMesh();
}
void IsotropicParticleMesher::_addPointsToScalarField(FragmentedVector<MarkerParticle> &points,
	                                                  ImplicitSurfaceScalarField &field) {
	if (_isScalarFieldAcceleratorSet) {
		_addPointsToScalarFieldAccelerator(points, field);
	} else {
		for (unsigned int i = 0; i < points.size(); i++) {
	        field.addPoint(points[i].position);
	    }
	}
}