ImpNode* SceneGraphCreator::importInstance( const COLLADAFW::Node* node, INode* parentINode )
	{
		const COLLADAFW::PointerArray<Instance>& instances = (node->*getInstances)();
		if ( instances.getCount() != 1 )
			return 0;

		ImpNode* newImportNode = getMaxImportInterface()->CreateNode();
		setNodeProperties(node, newImportNode);
		INode* newNode = newImportNode->GetINode();

		Instance* instance = instances[0];
		const COLLADAFW::UniqueId& uniqueId = instance->getInstanciatedObjectId();

		Object* object = getObjectByUniqueId(uniqueId);
		if ( object )
		{
			newImportNode->Reference(object);
			const String& objectName = getObjectNameByObject(object);

			if ( node->getName().empty() && !objectName.empty() )
			{
#ifdef UNICODE
				WideString wideObjectName = COLLADABU::StringUtils::toWideString(objectName.c_str());
				newImportNode->SetName( wideObjectName.c_str() );
#else
				newImportNode->SetName( objectName.c_str() );
#endif
			}
		}
		else
		{
			newImportNode->Reference( getDummyObject() );
		}

		const COLLADAFW::UniqueId& instanceGeometryUniqueId = instance->getInstanciatedObjectId();
		// Store mapping between unique ids and nodes referencing the corresponding object.
		// Used to clone nodes
		addObjectINodeUniqueIdPair(newNode, instanceGeometryUniqueId);
		// Used to resolve instancing of objects
		addUniqueIdObjectINodePair(instanceGeometryUniqueId, newNode);
		parentINode->AttachChild(newNode, FALSE);

		// post process the creation
		if ( postProcess )
			(this->*postProcess)(newNode, instance);

		return newImportNode;
	}
	//------------------------------
	bool MorphControllerCreator::initializeChannelGeometry( morphChannel* channel, Object* geometryObject )
	{
		if ( !channel || !geometryObject )
		{
			return false;
		}

		Class_ID geometryObjectClassId = geometryObject->ClassID();
	
		MNMesh* polyMesh = 0;
		Mesh* triangleMesh = 0;
	
		if ( (geometryObjectClassId == EPOLYOBJ_CLASS_ID)  || (geometryObjectClassId.PartA() == POLYOBJ_CLASS_ID) )
		{
			polyMesh = &((PolyObject*)geometryObject)->GetMesh();
		}
		else if ( (geometryObjectClassId.PartA() == TRIOBJ_CLASS_ID) || (geometryObjectClassId.PartA() == EDITTRIOBJ_CLASS_ID ) )
		{
			triangleMesh = &((TriObject*)geometryObject)->GetMesh();
		}

		if ( !polyMesh && !triangleMesh )
		{
			// unsupported object type
			return true;
		}

		// Verify that the COLLADA source size matches the original mesh's vertex count
		int vertexCount = polyMesh ? polyMesh->VNum() : triangleMesh->numVerts;
		if (vertexCount != channel->mp->cache.count) 
		{
			return false;
		}

		// Set the channel's name and the necessary flags
		channel->mName = getObjectNameByObject(geometryObject).c_str();
		channel->mInvalid = false;
		channel->mActive = true;
		channel->mModded = true;


		// Allocate the channel's buffers and fill them with the relative vertex positions
		channel->AllocBuffers(vertexCount, vertexCount);
		channel->mSel.SetSize(vertexCount);
		channel->mSel.ClearAll();
		channel->mNumPoints = vertexCount;

		if ( polyMesh )
		{
			for (int i = 0; i < vertexCount; ++i)
			{
				channel->mPoints[i] = polyMesh->V( i )->p;
				channel->mDeltas[i] = (channel->mPoints[i] - channel->mp->cache.points[i]) / 100.0f;
				channel->mSel.Set(i, false);
				channel->mWeights[i] = 1.0f; // Not too sure of what the value should be here.
			}
		}
		else 
		{
			for (int i = 0; i < vertexCount; ++i)
			{
				channel->mPoints[i] = triangleMesh->verts[ i ];
				channel->mDeltas[i] = (channel->mPoints[i] - channel->mp->cache.points[i]) / 100.0f;
				channel->mSel.Set(i, false);
				channel->mWeights[i] = 1.0f; // Not too sure of what the value should be here.
			}
		}

		// Update all the UI stuff. Important? Must it be done for every channel?
		channel->mp->NotifyDependents(FOREVER,(PartID) PART_ALL,REFMSG_CHANGE);
		channel->mp->NotifyDependents(FOREVER,(PartID) PART_ALL,REFMSG_SUBANIM_STRUCTURE_CHANGED);
		channel->mp->Update_channelFULL();
		channel->mp->Update_channelParams();

		return true;
	}