Example #1
0
Scene3DMesh* SGMExporter::ConvertMesh(IGameNode* meshNode)
{
	std::string meshNodeName = StringUtils::ToNarrow(meshNode->GetName());

	Log::LogT("exporting node '%s'", meshNodeName.c_str());

	IGameMesh *gMesh = (IGameMesh*)meshNode ->GetIGameObject();
	assert(gMesh);

	if (!gMesh ->InitializeData())
	{
		Log::LogT("error: couldnt initialize data, skipping node");
		return NULL;
	}

	if (!gMesh->IsObjectSkinned())
	{
		Log::LogT("Mesh '%s' is not skinned", meshNodeName.c_str());
		meshNode->ReleaseIGameObject();
		return NULL;
	}
	else 
		Log::LogT("Mesh '%s' is skinned", meshNodeName.c_str());

	Scene3DMesh *mesh = new Scene3DMesh();

	mesh->id = meshNode->GetNodeID();
	mesh->name = StringUtils::ToNarrow(meshNode->GetName());

	CollectProperties(mesh, gMesh);

	IGameMaterial *mat = meshNode ->GetNodeMaterial();

	if (mat != NULL)
		mesh->materialName = StringUtils::ToNarrow(mat->GetMaterialName());

	IGameSkin* skin = gMesh->GetIGameSkin();
	for (int i = 0; i < skin->GetTotalSkinBoneCount(); i++)
		mesh->bonesIds.push_back(skin->GetIGameBone(i)->GetNodeID());

	for (int i = 0; i < gMesh ->GetNumberOfFaces(); i++)
		ExtractVertices(skin, gMesh ->GetFace(i), gMesh, mesh->vertices);

	Log::LogT("Min bones = %d, max bones = %d", dbgMinBonesCount, dbgMaxBonesCount);

	meshNode ->ReleaseIGameObject();

	return mesh;
}
Example #2
0
//----------------------------------------------------------------------------------
bool Helper_ProcessFace(IGameMesh * gM,
                        unsigned int Index,
                        const AffineParts & PRS,
                        const Matrix3 & world_to_obj,
                        MatFaceMapType & matface_map,
                        TriMapType     & tri_map,
                        unsigned int & MaxFaceIdx)
{
    FaceEx *pFace		= gM->GetFace(Index);
    IGameMaterial *pIGMat = gM->GetMaterialFromFace(Index);
    bool HasTexVerts	= gM->GetNumberOfTexVerts() ? true : false;
    bool HasCVerts		= gM->GetNumberOfColorVerts() ? true : false;
    unsigned int smg_id = pFace->smGrp; // smooth group
    unsigned int mat_id = ExporterMAX::GetExporter()->FindMaterialIdx(pIGMat);
    IGameSkin *skin = NULL;

    const int numMod = gM->GetNumModifiers();

    if (numMod > 0)
    {
        for (int i = 0; i < numMod; i++)     // check for skin modifier
        {
            IGameModifier *pM = gM->GetIGameModifier(i);
            if (pM->IsSkin()) {
                skin = (IGameSkin*)pM; // skin modifier
            }
        }
    }

    mesh_opt * m_opt = NULL;

    // lets sort by material and find the corresponding mesh_opt
    MatFaceMapIt it_matfacemap = matface_map.find(mat_id);

    if (it_matfacemap == matface_map.end()) // no corresponding mesh, allocate new face holder
    {
        m_opt = new mesh_opt();
        matface_map.insert(MatFaceMapPair(mat_id, m_opt));
    }
    else
    {
        m_opt = (*it_matfacemap).second;
    }

    for (int j = 0; j < 3; ++j) // build the face
    {
        vert_opt face;
        unsigned int idx;
        unsigned int ori_face_idx = pFace->vert[j]; // get index into the vertex array
        unsigned int face_idx = ori_face_idx;

        bool create_face = false;

        // build the face as expected
        face.smg_id = smg_id; // smooth group

        if (HasTexVerts)
        {
            idx = pFace->texCoord[j]; // get index into the standard mapping channel

            if (idx != BAD_IDX)
            {
                face.t.x = gM->GetTexVertex(idx).x;
                face.t.y = gM->GetTexVertex(idx).y;
            }
        }

        if (HasCVerts)
        {
            idx = pFace->color[j];
            face.c.x = gM->GetColorVertex(idx).x;  // get vertex color
            face.c.y = gM->GetColorVertex(idx).y;
            face.c.z = gM->GetColorVertex(idx).z;
            face.c.w = 1.f;

        } else {
            face.c = Vector4f(1.f, 1.f, 1.f, 1.f);
        }

        Tab<int> mapNums = gM->GetActiveMapChannelNum();
        face.num_tmaps = mapNums.Count();

        if (face.num_tmaps)
        {
            face.tmaps = new Vector[face.num_tmaps];
            for (size_t k = 0; k < face.num_tmaps; ++k)
            {
                unsigned long mapfaceidx[3];
                gM->GetMapFaceIndex(mapNums[k], Index, &mapfaceidx[0]);
                idx = mapfaceidx[j];
                face.tmaps[k].x = gM->GetMapVertex(mapNums[k], idx).x;
                face.tmaps[k].y = gM->GetMapVertex(mapNums[k], idx).y;
                face.tmaps[k].z = gM->GetMapVertex(mapNums[k], idx).z;
            }
        }

        // try to find in origin array
        FaceMapIt it_face_map = m_opt->face_map.find(face_idx);  // get face map iter

        if (it_face_map == m_opt->face_map.end()) // if not find such create anyway
        {
            create_face = true;
        }
        else
        {
            if (is_matching((*it_face_map).second, face) == false) // check find vertex not matching
            {
                bool found = false;

                // process vertex multi map
                std::pair<FaceMMapIt,FaceMMapIt> pair_mmap = m_opt->face_mmap.equal_range(ori_face_idx);

                FaceMMapIt it_face_mmap = pair_mmap.first;

                while (it_face_mmap != pair_mmap.second && found == false)
                {
                    idxvert_opt & idxface = (*it_face_mmap).second;

                    if (is_matching(idxface.face, face))
                    {
                        face_idx = idxface.new_idx;
                        found = true;
                    }
                    ++it_face_mmap;
                }

                if (found == false)
                {
                    create_face = true;
                    ++MaxFaceIdx;			// increment max index and
                    face_idx = MaxFaceIdx;	// set index is out of bounds of origin 3DMax's index range
                }
            }
        }

        if (create_face)
        {
            if (skin)
            {
                std::vector<w_offset>   w_offsets;
                for (int k = 0; k < skin->GetNumberOfBones(ori_face_idx); ++k)
                {
                    /*	if (skin->GetWeight(ori_face_idx, k) > m_eps)
                    	{
                    		w_offset w;
                    		w.weight = skin->GetWeight(ori_face_idx, k);

                    		_BoneObject * Bone = ExporterMAX::GetExporter()->Skeleton.AddMaxBone(skin->GetIGameBone(ori_face_idx, k), skin->GetIGameBone(ori_face_idx, k)->GetNodeID());
                    		assert(Bone != NULL);

                    		w.bone_id = Bone->GetID();
                    		w_offsets.push_back(w);
                    	}*/
                }

//				std::sort(w_offsets.begin(), w_offsets.end(), heavier);

                int ILeft = 0;
                for (size_t l = 0; l < w_offsets.size() && l < 4; ++l, ++ILeft)
                {
                    w_offset & w = w_offsets[l];
                    face.weights[l] = w.weight;
                    face.bones[l] = w.bone_id;
                }

                for (; ILeft < 4; ++ILeft)
                {
                    face.weights[ILeft] = 0.f;
                    face.bones[ILeft] = BAD_IDX;
                }

                // check for valid weights...
                float w_sum = 0.f;

                for (int l = 0; l < 4; ++l) {
                    w_sum += face.weights[l];
                }

                if ((w_sum < m_one - m_eps) || (w_sum > m_one + m_eps))
                {
                    for (int l = 0; l < 4; ++l) // renormalizing...
                        face.weights[l] /= w_sum;
                }
            }

            Point3 v_world = gM->GetVertex(ori_face_idx);
            Point3 v_obj = v_world; // * world_to_obj;

            face.v.x = v_obj.x; // * PRS.k.x * PRS.f;
            face.v.y = v_obj.z; // * PRS.k.z * PRS.f;
            face.v.z = v_obj.y; // * PRS.k.y * PRS.f;

            // add the vertex and store its new idx
            face.face_idx = m_opt->count;

            m_opt->face_map.insert(FaceMapPair(face_idx, face));

            if (ori_face_idx != face_idx)  // store the newly created and duplicated independently
            {
                idxvert_opt idxface(face_idx, face);// store new face
                m_opt->face_mmap.insert(FaceMMapPair(ori_face_idx, idxface)); // but store key as a original
            }
            m_opt->count++;
        }

        // add the face indices...
        TriMapIt it = tri_map.find(mat_id);
        if (it != tri_map.end())
        {
            (*it).second->push_back(face_idx);
        }
        else
        {
            IdxType * idx_type = new IdxType;
            idx_type->push_back(face_idx);
            tri_map.insert(TriMapPair(mat_id, idx_type));
        }
    }
    return true;
}
int	MaxExporter::DoExport(const TCHAR *name,ExpInterface *ei,Interface *i, BOOL suppressPrompts, DWORD options)
{

	/*if(!suppressPrompts)
		DialogBoxParam(hInstance, 
				MAKEINTRESOURCE(IDD_PANEL), 
				GetActiveWindow(), 
				MaxExporterOptionsDlgProc, (LPARAM)this);*/

	#pragma message(TODO("return TRUE If the file is exported properly"))

	Node::s_nextID = 1;
	ofstream myFile;
	myFile.open("DebugExporter.txt");
	wstring wFileName( name );
	string fileName( wFileName.begin(), wFileName.end() );
	//f= fopen( fileName.c_str(),"wb");
	BinaryFile = loadSave( fileName.c_str() );
	//BinaryFile.saveInt( 5 );
	//BinaryFile.close();
	myFile << "Start Export\n";

	IGameScene* gameScene = GetIGameInterface();
	gameScene->InitialiseIGame();
	int nodeCount = gameScene->GetTopLevelNodeCount();
	myFile << "Number of top level nodes: " << nodeCount << "\n";
	//get all of the materials
	for( int nodeNumber = 0; nodeNumber < nodeCount; ++nodeNumber)
	{
		IGameNode* gameNode = gameScene->GetTopLevelNode( nodeNumber );
		
		Node* myNode = new Node( gameNode );
		m_NodeList.push_back( myNode );
		findFaces( myNode, myFile );
		
	}

	myFile << "Number of materials\n";
	myFile << m_materialSet.size() << "\n";
	

	int totalBatches = 0;
	//myFile<< "Number of triangleBatchMaps: " << m_triangleBatchesPerNode.size() << "\n";
	for( auto nodeIter = m_NodeList.begin(); nodeIter != m_NodeList.end(); ++nodeIter )
	{
		std::map< IGameMaterial*, TriangleBatch* > triangleBatches = (*nodeIter)->m_triangleBatchesPerMaterial;
		myFile << "Invidiual triangleBatch size: " << triangleBatches.size() << "\n";

		for( auto materialIter = m_materialSet.begin(); materialIter != m_materialSet.end(); ++materialIter )
		{
			auto found = triangleBatches.find( * materialIter );
			if( found != triangleBatches.end() )
			{
				++totalBatches;
			}
		}
	}

	BinaryFile.saveInt( m_NodeList.size() );
	myFile << "Number of Nodes: " << m_NodeList.size() << "\n";
	
	for( auto nodeIter = m_NodeList.begin(); nodeIter != m_NodeList.end(); ++nodeIter )
	{
		std::map< IGameMaterial*, TriangleBatch* > triangleBatches = (*nodeIter)->m_triangleBatchesPerMaterial;
		std::map<IGameMaterial*, std::vector< NodeFace > > facesPerMaterial = (*nodeIter)->m_facesPerMaterial;
		IGameNode* currentNode = (*nodeIter)->m_gameNode;
		IGameNode* parentNode;
		GMatrix parentWTM;
		GMatrix toParentMatrix;
		GMatrix worldTM;
		GMatrix localTM;
		int time = gameScene->GetSceneStartTime();
		for( ; time < gameScene->GetSceneEndTime(); time += 4800/30 )
		{
			if( (*nodeIter)->m_parentID != 0 )
			{
				myFile << "Trying to find parent... \n";
				parentNode = (*nodeIter)->m_parent->m_gameNode;
				if( parentNode != nullptr )
				{
					myFile << "Parent found \n";
					parentWTM = parentNode->GetWorldTM( time );
					toParentMatrix = parentWTM.Inverse();

					worldTM = currentNode->GetWorldTM(  time ) * toParentMatrix;

				}

			}
			else
			{
				worldTM = currentNode->GetWorldTM( time );
				
			}
			(*nodeIter)->m_toParentMatrix.push_back( Matrix4x4( worldTM[0], worldTM[1], worldTM[2], worldTM[3] ) );
		}


		localTM = currentNode->GetWorldTM().Inverse();
		(*nodeIter)->m_worldToLocal = Matrix4x4(  localTM[0], localTM[1], localTM[2], localTM[3] );
		

		//Save the node
		BinaryFile.saveNode( *nodeIter, myFile );
		BinaryFile.saveInt( (*nodeIter)->m_triangleBatchesPerMaterial.size() );
	
		for( auto materialIter = m_materialSet.begin(); materialIter != m_materialSet.end(); ++materialIter )
		{
			//Set the current material's VBO and IBO
			//
			IGameMaterial* currentMaterial = *materialIter;
			TriangleBatch* currentBatch = triangleBatches[ currentMaterial ];
			
			GMatrix localTMNoTrans = localTM;
			localTMNoTrans.SetRow( 3, Point4( 0,0,0,1) );
			if( currentBatch != nullptr )
			{
				
				MaxMaterial* currentMaxMaterial = currentBatch->m_material;
				VBO* currentVBO = currentBatch->m_vbo;
				IBO* currentIBO = currentBatch->m_ibo;
				vector< NodeFace >& faceVector = facesPerMaterial.find( currentMaterial )->second;

				//Get texture materials and export them
				//
				if( currentMaterial != nullptr )
				{
					int numOfTexMaps = currentMaterial->GetNumberOfTextureMaps();
					myFile << "Number of texture maps: " << numOfTexMaps << "\n";
					for( int i = 0; i < numOfTexMaps; ++i )
					{
						IGameTextureMap* gameTextureMap = currentMaterial->GetIGameTextureMap( i );
						
						if( gameTextureMap != nullptr && gameTextureMap->IsEntitySupported() )
						{
							int stdMapSlot = gameTextureMap->GetStdMapSlot();
							if( stdMapSlot == ID_DI )
							{
								wstring wBitmapFileName;
								wBitmapFileName = gameTextureMap->GetBitmapFileName();
								if( wBitmapFileName.size() > 0 )
								{
									BitmapInfo bi( gameTextureMap->GetBitmapFileName() );
									BMMGetFullFilename( &bi );
									wBitmapFileName = bi.Name();
									std::string fullBitmapFileName( wBitmapFileName.begin(), wBitmapFileName.end() );
									if( fullBitmapFileName.size() > 0 )
									{
										int lastSlash = fullBitmapFileName.find_last_of('\\') + 1;
										if( lastSlash != string::npos )
										{
											const std::string bitmapFileName = fullBitmapFileName.substr( lastSlash );
											wstring nameAsWString( name );
											std::string nameAsString( nameAsWString.begin(), nameAsWString.end() );
											const std::string extension = nameAsString.substr( 0, nameAsString.find_last_of('\\') + 1 );
											std::string newFileName = extension;
											newFileName.append( bitmapFileName );
											wstring wNewFileName(newFileName.begin(), newFileName.end());
											if( CopyFile( wBitmapFileName.c_str(), wNewFileName.c_str(), false ) )
											{
												if( stdMapSlot == ID_DI )
												{
													currentMaxMaterial->m_diffuseTexture = bitmapFileName;
													currentMaxMaterial->bHasDiffuseTexture = true;
												}
											//BinaryFile.saveString( bitmapFileName );
											}
											else
											{
												myFile << GetLastError() << "\n";
												myFile << "copying the file FAILED.\n";
											}
										}
									}	
								}
							}
						}
					}
				}
				
				myFile<< "Number of faces for this material: " << faceVector.size() << "\n";
				for( int face = 0; face < faceVector.size(); ++face )
				{
					FaceEx* meshFace = faceVector[face].m_face;
					IGameMesh* gameMesh = faceVector[face].m_mesh;
					IGameSkin* gameSkin = gameMesh->GetIGameSkin();
					int position, normal, color, texCoordinate, maxPosition;
					for( int i = 0; i < 3; ++i)
					{
						
						maxPosition = (int)meshFace->vert[i];
						
						Point3 tempPos = gameMesh->GetVertex( maxPosition );
						tempPos = tempPos * localTM;
						Vector3D positionVec3( tempPos.x, tempPos.y, tempPos.z );
						position = currentVBO->insertPosition(positionVec3);

						normal = (int)meshFace->norm[i];
						Point3 tempNormal = gameMesh->GetNormal( normal );
						tempNormal = tempNormal * localTMNoTrans;
						tempNormal = tempNormal.Normalize();
						
						Vector3D normalVec3( tempNormal.x, tempNormal.y, tempNormal.z );
						normal = currentVBO->insertNormal(normalVec3);

						//IBO
						texCoordinate = (int)meshFace->texCoord[i];
						Point2 tempTexCoord = gameMesh->GetTexVertex( texCoordinate );
						Vector2 texCoordVec2( tempTexCoord.x, tempTexCoord.y );
						texCoordinate = currentVBO->insertTexCoord(texCoordVec2);
						VertexIndex VI( position, normal, texCoordinate );
						if( gameSkin != nullptr )
						{
							int numberOfBones = gameSkin->GetNumberOfBones( maxPosition );
							for( int boneIndex = 0; boneIndex < numberOfBones; ++boneIndex )
							{
								float boneWeight = gameSkin->GetWeight( maxPosition, boneIndex );
								IGameNode* bone = gameSkin->GetIGameBone( maxPosition, boneIndex );
								myFile << "Bone node ID: " << bone->GetNodeID() << "\n";
								int nodeIDForBone = m_boneIDToNodeID[ bone->GetNodeID() ];
								myFile << "Node ID: " << nodeIDForBone << "\n";
								VI.addBoneWeight( nodeIDForBone, boneWeight );

								/*for( auto boneIter = m_NodeList.begin(); boneIter != m_NodeList.end(); ++boneIter )
								{
									if( (*boneIter)->m_gameNode == bone )
									{
										myFile << "Found the bone!\n"; 
										
									}
								}*/
								
							}
							VI.topBoneWeights();
						}

						int vertIndex = currentVBO->insertVertex( VI );
						currentIBO->addIndex( vertIndex );

					}

				}
				
				BinaryFile.saveTriangleMesh( currentBatch, myFile );
			}
		}

	}
	myFile.close();

	for( int nodeNumber = 0; nodeNumber < nodeCount; ++nodeNumber)
	{
		IGameNode* gameNode = gameScene->GetTopLevelNode( nodeNumber );
		if( gameNode != nullptr )
		{
			tearDown( gameNode );
		}
		
	}

	BinaryFile.close();
	return TRUE;

	//return FALSE;
}