//------------------------------
	bool SceneGraphCreator::create()
	{
		if ( !mVisualScene )
			return false;

		INode* rootNode = getMaxInterface()->GetRootNode();

//why does this not work: setting rotation on root node
// 		Matrix3 maxTransformationMatrix;
// 		Matrix4ToMaxMatrix3(maxTransformationMatrix, mUpAxisRotation);
// 		rootNode->SetNodeTM(0, maxTransformationMatrix);
// 
// 		Matrix3 x = rootNode->GetNodeTM(0);

		if( COLLADABU::Math::Matrix4::IDENTITY != mUpAxisRotation )
		{
			ImpNode* upAxisCorrectionNode = getMaxImportInterface()->CreateNode();
			Matrix3 maxTransformationMatrix;
			Matrix4ToMaxMatrix3( maxTransformationMatrix, mUpAxisRotation );
			upAxisCorrectionNode->SetName(__T("upaxis"));
			upAxisCorrectionNode->SetTransform(0, maxTransformationMatrix);
			INode* iNode = upAxisCorrectionNode->GetINode();
			upAxisCorrectionNode->Reference( getDummyObject() );
			rootNode->AttachChild(iNode, FALSE);
			importNodes(mVisualScene->getRootNodes(), iNode);
		}
		else
			importNodes(mVisualScene->getRootNodes(), rootNode);

		return true;
	}
示例#2
0
INode* NifImporter::CreateImportNode(const char *name, Object *obj, INode* parent)
{
#if USE_IMPORTNODE
	ImpNode* impNode = i->CreateNode();
	impNode->Reference(obj);
	if (INode *n = impNode->GetINode()) {
		n->SetName(const_cast<TCHAR*>(name));
		n->SetObjectRef(obj);
		i->AddNodeToScene(impNode);
		this->RegisterNode(name, n);
		if (parent)
		{
			parent->AttachChild(impNode->GetINode());

			ASSERT(parent == n->GetParentNode());

		}
	}
	return impNode->GetINode();
#else
	if ( INode* n = gi->CreateObjectNode(obj) )
	{
		n->SetName(const_cast<TCHAR*>(name));
		this->RegisterNode(name, n);
		if (parent)
		{
			parent->AttachChild(n);
			ASSERT(parent == n->GetParentNode());
		}
		return n;
	}
	return NULL;
	
#endif
}
	//------------------------------
	bool SceneGraphCreator::recursivelyCloneINode( ImpNode* parentImportNode, INode* nodeToClone )
	{
		ImpNode* newImportNode = getMaxImportInterface()->CreateNode();
		getMaxImportInterface()->AddNodeToScene(newImportNode);

		INode* newNode = newImportNode->GetINode();

		Object* object = nodeToClone->GetObjectRef();
		newImportNode->Reference(object);
		newNode->SetTMController(nodeToClone->GetTMController());
		newImportNode->SetName(nodeToClone->GetName());
		//used to assign material
		addClonedINodeOriginalINodePair(newNode, nodeToClone);

		INode* parentNode = parentImportNode->GetINode();
		parentNode->AttachChild(newNode, TRUE);

		/* If the node to clone references an object, the cloned one must references the same object.*/
		COLLADAFW::UniqueId id = getUniqueIdByObjectINode(nodeToClone);
		if ( id.isValid() )
		{
			addUniqueIdObjectINodePair(id, newNode);
			addObjectINodeUniqueIdPair(newNode, id);
		}

		// Clone the children 
		for ( int i = 0, count = nodeToClone->NumberOfChildren(); i < count; ++i)
			recursivelyCloneINode(newImportNode, nodeToClone->GetChildNode(i));

		return true;
	}
示例#4
0
INode* M2Importer::createGroupHeaderNode()
{
	DummyObject* obj = (DummyObject*)CreateInstance(HELPER_CLASS_ID, Class_ID(DUMMY_CLASS_ID, 0));

	ImpNode* node = m_impInterface->CreateNode();
	node->Reference(obj);
	m_impInterface->AddNodeToScene(node);

	return node->GetINode();
}
示例#5
0
INode* WMOGroupImpl::createGroupHeaderNode()
{
	DummyObject* obj = (DummyObject*)CreateInstance(HELPER_CLASS_ID, Class_ID(DUMMY_CLASS_ID, 0));

	ImpNode* node = m_wmoImporter->m_impInterface->CreateNode();
	node->Reference(obj);

	node->SetName(m_groupName.c_str());

	m_wmoImporter->m_impInterface->AddNodeToScene(node);

	return node->GetINode();
}
示例#6
0
int
OBJImport::DoImport(const TCHAR *filename,ImpInterface *i,Interface *gi, BOOL suppressPrompts) {
	TriObject *object = CreateNewTriObject();
	if(!object)
		return 0;
	if(objFileRead(filename, &object->GetMesh())) {
		ImpNode *node = i->CreateNode();
		if(!node) {
			delete object;
			return 0;
			}
		Matrix3 tm;
		tm.IdentityMatrix();
		node->Reference(object);
		node->SetTransform(0,tm);
		i->AddNodeToScene(node);
		node->SetName(GetString(IDS_TH_WAVE_OBJ_NAME));
		i->RedrawViews();
		return 1;
		}
	return 0;
	}
bool NifImporter::ImportMesh(NiTriStripsRef triStrips)
{
   bool ok = true;

   ImpNode *node = i->CreateNode();
   if(!node)
	   return false;
   INode *inode = node->GetINode();
   TriObject *triObject = CreateNewTriObject();
   node->Reference(triObject);
   wstring name = wide(triStrips->GetName());
   node->SetName(name.c_str());

   // Texture
   Mesh& mesh = triObject->GetMesh();
   NiTriStripsDataRef triStripsData = DynamicCast<NiTriStripsData>(triStrips->GetData());
   if (triStripsData == NULL)
      return false;

   vector<Triangle> tris = triStripsData->GetTriangles();
   ok |= ImportMesh(node, triObject, triStrips, triStripsData, tris);
   return ok;
}
		bool SceneGraphCreator::importInstances( const COLLADAFW::PointerArray<Instance>& instanceArray, ImpNode* parentImportNode )
	{
		for ( size_t i = 0, count = instanceArray.getCount(); i < count; ++i)
		{
			Instance* instance = instanceArray[i];

			ImpNode* newImportNode = getMaxImportInterface()->CreateNode();
			INode* newNode = newImportNode->GetINode();
			const COLLADAFW::UniqueId& uniqueId = instance->getInstanciatedObjectId();

			Object* object = getObjectByUniqueId(uniqueId);
			if ( object )
			{
				newImportNode->Reference(object);
			}
			else
			{
				newImportNode->Reference( getDummyObject() );
			}
			const COLLADAFW::UniqueId& instanceUniqueId = instance->getInstanciatedObjectId();
			// Store mapping between unique ids and nodes referencing the corresponding object.
			// Used to clone nodes
			addObjectINodeUniqueIdPair(newNode, instanceUniqueId);
			// Used to resolve instancing of objects
			addUniqueIdObjectINodePair(instanceUniqueId, newNode);

			INode* parentNode = parentImportNode->GetINode();
			parentNode->AttachChild(newNode, FALSE);

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

		return true;
	}
	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;
	}
	//------------------------------
	ImpNode* SceneGraphCreator::importNode( const COLLADAFW::Node* node, INode* parentINode )
	{
		bool singleInstance = (node->getInstanceGeometries().getCount() +
							   node->getInstanceControllers().getCount() +
			                   node->getInstanceCameras().getCount() +
							   node->getInstanceLights().getCount() ) == 1;
		ImpNode* newImportNode = 0;
		const COLLADAFW::UniqueId& nodeUniqueId = node->getUniqueId();

		if ( !singleInstance )
		{
			newImportNode = getMaxImportInterface()->CreateNode();

			setNodeProperties(node, newImportNode);
			getMaxImportInterface()->AddNodeToScene(newImportNode);

			RefResult res = newImportNode->Reference(getDummyObject());
			if ( node->getType() == COLLADAFW::Node::JOINT )
			{
				newImportNode->GetINode()->ShowBone(1);
			}

			importInstanceGeometries(node->getInstanceGeometries(), newImportNode);
			importInstanceControllers(node->getInstanceControllers(), newImportNode);
			importInstanceCameras(node->getInstanceCameras(), newImportNode);
			importInstanceLights(node->getInstanceLights(), newImportNode);
		}
		else
		{
			newImportNode = importInstanceGeometry( node, parentINode );

			if ( !newImportNode )
				newImportNode = importInstanceController( node, parentINode );

			if ( !newImportNode )
				newImportNode = importInstanceCamera( node, parentINode );

			if ( !newImportNode )
				newImportNode = importInstanceLight( node, parentINode );

			assert(newImportNode);
		}

		INode* childNode = newImportNode->GetINode();
		importNodes(node->getChildNodes(), childNode);

		// Append all nodes that are referenced by this node.
		importInstanceNodes(node->getInstanceNodes(), newImportNode);

		/** Store the unique id of the created node, to resolve references, when ever necessary.*/ 
		addUniqueIdINodePair( nodeUniqueId, newImportNode->GetINode());

		parentINode->AttachChild(childNode, FALSE);

#if 0
		/* if there are nodes that reference the just created node, clone this node
		and append it to the referencing node.*/
		ImpNode* referencingImpNode = 0;
		while ( referencingImpNode = getReferencingImpNodesByUniqueId(nodeUniqueId) )
		{
			removeUniqueIdReferencingImpNodePair( nodeUniqueId, referencingImpNode);
			recursivelyCloneINode( referencingImpNode, newImportNode->GetINode() );
		}
#endif
		return newImportNode;
	}
示例#11
0
BOOL objFileRead(const TCHAR *filename, ImpInterface *imp){
	FILE *fp;
    int i;
	tLump  *idxtable;

	if((fp = fopen(filename, "rb")) == NULL)
		return 0;

	fseek(fp, 0, SEEK_END);
	int fileSize = ftell(fp);
	fseek(fp, 0, SEEK_SET);

	char *data = new char[fileSize];
	fread(data, fileSize, 1, fp);

	tHeader *header = (tHeader *)data;
	if(*(int*)header->strID != CMAPHEADER_ID)
		return 0;

	if(header->version != CMAPHEADER_VERSION)
		return 0;

	idxtable = (tLump *)header + 1;

	tVertex *Verts = (tVertex *)(data + idxtable[kVertices].offset);	
	int NumVerts = idxtable[kVertices].length / sizeof(tVertex);

	tFace *faces = (tFace *)(data + idxtable[kLeafFaces].offset);	
	int NumFaces = idxtable[kLeafFaces].length / sizeof(tFace);

	int *elems = (int *)(data + idxtable[kElements].offset);	
	int NumElems = idxtable[kElements].length / sizeof(int);

	tArea *mAreas = (tArea *)(data + idxtable[kAreas].offset);
    int NumAreas = idxtable[kAreas].length / sizeof(tArea);

	Point3 p;

	TriObject *object = CreateNewTriObject();
	if(!object)
		return 0;
	
	Mesh *msh = &object->GetMesh();

	msh->setNumVerts(NumVerts);

	for(i = 0 ; i < NumVerts ; i++){
		msh->setVert(i, Verts[i].point[0], -Verts[i].point[2], Verts[i].point[1]);
		p.Set(Verts[i].norm[0], -Verts[i].norm[2], Verts[i].norm[1]);
		msh->setNormal(i, p);
	}

	int face = 0;
	for(int k = 1 ; k < NumAreas ; k++){
		for(i = mAreas[k].startFace ; i < mAreas[k].startFace + mAreas[k].numOfFaces ; i++){
			for(int j = faces[i].startElement ; j < faces[i].startElement + faces[i].elementsSize ; j++){
				int k = j * 3;
				if(elems[k] < 0){
					elems[k] = 0;
					elems[k+1] = 1;
					elems[k+2] = 2;
					faces[i].vertexIndex = 0;
				}
				msh->setNumFaces(face + 1, TRUE);
				msh->faces[face].setVerts(faces[i].vertexIndex + elems[k + 0], 
											faces[i].vertexIndex + elems[k + 1], 
											faces[i].vertexIndex + elems[k + 2]);
				msh->faces[face].setEdgeVisFlags(1, 1, 1);
				face++;
			}
		}
	}
	
	delete [] data;

	fclose(fp);
	msh->buildNormals();
	msh->buildBoundingBox();
	msh->InvalidateEdgeList();

	ImpNode *node = imp->CreateNode();
	if(!node) {
		delete object;
		return 0;
	}
	Matrix3 tm;
	tm.IdentityMatrix();
	node->Reference(object);
	node->SetTransform(0,tm);
	imp->AddNodeToScene(node);
	node->SetName(_T("Sylphis map"));


    return TRUE;
}
示例#12
0
void WMOGroupImpl::buildMaxData()
{
	// Group Header Node
	INode* groupHeadNode = createGroupHeaderNode();
	groupHeadNode->SetGroupHead(TRUE);
	groupHeadNode->SetGroupMember(FALSE);

	// Geoset
	// 一个Render Batch构造一个Node, 并且加入到组中

	for (int i = 0; i < m_batchCount; ++i)
	{
		WMORenderBatch& renderBatch = m_batchData[i];

		m_wmoImporter->m_logStream << "Model Geoset " << i << " Vertex Info: " 
			<< renderBatch.vertexStart << " -- " << renderBatch.vertexEnd << endl;
		m_wmoImporter->m_logStream << "Model Geoset " << i << " Index Info: " 
			<< renderBatch.indexStart << " -- " << renderBatch.indexCount << endl;

		// Triangle Mesh Object
		// 基本的三角形模型对象
		TriObject* triObject = CreateNewTriObject();

		// 创建Node, 并且设为Group Header Node的子节点
		ImpNode* tmpImpNode = m_wmoImporter->m_impInterface->CreateNode();
		tmpImpNode->Reference(triObject);

		m_wmoImporter->m_impInterface->AddNodeToScene(tmpImpNode);
		INode* realINode = tmpImpNode->GetINode();
		realINode->SetGroupHead(FALSE);
		realINode->SetGroupMember(TRUE);
		groupHeadNode->AttachChild(realINode);

		m_geosetNodeList.push_back(realINode);

		TCHAR nodeName[256];
		sprintf(nodeName, "%s_part_%03d", m_groupName.c_str(), i);
		realINode->SetName(nodeName);

		// mesh
		unsigned short vertexCount = renderBatch.vertexEnd - renderBatch.vertexStart + 1;
		unsigned int trigangleCount = renderBatch.indexCount / 3;

		Mesh& mesh = triObject->GetMesh();
		mesh.setNumVerts(vertexCount);
		mesh.setNumTVerts(vertexCount, TRUE);

		mesh.setNumFaces(trigangleCount);
		mesh.setNumTVFaces(trigangleCount);

		// 顶点坐标和UV
		for (int i = 0; i < vertexCount; ++i)
		{
			mesh.verts[i] = *(Point3*)(&(m_vertexData[renderBatch.vertexStart + i]));

			// UV坐标反转
			mesh.tVerts[i].x = m_textureCoords[renderBatch.vertexStart + i].x;
			mesh.tVerts[i].y = 1.0f - m_textureCoords[renderBatch.vertexStart + i].y;
		}

		// 三角形
		for (unsigned int i = 0; i < trigangleCount; ++i)
		{
			Face& face = mesh.faces[i];
			int index1 = m_indexData[renderBatch.indexStart + i*3] - renderBatch.vertexStart;
			int index2 = m_indexData[renderBatch.indexStart + i*3+1] - renderBatch.vertexStart;
			int index3 = m_indexData[renderBatch.indexStart + i*3+2] - renderBatch.vertexStart;

			face.setVerts(index1, index2, index3);
			face.Show();
			face.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS);

			TVFace& tface = mesh.tvFace[i];
			tface.setTVerts(index1, index2, index3);
		}

		// 法线
		mesh.SpecifyNormals();
		MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals();
		if (specNorms)
		{
			specNorms->ClearAndFree();
			specNorms->SetNumFaces(trigangleCount);
			specNorms->SetNumNormals(vertexCount);

			Point3* norms = specNorms->GetNormalArray();
			for (int i = 0; i < vertexCount; ++i)
			{
				norms[i] = *(Point3*)(&m_normalData[renderBatch.vertexStart + i]);
			}

			MeshNormalFace* pFaces = specNorms->GetFaceArray();
			for (unsigned int i = 0; i < trigangleCount; ++i)
			{
				int index1 = m_indexData[renderBatch.indexStart + i*3] - renderBatch.vertexStart;
				int index2 = m_indexData[renderBatch.indexStart + i*3+1] - renderBatch.vertexStart;
				int index3 = m_indexData[renderBatch.indexStart + i*3+2] - renderBatch.vertexStart;

				pFaces[i].SpecifyNormalID(0, index1);
				pFaces[i].SpecifyNormalID(1, index2);
				pFaces[i].SpecifyNormalID(2, index3);
			}

			specNorms->SetAllExplicit(true);
			specNorms->CheckNormals();
		}

		// 删除重复的和无效的面
		mesh.RemoveDegenerateFaces();
		mesh.RemoveIllegalFaces();

		realINode->SetMtl(m_wmoImporter->m_materialList[renderBatch.texture]);
		//realINode->BackCull(FALSE);			// 取消背面裁减 不是所有的Node都要取消背面裁减
		realINode->EvalWorldState(0);
	}
}
示例#13
0
// 1. 加载模型顶点数据
void M2Importer::importGeomObject()
{
	// Group Header Node
	INode* groupHeadNode = createGroupHeaderNode();
	groupHeadNode->SetGroupHead(TRUE);
	groupHeadNode->SetGroupMember(FALSE);

	if (m_modelHeader->nameLength > 1)
	{
		TCHAR* modelName = (TCHAR*)(m_m2FileData + m_modelHeader->nameOfs);
		groupHeadNode->SetName(modelName);
		m_logStream << "ModelName: " << modelName << endl;
	}
	else
		groupHeadNode->SetName("GeomGroup");


	// Geoset
	// 一个Geoset构造一个Node, 并且加入到组中

	unsigned short* verDataIndex = (unsigned short*)(m_m2FileData + m_modelView->ofsIndex);
	unsigned short* triData = (unsigned short*)(m_m2FileData + m_modelView->ofsTris);

	m_geosetNodeList.reserve(m_modelView->nSub);
	m_materialList.reserve(m_modelView->nSub);
	for (unsigned int i = 0; i < m_modelView->nSub; ++i)
		m_materialList.push_back(0);

	for (unsigned int i = 0; i < m_modelView->nSub; ++i)
	{
		ModelGeoset& geosetData = m_modelGeoset[i];

		// Triangle Mesh Object
		// 基本的三角形模型对象
		TriObject* triObject = CreateNewTriObject();

		// 创建Node, 并且设为Group Header Node的子节点
		ImpNode* tmpImpNode = m_impInterface->CreateNode();
		tmpImpNode->Reference(triObject);
		//tmpImpNode->SetPivot(*(Point3*)&(geosetData.v));

		m_impInterface->AddNodeToScene(tmpImpNode);
		INode* realINode = tmpImpNode->GetINode();
		realINode->SetGroupHead(FALSE);
		realINode->SetGroupMember(TRUE);
		groupHeadNode->AttachChild(realINode);

		m_geosetNodeList.push_back(realINode);

		TCHAR nodeName[256];
		sprintf(nodeName, "GeosetPart_%d", i);
		realINode->SetName(nodeName);

		// mesh
		Mesh& mesh = triObject->GetMesh();
		mesh.setNumVerts(geosetData.vcount);
		mesh.setNumTVerts(geosetData.vcount, TRUE);

		unsigned int triangeCount = geosetData.icount / 3;
		mesh.setNumFaces(triangeCount);
		mesh.setNumTVFaces(triangeCount);

		m_logStream << "Model Geoset " << i << " Vertex Count: " << geosetData.vcount << endl;
		m_logStream << "Model Geoset " << i << " Index Count: " << triangeCount << endl;

		// 顶点坐标和UV
		for (unsigned int i = 0; i < geosetData.vcount; ++i)
		{
			ModelVertex& vertexData = m_globalVertices[ verDataIndex[geosetData.vstart + i] ];

			mesh.verts[i] = *(Point3*)(&vertexData.pos);

			// UV坐标反转
			mesh.tVerts[i].x = vertexData.texcoords.x;
			mesh.tVerts[i].y = 1.0f - vertexData.texcoords.y;
		}

		// 三角形
		for (unsigned int i = 0; i < triangeCount; ++i)
		{
			Face& face = mesh.faces[i];
			face.setVerts(triData[geosetData.istart + i*3] - m_indexCount, 
						  triData[geosetData.istart + i*3+1] - m_indexCount, 
						  triData[geosetData.istart + i*3+2] - m_indexCount);
			face.Show();
			face.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS);

			TVFace& tface = mesh.tvFace[i];
			tface.setTVerts(triData[geosetData.istart + i*3] - m_indexCount, 
							triData[geosetData.istart + i*3+1] - m_indexCount, 
							triData[geosetData.istart + i*3+2] - m_indexCount);
		}

		// 法线
		mesh.SpecifyNormals();
		MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals();
		if (specNorms)
		{
			specNorms->ClearAndFree();
			specNorms->SetNumFaces(triangeCount);
			specNorms->SetNumNormals(geosetData.vcount);

			Point3* norms = specNorms->GetNormalArray();
			for (unsigned int i = 0; i < geosetData.vcount; ++i)
			{
				ModelVertex& vertexData = m_globalVertices[ verDataIndex[geosetData.vstart + i] ];
				norms[i] = *(Point3*)(&vertexData.normal);
			}

			MeshNormalFace* pFaces = specNorms->GetFaceArray();
			for (unsigned int i = 0; i < triangeCount; ++i)
			{
				pFaces[i].SpecifyNormalID(0, triData[geosetData.istart + i*3] - m_indexCount);
				pFaces[i].SpecifyNormalID(1, triData[geosetData.istart + i*3+1] - m_indexCount);
				pFaces[i].SpecifyNormalID(2, triData[geosetData.istart + i*3+2] - m_indexCount);
			}

			specNorms->SetAllExplicit(true);
			specNorms->CheckNormals();
		}

		// 删除重复的和无效的面
		mesh.RemoveDegenerateFaces();
		mesh.RemoveIllegalFaces();

		//realINode->BackCull(FALSE);			// 取消背面裁减 双面绘制与取消背面裁减一起设置
		realINode->EvalWorldState(0);

		// 索引值修正
		m_indexCount += geosetData.vcount;
	}

	// 加载材质
	unsigned short* texLookupData = (unsigned short*)(m_m2FileData + m_modelHeader->ofsTexLookup);
	ModelTextureDef* texUnitDefData = (ModelTextureDef*)(m_m2FileData + m_modelHeader->ofsTextures);
	ModelTexUnit* texUnitData = (ModelTexUnit*)(m_m2FileData + m_modelView->ofsTex);

	for (unsigned int i = 0; i < m_modelView->nTex; ++i)
	{
		ModelTexUnit& texUnit = texUnitData[i];
		unsigned short textureID = texLookupData[texUnit.textureid];
		ModelTextureDef& texDef = texUnitDefData[textureID];

		string textureName;

		if (texDef.type == 0)
			textureName = (LPCSTR)(m_m2FileData + texDef.nameOfs);
		else
			textureName = getReplacableTexture(texDef.type);

		StdMat2* material = m_materialList[texUnit.op];
		if (!material)
			material = createMaterial();

		// 根据混合属性决定加在第几层
		material->SetSubTexmap(ID_DI, createTexture(textureName.c_str()));
		material->EnableMap(ID_DI, TRUE);
		//material->SetTwoSided(TRUE);		// 双面 设置了此标志的才打开

		m_maxInterface->GetMaterialLibrary().Add(material);
		m_geosetNodeList[texUnit.op]->SetMtl(material);
	}

	m_maxInterface->RedrawViews(m_maxInterface->GetTime());
}
bool PlasmaImport::IImportObject(plSceneObject *obj, ImpInterface *imp)
{
    if (!obj->getDrawInterface().isLoaded())
        return false;

    plDrawInterface* draw = plDrawInterface::Convert(obj->getDrawInterface()->getObj());
    plCoordinateInterface* coord = NULL;
    if (obj->getCoordInterface().Exists())
        coord = plCoordinateInterface::Convert(obj->getCoordInterface()->getObj());

    TriObject *maxObj = CreateNewTriObject();
    Mesh *msh = &maxObj->GetMesh();

    std::vector<Point3> vertexList;
    std::vector<int> indexList;

    if (!maxObj)
        return false;

    // read the object from PRP
    for (size_t i = 0; i < draw->getNumDrawables(); i++)
    {
        if (draw->getDrawableKey(i) == -1)
            continue;

        plDrawableSpans* span = plDrawableSpans::Convert(draw->getDrawable(i)->getObj());
        plDISpanIndex di = span->getDIIndex(draw->getDrawableKey(i));
        if ((di.fFlags & plDISpanIndex::kMatrixOnly) != 0)
            continue;

        for (size_t idx = 0; idx < di.fIndices.size(); idx++)
        {
            plIcicle* ice = (plIcicle*)span->getSpan(di.fIndices[idx]);
            std::vector<plGBufferVertex> verts = span->getVerts(ice);
            std::vector<unsigned short> indices = span->getIndices(ice);

            for (size_t j = 0; j < verts.size(); j++)
            {
                hsVector3 pos;
                if (coord != NULL)
                    pos = coord->getLocalToWorld().multPoint(verts[j].fPos) * 10.0f;
                else
                    pos = ice->getLocalToWorld().multPoint(verts[j].fPos) * 10.0f;
                vertexList.push_back(Point3(pos.X, pos.Y, pos.Z));
            }
            
            indexList.insert(indexList.end(), indices.begin(), indices.end());
        }
    }
    
    //create the Mesh
    msh->setNumVerts(vertexList.size());
    msh->setNumFaces(indexList.size()/3);
    for (size_t i = 0; i < vertexList.size(); i++)
        msh->setVert(i, vertexList[i]);

    for (size_t i = 0; i < indexList.size()/3; i++)
    {
        int v1, v2, v3;
        v1 = indexList[3*i];
        v2 = indexList[3*i+1];
        v3 = indexList[3*i+2];

        msh->faces[i].setVerts(v1, v2, v3);
        msh->faces[i].setEdgeVisFlags(1,1,1); //we asume we have Triangles obnly
    }

    msh->buildNormals();
    msh->buildBoundingBox();
    msh->InvalidateEdgeList();

    //Add Object To Scene
    ImpNode *node = imp->CreateNode();
    Matrix3 tm;
    tm.IdentityMatrix();
    node->Reference(maxObj);
    node->SetTransform(0,tm);
    imp->AddNodeToScene(node);
    node->SetName(obj->getKey()->getName());
    imp->RedrawViews();

    return true;
}
示例#15
0
BOOL AIShapeImport::FinishWorkingShape(BOOL forceFinish, ImpInterface *i) {
	// If nothing going on, forget the whole thing and return success
	if(!splShape)
		return TRUE;
	if(!shape) {
		assert(0);
		return FALSE;
		}
	// Otherwise, see if the current spline is closed
	if(spline) {
		int knots = spline->KnotCount();
		// If not a valid spline, get rid of it!
		if(knots < 2) {
			singularity:
//			DebugPrint("WARN: spline w/%d points\n",knots);
			shape->UpdateSels();	// Make sure it readies the selection set info
			shape->DeleteSpline(shape->SplineCount() - 1);
			spline = NULL;
			}
		else {
			int lastKnot = knots-1;
			if(spline->GetKnotPoint(0) == spline->GetKnotPoint(lastKnot)) {
				spline->SetInVec(0, spline->GetInVec(lastKnot));
				spline->DeleteKnot(lastKnot);
				if(spline->KnotCount() < 2)
					goto singularity;
				spline->SetClosed();
				}
			// Check to be sure knot types are correct -- The default is for
			// smooth beziers, but they may be corners
			for(int k = 0; k < knots; ++k) {
				Point3 in = spline->GetInVec(k);
				Point3 out = spline->GetOutVec(k);
				Point3 knot = spline->GetKnotPoint(k);
				int type = spline->GetKnotType(k);
				if(type == KTYPE_BEZIER) {
					if(in == knot && out == knot)	// If both zero length vector, it's a corner
						spline->SetKnotType(k, KTYPE_CORNER);
					else	// If vectors not collinear, it's a corner!
					if(in == knot || out == knot)	// If zero length vector, it's a bez corner
						spline->SetKnotType(k, KTYPE_BEZIER_CORNER);
					else {	// If vectors not collinear, it's a corner!
						Point3 normIn = Normalize(knot - in);
						Point3 normOut = Normalize(out - knot);
						Point3 lowtest = normIn * 0.98f;
						Point3 hightest = normIn * 1.02f;
						if(!(((normOut.x >= lowtest.x && normOut.x <= hightest.x) || (normOut.x <= lowtest.x && normOut.x >= hightest.x)) && 
						   ((normOut.y >= lowtest.y && normOut.y <= hightest.y) || (normOut.y <= lowtest.y && normOut.y >= hightest.y)) && 
						   ((normOut.z >= lowtest.z && normOut.z <= hightest.z) || (normOut.z <= lowtest.z && normOut.z >= hightest.z))))
							spline->SetKnotType(k, KTYPE_BEZIER_CORNER);
						}
					}
				}
			spline->ComputeBezPoints();
			}
		}
	// If necessary, create the object
	if(importType == MULTIPLE_SHAPES || forceFinish) {
		if(shape->SplineCount()) {
			shape->UpdateSels();	// Make sure it readies the selection set info
			shape->InvalidateGeomCache();
			// create shape object
			ImpNode *node = i->CreateNode();
			if(!node)
				return FALSE;
			node->Reference(splShape);
			Matrix3 tm(1);
			Box3 bbox = shape->GetBoundingBox();
			Point3 center = Point3(bbox.Center().x, bbox.Center().y, 0.0f);
			tm.SetTrans(center);	// TH 7/5/96
			node->SetPivot(-center);	// TH 3/9/99
			node->SetTransform(0,tm);
			i->AddNodeToScene(node);
			TSTR name;
			name.printf(GetString(IDS_TH_SHAPE_NUM),theShapeImport->shapeNumber++);
			node->SetName(name);
			gotStuff = TRUE;
			}
		// Reset the shape stuff
		splShape = NULL;
		shape = NULL;
		spline = NULL;
		}
	return TRUE;
	}
bool NifImporter::ImportMultipleGeometry(NiNodeRef parent, vector<NiTriBasedGeomRef>& glist)
{
   bool ok = true;
   if (glist.empty()) return false;

   ImpNode *node = i->CreateNode();
   if(!node) return false;

   INode *inode = node->GetINode();
   TriObject *triObject = CreateNewTriObject();
   node->Reference(triObject);

   string name = parent->GetName();
   node->SetName(wide(name).c_str());

   // Texture
   Mesh& mesh = triObject->GetMesh();

   vector< pair<int, int> > vert_range, tri_range;
   vector<Triangle> tris;
   vector<Vector3> verts;
   int submats = glist.size();

   // Build list of vertices and triangles.  Optional components like normals will be handled later.
   for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr) {
      NiTriBasedGeomDataRef triGeomData = StaticCast<NiTriBasedGeomData>((*itr)->GetData());

      // Get verts and collapse local transform into them
      int nVertices = triGeomData->GetVertexCount();
      vector<Vector3> subverts = triGeomData->GetVertices();
      Matrix44 transform = (*itr)->GetLocalTransform();
      //Apply the transformations
      if (transform != Matrix44::IDENTITY) {
         for ( unsigned int i = 0; i < subverts.size(); ++i )
            subverts[i] = transform * subverts[i];
      }
      vert_range.push_back( pair<int,int>( verts.size(), verts.size() + subverts.size()) );
      verts.insert(verts.end(), subverts.begin(), subverts.end());

      vector<Triangle> subtris = triGeomData->GetTriangles();
      for (vector<Triangle>::iterator itr = subtris.begin(), end = subtris.end(); itr != end; ++itr) {
         (*itr).v1 += nVertices, (*itr).v2 += nVertices, (*itr).v3 += nVertices;
      }
      tri_range.push_back( pair<int,int>( tris.size(), tris.size() + subtris.size()) );
      tris.insert(tris.end(), subtris.begin(), subtris.end());
   }

   // Transform up-to-parent
   Matrix44 baseTM = (importBones) ? Matrix44::IDENTITY : parent->GetWorldTransform();
   node->SetTransform(0,TOMATRIX3(baseTM));  

   // Set vertices and triangles
   mesh.setNumVerts(verts.size());
   mesh.setNumTVerts(verts.size(), TRUE);
   for (int i=0, n=verts.size(); i < n; ++i){
      Vector3 &v = verts[i];
      mesh.verts[i].Set(v.x, v.y, v.z);
   }
   mesh.setNumFaces(tris.size());
   mesh.setNumTVFaces(tris.size());
   for (int submat=0; submat<submats; ++submat) {
      int t_start = tri_range[submat].first, t_end = tri_range[submat].second;
      for (int i=t_start; i<t_end; ++i) {
         Triangle& t = tris[i];
         Face& f = mesh.faces[i];
         f.setVerts(t.v1, t.v2, t.v3);
         f.Show();
         f.setEdgeVisFlags(EDGE_VIS, EDGE_VIS, EDGE_VIS);
         f.setMatID(-1);
         TVFace& tf = mesh.tvFace[i];
         tf.setTVerts(t.v1, t.v2, t.v3);
      }
   }
   mesh.buildNormals();
   bool bSpecNorms = false;

   MultiMtl *mtl = NULL;
   int igeom = 0;
   for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr, ++igeom) 
   {
      NiTriBasedGeomDataRef triGeomData = StaticCast<NiTriBasedGeomData>((*itr)->GetData());

      int v_start = vert_range[igeom].first, v_end = vert_range[igeom].second;
      int t_start = tri_range[igeom].first, t_end = tri_range[igeom].second;

      // Normals
      vector<Vector3> subnorms = triGeomData->GetNormals();
      Matrix44 rotation = (*itr)->GetLocalTransform().GetRotation();
      if (rotation != Matrix44::IDENTITY) {
         for ( unsigned int i = 0; i < subnorms.size(); ++i )
            subnorms[i] = rotation * subnorms[i];
      }
      if (!subnorms.empty())
      {
#if VERSION_3DSMAX > ((5000<<16)+(15<<8)+0) // Version 5
         // Initialize normals if necessary
         if (!bSpecNorms) {
            bSpecNorms = true;
            mesh.SpecifyNormals();
            MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals();
            if (NULL != specNorms) {
               specNorms->BuildNormals();
               //specNorms->ClearAndFree();
               //specNorms->SetNumFaces(tris.size());
               //specNorms->SetNumNormals(n.size());
            }
         }
         MeshNormalSpec *specNorms = mesh.GetSpecifiedNormals();
         if (NULL != specNorms)
         {
            Point3* norms = specNorms->GetNormalArray();
            for (int i=0, n=subnorms.size(); i<n; i++){
               Vector3& v = subnorms[i];
               norms[i+v_start] = Point3(v.x, v.y, v.z);
            }
            //MeshNormalFace* pFaces = specNorms->GetFaceArray();
            //for (int i=0; i<tris.size(); i++){
            //   Triangle& tri = tris[i];
            //   MeshNormalFace& face = pFaces[i+t_start];
            //   face.SpecifyNormalID(0, tri.v1);
            //   face.SpecifyNormalID(1, tri.v2);
            //   face.SpecifyNormalID(2, tri.v3);
            //}
#if VERSION_3DSMAX > ((7000<<16)+(15<<8)+0) // Version 7+
			specNorms->SetAllExplicit(true);
#endif
            specNorms->CheckNormals();
         }
#endif
      }
      // uv texture info
      if (triGeomData->GetUVSetCount() > 0) {
         vector<TexCoord> texCoords = triGeomData->GetUVSet(0);
         for (int i=0, n = texCoords.size(); i<n; ++i) {
            TexCoord& texCoord = texCoords[i];
            mesh.tVerts[i+v_start].Set(texCoord.u, (flipUVTextures) ? 1.0f-texCoord.v : texCoord.v, 0);
         }
      }
      vector<Color4> cv = triGeomData->GetColors();
      ImportVertexColor(inode, triObject, tris, cv, v_start);

      if ( StdMat2* submtl = ImportMaterialAndTextures(node, (*itr)) )
      {
         if (mtl == NULL) {
            mtl = NewDefaultMultiMtl();
            gi->GetMaterialLibrary().Add(mtl);
            inode->SetMtl(mtl);
         }
         // SubMatIDs do not have to be contiguous so we just use the offset
         mtl->SetSubMtlAndName(igeom, submtl, submtl->GetName());
         for (int i=t_start; i<t_end; ++i)
            mesh.faces[i].setMatID(igeom);
      }
      if (enableSkinSupport)
         ImportSkin(node, (*itr));
   }

   this->i->AddNodeToScene(node);   

   inode = node->GetINode();
   inode->EvalWorldState(0);

   for (vector<NiTriBasedGeomRef>::iterator itr = glist.begin(), end = glist.end(); itr != end; ++itr) 
   {
      // attach child
      if (INode *parent = GetNode((*itr)->GetParent()))
         parent->AttachChild(inode, 1);
      inode->Hide((*itr)->GetVisibility() ? FALSE : TRUE);
   }
   if (removeDegenerateFaces)
      mesh.RemoveDegenerateFaces();
   if (removeIllegalFaces)
      mesh.RemoveIllegalFaces();
   if (weldVertices)
	   WeldVertices(mesh);
   if (enableAutoSmooth)
      mesh.AutoSmooth(TORAD(autoSmoothAngle), FALSE, FALSE);
   return ok;
}
示例#17
0
int IFCImp::DoImport(const TCHAR *name, ImpInterface *impitfc, Interface *itfc, BOOL suppressPrompts) {

	IfcGeom::IteratorSettings settings;
	settings.use_world_coords() = false;
	settings.weld_vertices() = true;
	settings.sew_shells() = true;

#ifdef _UNICODE
	int fn_buffer_size = WideCharToMultiByte(CP_UTF8, 0, name, -1, 0, 0, 0, 0);
	char* fn_mb = new char[fn_buffer_size];
	WideCharToMultiByte(CP_UTF8, 0, name, -1, fn_mb, fn_buffer_size, 0, 0);
#else
	const char* fn_mb = name;
#endif

	IfcGeom::Iterator<float> iterator(settings, fn_mb);

	if (!iterator.initialize()) return false;

	itfc->ProgressStart(_T("Importing file..."), TRUE, fn, NULL);

	MtlBaseLib* mats = itfc->GetSceneMtls();
	int slot = mats->Count();

	std::map<std::vector<std::string>, Mtl*> material_cache;

	do{
		const IfcGeom::TriangulationElement<float>* o = static_cast<const IfcGeom::TriangulationElement<float>*>(iterator.get());

		TSTR o_type = S(o->type());
		TSTR o_guid = S(o->guid());

		Mtl *m = ComposeMultiMaterial(material_cache, mats, itfc, slot, o->geometry().materials(), o->type(), o->geometry().material_ids());

		TriObject* tri = CreateNewTriObject();

		const int numVerts = o->geometry().verts().size()/3;
		tri->mesh.setNumVerts(numVerts);
		for( int i = 0; i < numVerts; i ++ ) {
			tri->mesh.setVert(i,o->geometry().verts()[3*i+0],o->geometry().verts()[3*i+1],o->geometry().verts()[3*i+2]);
		}
		const int numFaces = o->geometry().faces().size()/3;
		tri->mesh.setNumFaces(numFaces);

		bool needs_default = std::find(o->geometry().material_ids().begin(), o->geometry().material_ids().end(), -1) != o->geometry().material_ids().end();

		typedef std::pair<int, int> edge_t;

		std::set<edge_t> face_boundaries;
		for(std::vector<int>::const_iterator it = o->geometry().edges().begin(); it != o->geometry().edges().end();) {
			const int v1 = *it++;
			const int v2 = *it++;

			const edge_t e((std::min)(v1, v2), (std::max)(v1, v2));
			face_boundaries.insert(e);
		}

		for( int i = 0; i < numFaces; i ++ ) {
			const int v1 = o->geometry().faces()[3*i+0];
			const int v2 = o->geometry().faces()[3*i+1];
			const int v3 = o->geometry().faces()[3*i+2];
			
			const edge_t e1((std::min)(v1, v2), (std::max)(v1, v2));
			const edge_t e2((std::min)(v2, v3), (std::max)(v2, v3));
			const edge_t e3((std::min)(v3, v1), (std::max)(v3, v1));

			const bool b1 = face_boundaries.find(e1) != face_boundaries.end();
			const bool b2 = face_boundaries.find(e2) != face_boundaries.end();
			const bool b3 = face_boundaries.find(e3) != face_boundaries.end();

			tri->mesh.faces[i].setVerts(v1, v2, v3);
			tri->mesh.faces[i].setEdgeVisFlags(b1, b2, b3);

			MtlID mtlid = o->geometry().material_ids()[i];
			if (needs_default) {
				mtlid ++;
			}
			tri->mesh.faces[i].setMatID(mtlid);
		}
				
		tri->mesh.buildNormals();
		// Either use this or undefine the FACESETS_AS_COMPOUND option in IfcGeom.h to have
		// properly oriented normals. Using only the line below will result in a consistent
		// orientation of normals accross shells, but not always oriented towards the
		// outside.
		// tri->mesh.UnifyNormals(false);
		tri->mesh.BuildStripsAndEdges();
		tri->mesh.InvalidateTopologyCache();
		tri->mesh.InvalidateGeomCache();

		ImpNode* node = impitfc->CreateNode();
		node->Reference(tri);
		node->SetName(o_guid);
		node->GetINode()->Hide(o->type() == "IfcOpeningElement" || o->type() == "IfcSpace");
		if (m) {
			node->GetINode()->SetMtl(m);
		}
		const std::vector<float>& matrix_data = o->transformation().matrix().data();
		node->SetTransform(0,Matrix3 ( Point3(matrix_data[0],matrix_data[1],matrix_data[2]),Point3(matrix_data[3],matrix_data[4],matrix_data[5]),
			Point3(matrix_data[6],matrix_data[7],matrix_data[8]),Point3(matrix_data[9],matrix_data[10],matrix_data[11]) ));
		impitfc->AddNodeToScene(node);

		itfc->ProgressUpdate(iterator.progress(), true, _T(""));

	} while (iterator.next());

	itfc->ProgressEnd();
	
	return true;
}
示例#18
0
// 2. 加载骨骼数据
void M2Importer::importBoneObject()
{
	// Bone Group Header Node
	INode* groupHeadNode = createGroupHeaderNode();
	groupHeadNode->SetGroupHead(TRUE);
	groupHeadNode->SetGroupMember(FALSE);

	if (m_modelHeader->nameLength > 1)
	{
		TCHAR* modelName = (TCHAR*)(m_m2FileData + m_modelHeader->nameOfs);
		TCHAR boneGroupName[256];
		sprintf(boneGroupName, "%s_bone", modelName);
		groupHeadNode->SetName(boneGroupName);
	}
	else
		groupHeadNode->SetName("BoneGroup");


	// Bone
	// 一个Bone构造一个Node, 并且加入到组中

	ModelBoneDef* boneData = (ModelBoneDef*)(m_m2FileData + m_modelHeader->ofsBones);

	m_boneNodeList.reserve(m_modelHeader->nBones);
	for (unsigned int i = 0; i < m_modelHeader->nBones; ++i)
	{
		ModelBoneDef& boneDef = boneData[i];

		// create bone node
		HelperObject* obj = (HelperObject*)CreateInstance(HELPER_CLASS_ID, Class_ID(BONE_CLASS_ID, 0));

		ImpNode* node = m_impInterface->CreateNode();

		TCHAR boneName[256];
		sprintf(boneName, "bone_%02d", i);
		node->SetName(boneName);

		node->SetPivot(*(Point3*)&(boneDef.pivot));
		node->Reference(obj);

		m_impInterface->AddNodeToScene(node);

		// 设置变换矩阵
		Matrix3 tm;
		tm.IdentityMatrix();
		tm.SetTrans(*(Point3*)&(boneDef.pivot));
		node->SetTransform(0, tm);

		// 添加到组
		INode* realINode = node->GetINode();
		realINode->SetGroupHead(FALSE);
		realINode->SetGroupMember(TRUE);
		groupHeadNode->AttachChild(realINode);

		// 设置Bone父子关系
		realINode->ShowBone(2);
		m_boneNodeList.push_back(realINode);
		if (boneDef.parent != -1)
		{
			INode* parentNode = m_boneNodeList[boneDef.parent];
			parentNode->AttachChild(realINode);
		}

		realINode->EvalWorldState(0);
	}

	// 导入每根骨骼的关键桢数据
	for (unsigned int i = 0; i < m_modelHeader->nBones; ++i)
	{
		ModelBoneDef& boneDef = boneData[i];
		INode* realINode = m_boneNodeList[i];

		Control* tmControl = realINode->GetTMController();

		// Position
		if (boneDef.translation.nKeys)
		{
			// 设置动画控制器为线性控制器
			Control* posControl = createPositionController();
			tmControl->SetPositionController(posControl);

			unsigned int* timeData = (unsigned int*)(m_m2FileData + boneDef.translation.ofsTimes);
			Point3* keyData = (Point3*)(m_m2FileData + boneDef.translation.ofsKeys);

			// 设置动画时间范围
			bool animRangeChanged = false;
			Interval animRange = m_maxInterface->GetAnimRange();
			for (unsigned int j = 0; j < boneDef.translation.nKeys; ++j)
			{
				if (timeData[j] < animRange.Start())
				{
					animRange.SetStart(timeData[j]);
					animRangeChanged = true;
				}
				else if (timeData[j] > animRange.End())
				{
					animRange.SetEnd(timeData[j]);
					animRangeChanged = true;
				}
			}
			if (animRangeChanged)
				m_maxInterface->SetAnimRange(animRange);

			// 设置动画关键桢数据
			Control* xControl = posControl->GetXController();
			IKeyControl* xKeyControl = GetKeyControlInterface(xControl);
			xKeyControl->SetNumKeys(boneDef.translation.nKeys);

			Control* yControl = posControl->GetYController();
			IKeyControl* yKeyControl = GetKeyControlInterface(yControl);
			yKeyControl->SetNumKeys(boneDef.translation.nKeys);

			Control* zControl = posControl->GetZController();
			IKeyControl* zKeyControl = GetKeyControlInterface(zControl);
			zKeyControl->SetNumKeys(boneDef.translation.nKeys);

			for (unsigned int j = 0; j < boneDef.translation.nKeys; ++j)
			{
				// X
				AnyKey bufX;
				ILinFloatKey* keyX = reinterpret_cast<ILinFloatKey*>((IKey*)bufX);
				keyX->time = timeData[j];
				keyX->val = keyData[j].x;
				xKeyControl->AppendKey(keyX);

				// Y
				AnyKey bufY;
				ILinFloatKey* keyY = reinterpret_cast<ILinFloatKey*>((IKey*)bufY);
				keyY->time = timeData[j];
				keyY->val = keyData[j].y;
				yKeyControl->AppendKey(keyY);

				// Z
				AnyKey bufZ;
				ILinFloatKey* keyZ = reinterpret_cast<ILinFloatKey*>((IKey*)bufZ);
				keyZ->time = timeData[j];
				keyZ->val = keyData[j].z;
				zKeyControl->AppendKey(keyZ);
			}
		}
/*
		// Rotation
		if (boneDef.rotation.nKeys)
		{
			Control* rotControl = createRotationController();
			tmControl->SetRotationController(rotControl);

			unsigned int* timeData = (unsigned int*)(m_m2FileData + boneDef.rotation.ofsTimes);
			Quat* keyData = (Quat*)(m_m2FileData + boneDef.rotation.ofsKeys);

			// 设置动画时间范围
			bool animRangeChanged = false;
			Interval animRange = m_maxInterface->GetAnimRange();
			for (unsigned int j = 0; j < boneDef.rotation.nKeys; ++j)
			{
				if (timeData[j] < animRange.Start())
				{
					animRange.SetStart(timeData[j]);
					animRangeChanged = true;
				}
				else if (timeData[j] > animRange.End())
				{
					animRange.SetEnd(timeData[j]);
					animRangeChanged = true;
				}
			}
			if (animRangeChanged)
				m_maxInterface->SetAnimRange(animRange);

			// 设置动画关键桢数据
			IKeyControl* keyControl = GetKeyControlInterface(rotControl);
			keyControl->SetNumKeys(boneDef.rotation.nKeys);

			for (unsigned int j = 0; j < boneDef.rotation.nKeys; ++j)
			{
				AnyKey buf;
				ILinRotKey* key = reinterpret_cast<ILinRotKey*>((IKey*)buf);
				key->time = timeData[j];
				key->val = keyData[j];
				keyControl->AppendKey(key);
			}
		}
*/
		// Scaling
		if (boneDef.scaling.nKeys)
		{
			Control* scaControl = createScaleController();
			tmControl->SetScaleController(scaControl);

			unsigned int* timeData = (unsigned int*)(m_m2FileData + boneDef.scaling.ofsTimes);
			Point3* keyData = (Point3*)(m_m2FileData + boneDef.scaling.ofsKeys);

			// 设置动画时间范围
			bool animRangeChanged = false;
			Interval animRange = m_maxInterface->GetAnimRange();
			for (unsigned int j = 0; j < boneDef.scaling.nKeys; ++j)
			{
				if (timeData[j] < animRange.Start())
				{
					animRange.SetStart(timeData[j]);
					animRangeChanged = true;
				}
				else if (timeData[j] > animRange.End())
				{
					animRange.SetEnd(timeData[j]);
					animRangeChanged = true;
				}
			}
			if (animRangeChanged)
				m_maxInterface->SetAnimRange(animRange);

			// 设置动画关键桢数据
			IKeyControl* keyControl = GetKeyControlInterface(scaControl);
			keyControl->SetNumKeys(boneDef.scaling.nKeys);

			for (unsigned int j = 0; j < boneDef.scaling.nKeys; ++j)
			{
				AnyKey buf;
				ILinScaleKey* key = reinterpret_cast<ILinScaleKey*>((IKey*)buf);
				key->time = timeData[j];
				key->val = ScaleValue(keyData[j]);
				keyControl->AppendKey(key);
			}
		}
	}
}