/*!
	\param modelId model ID
	\param instanceId instance ID
	\param factor fade factor
*/
void Storm3D_TerrainGroup::setInstanceFade(int modelId, int instanceId, float factor)
{
	assert(modelId >= 0 && instanceId >= 0);
	if(modelId < 0 || instanceId < 0 || modelId >= int(data->models.size()))
		return;

	SharedModel &original = data->models[modelId];
	if(instanceId >= int(original.instances.size()))
		return;

	Instance &instance = *original.instances[instanceId];
	if(factor < 0.02f)
		factor = 0.02f;

	if(instance.fadeModel)
	{
		boost::scoped_ptr<Iterator<IStorm3D_Model_Object *> > objectIterator(instance.fadeModel->ITObject->Begin());
		for(; !objectIterator->IsEnd(); objectIterator->Next())
		{
			IStorm3D_Model_Object *object = objectIterator->GetCurrent();
			if(!object)
				continue;

			object->SetForceAlpha(factor);
		}

		data->terrainModels.addModel(*instance.fadeModel);
	}
}
/*!
	\param modelId model ID
	\param position instance position
	\param rotation instance rotation
	\param color instance color
	\return index of added instance
*/
int Storm3D_TerrainGroup::addInstance(int modelId, const VC3 &position, const QUAT &rotation, const COL &color)
{
	assert(modelId >= 0 && modelId < int(data->models.size()));
	SharedModel &original = data->models[modelId];

	shared_ptr<IStorm3D_Model> m(original.model->GetClone(true, false, true));

	shared_ptr<IStorm3D_Model> mf;
	if(original.fadeModel)
		mf.reset(original.fadeModel->GetClone(true, false, true));

	if(!original.idleAnimation.empty() && !original.animation)
	{
		IStorm3D_BoneAnimation *ba = data->storm.CreateNewBoneAnimation(original.idleAnimation.c_str());
		if(ba)
			original.animation.reset(ba, ModelAnimationDeleter());
	}

	m->SetPosition(const_cast<VC3 &> (position));
	m->SetRotation(const_cast<QUAT &> (rotation));
	m->SetSelfIllumination(color);
#ifdef PHYSICS_NONE
	m->SetNoCollision(true);
#endif

	static_cast<Storm3D_Model *> (m.get())->terrain_object = true;

	if(mf)
	{
		mf->SetPosition(const_cast<VC3 &> (position));
		mf->SetRotation(const_cast<QUAT &> (rotation));
		mf->SetSelfIllumination(color);
		mf->SetNoCollision(true);
		static_cast<Storm3D_Model *> (mf.get())->terrain_object = true;

		boost::scoped_ptr<Iterator<IStorm3D_Model_Object *> > objectIterator(mf->ITObject->Begin());
		for(; !objectIterator->IsEnd(); objectIterator->Next())
		{
			IStorm3D_Model_Object *object = objectIterator->GetCurrent();
			if(!object)
				continue;

			object->SetForceAlpha(0);
		}

	}

	if(original.animation)
	{
		m->SetRandomAnimation(original.animation.get());
		if(mf)
			mf->SetRandomAnimation(original.animation.get());
	}

	data->terrainModels.addModel(*m);

	int index = original.instances.size();
	shared_ptr<Instance> instance(new Instance(m, mf, color));
	original.instances.push_back(instance);

	// ToDo:
	// Add a flag which controls whether to insert instance to collision tree.
	// A lot of objects don't care about collisions, anyway

	instance->radius2d = original.radius2d;
	instance->position = position;
	instance->rotation = rotation;
	instance->modelId = modelId;
	instance->instanceId = index;
	instance->entity = data->tree->insert(instance.get(), position, original.radius);

	// give the storm3d model some info about the terrain object instance/model ids
	static_cast<Storm3D_Model *> (m.get())->terrainInstanceId = index;
	static_cast<Storm3D_Model *> (m.get())->terrainModelId = modelId;
	// --jpk

	data->instanceMap[m.get()] = InstanceInfo(modelId, index);
	return index;
}