bool InstanceSurfaceScatterBuilder::testPositionPickAndAddObject(Scene& scene, const Point& position, RNG& rng, TestPosInfo& posInfo)
{
	Ray occlusionRay(position, Normal(0.0f, -1.0f, 0.0f), RAY_ALL);

	// BVH intersectors depend on signed inf values resulting from div-by-0 for axis-aligned rays...
	occlusionRay.calculateInverseDirection();

	HitResult hitResult;
	float t = 1000.0f;

	if (scene.didHitObject(occlusionRay, t, hitResult))
	{
		if (hitResult.hitPoint.y < m_minimumCutoff)
			return false;

		Object* pSrcObject = posInfo.pCurrentSelectedObject;

		Point newPoint = position;
		newPoint.y -= t;

		unsigned int randomIndex = 0;
		if (posInfo.randomlyPickObject)
		{
			// TODO: Given that we're picking a random index AND a random location, we don't get the best
			//       distribution here...

			if (posInfo.doSwitchover)
			{
				if (posInfo.switchCount < m_lastObjectSwitchover)
				{
					randomIndex = rng.randomInt(posInfo.numSelectedItems - 1);
					pSrcObject = SelectionManager::instance().getSelection().getSelectedObjectAtIndex(randomIndex);
				}
				else
				{
					// pick the last object
					randomIndex = posInfo.numSelectedItems - 1;
					pSrcObject = SelectionManager::instance().getSelection().getSelectedObjectAtIndex(randomIndex);
				}
			}
			else
			{
				// just randomly pick...
				randomIndex = rng.randomInt(posInfo.numSelectedItems);
				pSrcObject = SelectionManager::instance().getSelection().getSelectedObjectAtIndex(randomIndex);
			}

			// need to update the height of the object
			BoundaryBox shapeBBox = pSrcObject->getTransformedBoundaryBox();
			posInfo.heightOffset = shapeBBox.getExtent().y * 0.5f;
		}

		float scaleVariation = 1.0f;

		if (posInfo.scaleVariation)
		{
			// scale variation can be larger or smaller than current object, split around the middle
			float halfVariation = m_uniformScaleVariation * 0.5f;
			scaleVariation = 1.0f - halfVariation + (m_uniformScaleVariation * rng.randomFloat());
		}

		float localHeightOffset = posInfo.heightOffset;

		if (posInfo.scaleVariation)
		{
			localHeightOffset *= scaleVariation;
		}

		newPoint.y += localHeightOffset; // centre the object's bbox on the surface that was hit

		// TODO: an option to ratio this based on the surface flatness amount, so that objects on a flat surface
		//       don't have as much as an offset, whereas objects on a steep incline (trees for example) have more of an offset
		newPoint.y += m_surfaceYOffset;

		Object* pNewObject = NULL;

		if (!posInfo.shouldMakeBakedInstances)
		{
			pNewObject = pSrcObject->clone();

			if (m_alternatingMaterials)
			{
				Material* pMat = posInfo.aMaterials[posInfo.altMaterialIndex];

				pNewObject->setMaterial(pMat);

				posInfo.altMaterialIndex++;

				if (posInfo.altMaterialIndex >= m_numMaterials)
					posInfo.altMaterialIndex = 0;
			}
		}
		else
		{
			if (posInfo.randomlyPickObject)
			{
				pNewObject = new CompoundInstance(posInfo.aMultipleSrcCO[randomIndex]);
			}
			else
			{
				pNewObject = new CompoundInstance(posInfo.pSrcCOForBakedInstances);
			}
		}

		pNewObject->setPosition(Vector(newPoint.x, newPoint.y, newPoint.z));

		if (posInfo.scaleVariation)
		{
			float currentUScale = pNewObject->transform().getUniformScale();
			pNewObject->transform().setUniformScale(currentUScale * scaleVariation);
		}

		if (m_alignToSurface)
		{
			// work out what the rotation should be to make it roughly flat on the surface - this won't be physically-accurate, but it's
			// a good starting point
			Quaternion rotateQ = Quaternion::fromDirections(Normal(0.0f, 1.0f, 0.0f), hitResult.geometryNormal);
			Matrix4 rotateM = rotateQ.toMatrix();
			Vector rotation = rotateM.getRotationYXZ();

			if (m_randomYRotation)
			{
				rotation.y = rng.randomFloat() * 360.0f;
			}

			pNewObject->setRotation(rotation);
		}
		else
		{
			if (m_randomYRotation)
			{
				pNewObject->setRotation(Vector(0.0f, rng.randomFloat() * 360.0f, 0.0f));
			}
		}

		if (m_drawAsBBox)
			pNewObject->setDisplayType(eBoundaryBox);

		sprintf(posInfo.szName, "ScatteredOb_%d", posInfo.createdCount); // calling function needs to increment this
		pNewObject->setName(posInfo.szName, false);

		if (m_addToGroup)
		{
			posInfo.pNewCO->addObject(pNewObject, false);
		}
		else
		{
			addObject(scene, pNewObject);
		}
	}

	return true;
}