GameOptionsMenu::GameOptionsMenu(SMenuConfig* menuConfig) :
		title("Options de la partie", TITLEFONT, 30),
		category(TITLEFONT, 100),		
		cancel("Annuler", 550, CREATEGAMEMENU),
		save("Valider", 550, CREATEGAMEMENU),
		menuConfig(menuConfig)
	{
		ISkin* skin = PolyBomberApp::getISkin();
		
		title.setColor(skin->getColor(TITLECOLOR));

		category.push_back("Bonus de bombe");
		category.push_back("Bonus de personnage");
		category.push_back("Infections");

		cancel.move(-100, 0);
		save.move(100, 0);

		cancel.setSelected(true);
		
		cancel.setNext(&save);			
		save.setNext(&cancel);

		this->widgets.push_back(&title);
		this->widgets.push_back(&category);
		this->widgets.push_back(&cancel);
		this->widgets.push_back(&save);

		initBonus();
	}
	void GraphicsConfigMenu::validPressed(EMenuScreen* nextScreen)
	{
		ISkin* skin = PolyBomberApp::getISkin();

		if (cancel.getSelected())
		{
			skin->reloadConfig();
			*nextScreen = cancel.activate();
		}
		
		if (save.getSelected())
		{
			if (window->canFullScreen())
			{
				window->setFullScreen(fullscreen.getCurrentItem());

				IConfigFile* configFile = new ConfigFileManager();

				configFile->setIntValue("window.fullscreen.enabled", fullscreen.getCurrentItem());

				delete configFile;
			}

			skin->saveConfig();							
			*nextScreen = save.activate();
		}
	}
	void GameOptionsMenu::initBonus()
	{				
		ISkin* skin = PolyBomberApp::getISkin();

		EImage icones[18] = {EIMAGE_BOMBPLUS, EIMAGE_BOMBMOINS, EIMAGE_RANGEPLUS, EIMAGE_RANGEMOINS,
							EIMAGE_RANGEMAX, EIMAGE_MINEBONUS, EIMAGE_INFINITY, EIMAGE_ATOMIC,
							EIMAGE_VITESSEPLUS, EIMAGE_VITESSEMOINS, EIMAGE_BOMBLINE, EIMAGE_REMOTEBONUS,
							EIMAGE_CRANE, EIMAGE_HELL, EIMAGE_CONFUSION,	EIMAGE_SPASME,	EIMAGE_DILATATION,
							EIMAGE_RAGE};
		int i;
		
		for (i=0; i<18; i++)
		{
			int j = i;
			if (i >= 12) j -= 12;
			else if (i >= 8) j -= 8;

			this->images[i] = new ImageWidget();
			this->images[i]->setImage(skin->loadImage(icones[i]));
			this->images[i]->setPosition(300,200+40*j);			
			
			this->bonus[i] = new SelectionWidget(TEXTFONT, 200 + 40*j);
			this->bonus[i]->push_back("0");
			this->bonus[i]->push_back("1");
			this->bonus[i]->push_back("2");
			this->bonus[i]->push_back("3");
			this->bonus[i]->push_back("4");
			this->bonus[i]->push_back("5");
			this->bonus[i]->push_back("6");
			this->bonus[i]->push_back("7");
			this->bonus[i]->push_back("8");
			this->bonus[i]->push_back("9");
			this->bonus[i]->push_back("10");
			this->bonus[i]->setCurrentItem(this->menuConfig->gameConfig.nbBonus[i]);
			this->bonus[i]->move(70, 0);

			if (j > 0)
				this->bonus[i]->setPrevious(this->bonus[i-1]);
			else
				this->bonus[i]->setPrevious(&category);
			
			this->widgets.push_back(this->images[i]);
			this->widgets.push_back(this->bonus[i]);
		}

		for (i=0; i<7; i++)
			this->bonus[i]->setNext(this->bonus[i+1]);

		for (i=8; i<11; i++)
			this->bonus[i]->setNext(this->bonus[i+1]);

		for (i=12; i<17; i++)
			this->bonus[i]->setNext(this->bonus[i+1]);

		this->bonus[7]->setNext(&cancel);						
		this->bonus[11]->setNext(&cancel);						
		this->bonus[17]->setNext(&cancel);

		setCategory();				
	}
//// FindSkinModifier ///////////////////////////////////////////////////////
//  Given an INode, gets the ISkin object of that node, or nil if there is
//  none. Taken from the Max4 SDK, ISkin.h
ISkin* plMaxNodeBase::FindSkinModifier()
{
    int modStackIndex;

    // Get object from node. Abort if no object.
    Object *pObj = GetObjectRef();
    if( pObj == nil )
        return nil;

    // Is derived object ?
    while( pObj->SuperClassID() == GEN_DERIVOB_CLASS_ID )
    {
        IDerivedObject *pDerObj = (IDerivedObject *)pObj;

        // Iterate over all entries of the modifier stack.
        for( modStackIndex = 0; modStackIndex < pDerObj->NumModifiers(); modStackIndex++ )
        {
            // Get current modifier.
            Modifier *mod = pDerObj->GetModifier( modStackIndex );

            // Is this Skin ?
            if( mod->ClassID() == SKIN_CLASSID )
            {
                ISkin* skin = (ISkin*)mod->GetInterface(I_SKIN);
                if( skin->GetNumBones() > 0 )
                    return skin;
            }
        }
        pObj = pDerObj->GetObjRef();
    }

    // Not found.
    return nil;
}
	EMenuScreen GraphicsConfigMenu::run(MainWindow& window, EMenuScreen previous)
	{
		this->window = &window;

		// Configuration plein ecran
		fullscreen.setCurrentItem(window.getFullScreen());

		if (window.canFullScreen())
		{
			skinList.setPrevious(&fullscreen);
			this->widgets.push_back(&fullscreen);
		}
		else
			this->widgets.push_back(&noFullscreen);

		// Mise à jour du skin
		ISkin* skin = PolyBomberApp::getISkin();
		std::vector<std::string> skins = skin->getSkinsList();
		
		for (unsigned int i=0; i<skins.size(); i++)
		{
			if (skin->getSkin().compare(skins[i]) == 0)
				skinList.setCurrentItem(i);
		}

		return IMenuScreen::run(window, previous);
	}
示例#6
0
	ScoreMenu::ScoreMenu(SMenuConfig* menuConfig) :
		title("Score de la partie", TITLEFONT, 100),
		winner("Le joueur i a gagne !", TEXTFONT, 170),
		back("Retour au menu", 550, MAINMENU),
		menuConfig(menuConfig)
	{
		ISkin* skin = PolyBomberApp::getISkin();

		title.setColor(skin->getColor(TITLECOLOR));
		winner.setColor(skin->getColor(TEXTCOLOR));

		back.setSelected(true);

		this->widgets.push_back(&title);
		this->widgets.push_back(&winner);
		this->widgets.push_back(&back);

		for (int i=0; i<4; i++)
		{
			this->pictures[i] = new ImageWidget();
			this->pictures[i]->setPosition(300, 250 + 60*i);				
			this->pictures[i]->setImage(skin->loadImage((EImage)(PLAYER1 + i)));				

			this->names[i] = new TextWidget("", TEXTFONT, 250 + 60*i);
			this->names[i]->setColor(skin->getColor(TEXTCOLOR));

			this->widgets.push_back(this->pictures[i]);
			this->widgets.push_back(this->names[i]);
		}
	}
	void GraphicsConfigMenu::rightPressed()
	{
		ISkin* skin = PolyBomberApp::getISkin();
		std::vector<std::string> skins = skin->getSkinsList();

		cancel.goNext();
		fullscreen.goNextItem();
		skinList.goNextItem();
		skin->setSkin(skins[skinList.getCurrentItem()]);
	}
	//---------------------------------------------------------------
	bool SkinController::isSkinController( Modifier * modifier )
	{
		Class_ID classId = modifier->ClassID();
		if (classId == SKIN_CLASSID)
		{
			ISkin* skin = (ISkin*) modifier->GetInterface(I_SKIN);
			if ( !skin) 
				return false;
			return skin->GetNumBonesFlat() > 0;
		}
		else 
			return (classId == PHYSIQUE_CLASSID) != false;

		return false;
	}
	ControllersConfigMenu::ControllersConfigMenu() :
		title("Configuration des controleurs", TITLEFONT, 100),
		error("Aucun controleur detecte", TEXTFONT, 200),
		cancel("Retour", 500, CONFIGMENU)
	{
		ISkin* skin = PolyBomberApp::getISkin();	
		title.setColor(skin->getColor(TITLECOLOR));
		error.setColor(skin->getColor(ERRORCOLOR));

		this->widgets.push_back(&title);
		this->widgets.push_back(&error);
		this->widgets.push_back(&cancel);

		error.setVisible(false);

		for (int i=0; i<4; i++)
		{
			std::ostringstream text;
			text << "Joueur " << i+1 << " : ";
			playerText[i] = new TextWidget(text.str(), TEXTFONT, 250 + 50*i);
			playerText[i]->setColor(skin->getColor(TEXTCOLOR));
			playerText[i]->move(-100, 0);

			playerController[i] = new SelectionWidget(LINKFONT, 250 + 50*i);

			playerController[i]->push_back("Gamepad");
			playerController[i]->push_back("Clavier");
			playerController[i]->push_back("Wii");

			playerController[i]->move(100, 0);

			if (i > 0)
				playerController[i]->setPrevious(playerController[i-1]);			

			this->widgets.push_back(playerText[i]);
			this->widgets.push_back(playerController[i]);
		}

		playerController[0]->setNext(playerController[1]);
		playerController[1]->setNext(playerController[2]);
		playerController[2]->setNext(playerController[3]);
		playerController[3]->setNext(&cancel);

		cancel.setPrevious(playerController[3]);
		cancel.setSelected(true);
	}
示例#10
0
	WaitingMenu::WaitingMenu(SMenuConfig* menuConfig) :
		title("Resume de la partie", TITLEFONT, 50),
		ip("Adresse IP du serveur : ", TEXTFONT, 150),
		cancel("Annuler", 500, GAMEMENU),
		start("Jouer !", 500, RUNGAME),
		menuConfig(menuConfig)
	{
		ISkin* skin = PolyBomberApp::getISkin();
		
		title.setColor(skin->getColor(TITLECOLOR));
		ip.setColor(skin->getColor(TEXTCOLOR));

		this->network = PolyBomberApp::getINetworkToMenu();
		ip.setString(ip.getString() + this->network->getIpAddress());
		
		ip.move(-80, 0);
		
		cancel.move(-100, 0);
		start.move(100, 0);

		cancel.setSelected(true);
		cancel.setNext(&start);
		start.setNext(&cancel);

		this->widgets.push_back(&title);
		this->widgets.push_back(&ip);
		this->widgets.push_back(&cancel);
		this->widgets.push_back(&start);

		for (int i=0; i<4; i++)
		{
			this->pictures[i] = new ImageWidget();
			this->pictures[i]->setPosition(300, 200 + 60*i);				
			this->pictures[i]->setImage(skin->loadImage((EImage)(PLAYER1 + i)));				

			this->names[i] = new TextWidget("...", TEXTFONT, 210 + 60*i);
			this->names[i]->setColor(skin->getColor(TEXTCOLOR));
			this->names[i]->move(100, 0);

			this->widgets.push_back(this->pictures[i]);
			this->widgets.push_back(this->names[i]);
		}
	}
示例#11
0
	InputWidget::InputWidget(ETextFont font, unsigned int y, ETextPosition position, unsigned int width) :
		ClickableWidget(),
		text("", font, 0, LEFT),
		maxLength(10),
		WIDTH(800)
	{
		ISkin* skin = PolyBomberApp::getISkin();
		
		area.setSize(sf::Vector2f(width, 35));
		area.setFillColor(skin->getColor(BGCOLOR));
		area.setOutlineColor(skin->getColor(TEXTCOLOR));
		area.setOutlineThickness(3);

		text.setPosition(5, 5);
		text.setColor(skin->getColor(TEXTCOLOR));

		if (position == RIGHT)
			setPosition(this->WIDTH - width, y);
		else if (position == CENTER)
			setPosition(this->WIDTH/2 - (width)/2, y);
	}
	SelectSlotsMenu::SelectSlotsMenu(SMenuConfig* menuConfig) :
		title("Creation d'une partie", TITLEFONT, 100),
		error("Pas assez de place sur le serveur", TEXTFONT, 300),
		nbPlayersText("Nombre de joueurs sur cet ordinateur :", TEXTFONT, 250),
		nbPlayers(TEXTFONT, 300),
		cancel("Annuler", 450, GAMEMENU),
		next("Valider", 450, SELECTNAMEMENU),
		menuConfig(menuConfig)
	{
		ISkin* skin = PolyBomberApp::getISkin();
		
		title.setColor(skin->getColor(TITLECOLOR));
		error.setColor(skin->getColor(ERRORCOLOR));
		nbPlayersText.setColor(skin->getColor(TEXTCOLOR));

		cancel.move(-100, 0);
		next.move(100, 0);

		nbPlayers.push_back("1");
		nbPlayers.setCurrentItem(0);

		error.setVisible(false);

		cancel.setSelected(true);

		nbPlayers.setNext(&cancel);
		cancel.setPrevious(&nbPlayers);
		next.setPrevious(&nbPlayers);
		cancel.setNext(&next);
		next.setNext(&cancel);

		this->widgets.push_back(&title);
		this->widgets.push_back(&error);
		this->widgets.push_back(&nbPlayersText);
		this->widgets.push_back(&nbPlayers);
		this->widgets.push_back(&cancel);
		this->widgets.push_back(&next);

		this->network = PolyBomberApp::getINetworkToMenu();
	}
	GraphicsConfigMenu::GraphicsConfigMenu() :
		title("Configuration graphique", TITLEFONT, 100),
		textFullscreen("Mode plein-ecran : ", TEXTFONT, 200),
		fullscreen(TEXTFONT, 200),
		noFullscreen("Indisponible", ERRORFONT, 200),
		skinText("Skin choisi :", TEXTFONT, 300),
		skinList(TEXTFONT, 350),
		cancel("Annuler", 450, CONFIGMENU),
		save("Valider", 450, CONFIGMENU)
	{
		ISkin* skin = PolyBomberApp::getISkin();
		
		title.setColor(skin->getColor(TITLECOLOR));
		skinText.setColor(skin->getColor(TEXTCOLOR));		
		textFullscreen.setColor(skin->getColor(TEXTCOLOR));

		// Mode plein ecran
		textFullscreen.move(-100, 0);

		fullscreen.push_back("non");
		fullscreen.push_back("oui");
		fullscreen.move(100, 0);

		noFullscreen.setColor(skin->getColor(ERRORCOLOR));
		noFullscreen.move(100, 0);

		// Liste des skins
		std::vector<std::string> skins = skin->getSkinsList();		
		for (unsigned int i=0; i<skins.size(); i++)
			skinList.push_back(skins[i]);

		cancel.move(-100, 0);
		save.move(100, 0);

		cancel.setSelected(true);
		
		fullscreen.setNext(&skinList);
		skinList.setNext(&cancel);
		
		cancel.setPrevious(&skinList);
		cancel.setNext(&save);
			
		save.setPrevious(&skinList);
		save.setNext(&cancel);

		this->widgets.push_back(&title);
		this->widgets.push_back(&textFullscreen);
		this->widgets.push_back(&skinText);
		this->widgets.push_back(&skinList);
		this->widgets.push_back(&cancel);
		this->widgets.push_back(&save);

		this->window = NULL;
	}
示例#14
0
	void InputWidget::setSelected(bool selected)
	{
		ISkin* skin = PolyBomberApp::getISkin();
		ClickableWidget::setSelected(selected);

		if (selected)
		{
			area.setFillColor(skin->getColor(SELECTEDBGCOLOR));
			area.setOutlineColor(skin->getColor(SELECTEDCOLOR));
			text.setColor(skin->getColor(SELECTEDCOLOR));
		}
		else
		{
			area.setFillColor(skin->getColor(BGCOLOR));
			area.setOutlineColor(skin->getColor(TEXTCOLOR));
			text.setColor(skin->getColor(TEXTCOLOR));
		}
	}
示例#15
0
文件: MaxMesh.cpp 项目: imvu/cal3d
CVertexCandidate *CMaxMesh::GetVertexCandidate(CSkeletonCandidate *pSkeletonCandidate, int faceId, int faceVertexId)
{
    // check for valid mesh and physique modifier
    if((m_pIMesh == 0))
    {
        theExporter.SetLastError("Invalid handle.", __FILE__, __LINE__);
        return 0;
    }

    // check if face id is valid
    if((faceId < 0) || (faceId >= m_pIMesh->getNumFaces()))
    {
        theExporter.SetLastError("Invalid face id found.", __FILE__, __LINE__);
        return 0;
    }

    // check if face vertex id is valid
    if((faceVertexId < 0) || (faceVertexId >= 3))
    {
        theExporter.SetLastError("Invalid face vertex id found.", __FILE__, __LINE__);
        return 0;
    }

    // allocate a new vertex candidate
    CVertexCandidate *pVertexCandidate;
    pVertexCandidate = new CVertexCandidate();
    if(pVertexCandidate == 0)
    {
        theExporter.SetLastError("Memory allocation failed.", __FILE__, __LINE__);
        return 0;
    }

    // create the new vertex candidate
    if(!pVertexCandidate->Create())
    {
        delete pVertexCandidate;
        return 0;
    }

    // get vertex id
    int vertexId;
    vertexId = m_pIMesh->faces[faceId].v[faceVertexId];

    // get the absolute vertex position
    Point3 vertex;
    vertex = m_pIMesh->getVert(vertexId) * m_tm;

    // set the vertex candidate position
    pVertexCandidate->SetPosition(vertex.x, vertex.y, vertex.z);
    pVertexCandidate->SetUniqueId(vertexId);

    // get the absolute vertex normal
    Point3 normal;
    normal = GetVertexNormal(faceId, vertexId);
    normal = normal * Inverse(Transpose(m_tm));
    normal = normal.Normalize();

    // set the vertex candidate normal
    pVertexCandidate->SetNormal(normal.x, normal.y, normal.z);
 
  if(m_pIMesh->numCVerts > 0)
  { 
        VertColor vc;
        vc = m_pIMesh->vertCol[m_pIMesh->vcFace[faceId].t[faceVertexId]];
    CalVector vcCal(vc.x, vc.y, vc.z);
    pVertexCandidate->SetVertColor(vcCal);
  }  
 
    // get the vertex weight array
    float *pVertexWeights;
    pVertexWeights = m_pIMesh->getVertexWeights();
  //if( pVertexWeights == NULL ) {
    //    delete pVertexCandidate;
    //    theExporter.SetLastError("Mesh has no vertex weights", __FILE__, __LINE__);
    //    return 0;
  //}

    // get the vertex weight (if possible)
    float weight;
    if(pVertexWeights != 0)
    {
        weight = pVertexWeights[vertexId];
    }
    else
    {
        weight = 0.0f;
    }

    // another 3ds max weird behaviour:
    // zero out epsilon weights
    if(weight < 0.0005f) weight = 0.0f;

    // set the vertex candidate weight
    pVertexCandidate->SetPhysicalProperty(weight);

    // get the material id of the face
    int materialId;
    materialId = GetFaceMaterialId(faceId);

    if((materialId < 0) || (materialId >= (int)m_vectorStdMat.size()))
    {
        delete pVertexCandidate;
        theExporter.SetLastError("Invalid material id found.", __FILE__, __LINE__);
        return 0;
    }

    // get the material of the face
    StdMat *pStdMat;
    pStdMat = m_vectorStdMat[materialId];

    // loop through all the mapping channels and extract texture coordinates
    int mapId;
    for(mapId = 0; mapId < pStdMat->NumSubTexmaps(); mapId++)
    {
        // get texture map
        Texmap *pTexMap;
        pTexMap = pStdMat->GetSubTexmap(mapId);

        // check if map is valid
        if((pTexMap != 0) && (pStdMat->MapEnabled(mapId)))
        {
            // get the mapping channel
            int channel;
            channel = pTexMap->GetMapChannel();

            bool bValidUV;
            bValidUV = false;

            // extract the texture coordinate
            UVVert uvVert;
            if(m_pIMesh->mapSupport(channel))
            {
                TVFace *pTVFace;
                pTVFace = m_pIMesh->mapFaces(channel);

                UVVert *pUVVert;
                pUVVert = m_pIMesh->mapVerts(channel);

                uvVert = pUVVert[pTVFace[faceId].t[faceVertexId]];
                bValidUV = true;
            }
            else if(m_pIMesh->numTVerts > 0)
            {
                uvVert = m_pIMesh->tVerts[m_pIMesh->tvFace[faceId].t[faceVertexId]];
                bValidUV = true;
            }

            // if we found valid texture coordinates, add them to the vertex candidate
            if(bValidUV)
            {
                // apply a possible uv generator
                StdUVGen *pStdUVGen;
                pStdUVGen = (StdUVGen *)pTexMap->GetTheUVGen();
                if(pStdUVGen != 0)
                {
                    Matrix3 tmUV;
                    pStdUVGen->GetUVTransform(tmUV);
                    uvVert = uvVert * tmUV;
                }

                // add texture coordinate to the vertex candidate, inverting the y coordinate
                pVertexCandidate->AddTextureCoordinate(uvVert.x, 1.0f - uvVert.y);
            }
        }
    }

    // check for physique modifier
    if(m_modifierType == MODIFIER_PHYSIQUE)
    {
        // create a physique export interface
        IPhysiqueExport *pPhysiqueExport;
        pPhysiqueExport = (IPhysiqueExport *)m_pModifier->GetInterface(I_PHYINTERFACE);
        if(pPhysiqueExport == 0)
        {
            delete pVertexCandidate;
            theExporter.SetLastError("Physique modifier interface not found.", __FILE__, __LINE__);
            return 0;
        }

        // create a context export interface
        IPhyContextExport *pContextExport;
        pContextExport = (IPhyContextExport *)pPhysiqueExport->GetContextInterface(m_pINode);
        if(pContextExport == 0)
        {
            m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
            delete pVertexCandidate;
            theExporter.SetLastError("Context export interface not found.", __FILE__, __LINE__);
            return 0;
        }

        // set the flags in the context export interface
        pContextExport->ConvertToRigid(TRUE);
        pContextExport->AllowBlending(TRUE);

        // get the vertex export interface
        IPhyVertexExport *pVertexExport;
        pVertexExport = (IPhyVertexExport *)pContextExport->GetVertexInterface(vertexId);
        if(pVertexExport == 0)
        {
            pPhysiqueExport->ReleaseContextInterface(pContextExport);
            m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
            delete pVertexCandidate;
            theExporter.SetLastError("Vertex export interface not found.", __FILE__, __LINE__);
            return 0;
        }

        // get the vertex type
        int vertexType;
        vertexType = pVertexExport->GetVertexType();

        // handle the specific vertex type
        if(vertexType == RIGID_TYPE)
        {
            // typecast to rigid vertex
            IPhyRigidVertex *pTypeVertex;
            pTypeVertex = (IPhyRigidVertex *)pVertexExport;

                // add the influence to the vertex candidate
            // get the influencing bone
            if(!AddBoneInfluence(pSkeletonCandidate, pVertexCandidate, pTypeVertex->GetNode(), 1.0f))
            {
                pPhysiqueExport->ReleaseContextInterface(pContextExport);
                m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
                delete pVertexCandidate;
                theExporter.SetLastError("Invalid bone assignment.", __FILE__, __LINE__);
                return 0;
            }
        }
        else if(vertexType == RIGID_BLENDED_TYPE)
        {
            // typecast to blended vertex
            IPhyBlendedRigidVertex *pTypeVertex;
            pTypeVertex = (IPhyBlendedRigidVertex *)pVertexExport;

            // loop through all influencing bones
            int nodeId;
            for(nodeId = 0; nodeId < pTypeVertex->GetNumberNodes(); nodeId++)
            {
                // add the influence to the vertex candidate
                if(!AddBoneInfluence(pSkeletonCandidate, pVertexCandidate, pTypeVertex->GetNode(nodeId), pTypeVertex->GetWeight(nodeId)))
                {
                    pPhysiqueExport->ReleaseContextInterface(pContextExport);
                    m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
                    delete pVertexCandidate;
                    theExporter.SetLastError("Invalid bone assignment.", __FILE__, __LINE__);
                    return 0;
                }
            }
        }

        // release all interfaces
        pPhysiqueExport->ReleaseContextInterface(pContextExport);
        m_pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
    }
#if MAX_RELEASE >= 4000
    // check for skin modifier
    else if(m_modifierType == MODIFIER_SKIN)
    {
        // create a skin interface
        ISkin *pSkin;
        pSkin = (ISkin*)m_pModifier->GetInterface(I_SKIN);
        if(pSkin == 0)
        {
            delete pVertexCandidate;
            theExporter.SetLastError("Skin modifier interface not found.", __FILE__, __LINE__);
            return 0;
        }

        // create a skin context data interface
        ISkinContextData *pSkinContextData;
        pSkinContextData = (ISkinContextData *)pSkin->GetContextInterface(m_pINode);
        if(pSkinContextData == 0)
        {
            m_pModifier->ReleaseInterface(I_SKIN, pSkin);
            delete pVertexCandidate;
            theExporter.SetLastError("Skin context data interface not found.", __FILE__, __LINE__);
            return 0;
        }

        // loop through all influencing bones
        int nodeId;
        for(nodeId = 0; nodeId < pSkinContextData->GetNumAssignedBones(vertexId); nodeId++)
        {
            // get the bone id
            int boneId;
            boneId = pSkinContextData->GetAssignedBone(vertexId, nodeId);
            if(boneId < 0) continue;

            // add the influence to the vertex candidate
            if(!AddBoneInfluence(pSkeletonCandidate, pVertexCandidate, pSkin->GetBone(boneId), pSkinContextData->GetBoneWeight(vertexId, nodeId)))
            {
                m_pModifier->ReleaseInterface(I_SKIN, pSkin);
                delete pVertexCandidate;
                theExporter.SetLastError("Invalid bone assignment.", __FILE__, __LINE__);
                return 0;
            }
        }

        // release all interfaces
        m_pModifier->ReleaseInterface(I_SKIN, pSkin);
    }
#endif
        else if( m_modifierType == MODIFIER_MORPHER || m_modifierType == MODIFIER_NONE ) {
        }
        else 
    {
          theExporter.SetLastError("No physique/skin/morpher modifier found.", __FILE__, __LINE__);
          return 0;
    }

    return pVertexCandidate;
}
示例#16
0
void SGP_MaxInterface::GetBoneGroup( Modifier *pModifier,
									 int nModifierType, 
									 INode* pNode, 
									 Mesh* pMesh,
									 int nVertexId,
									 BoneGroup& boneGroup )
{
	if( !pMesh )
	{
		assert( false );
		return;
	}

	if( nVertexId >= pMesh->numVerts )
	{
		assert( false );
		return;
	}

	// static mesh
	if( nModifierType == MODIFIER_NONE )
	{
		INode* pParent = pNode->GetParentNode();
		if( pParent && ( IsBone( pParent ) || IsBipedBone( pParent ) ) )
		{
			Influence infl;
			infl.fWeight = 1.0f;
			strcpy( infl.szBoneName, pParent->GetName() );
			boneGroup.AddInfluence( infl );
		}
	}
	// check for physique modifier
	else if( nModifierType == MODIFIER_PHYSIQUE )
	{
		assert( pModifier && "get bone group error, modifier is null" );
		// create a physique export interface
		IPhysiqueExport *pPhysiqueExport = (IPhysiqueExport *)pModifier->GetInterface(I_PHYINTERFACE);
		if(pPhysiqueExport == NULL)
		{
			return;
		}

		// create a context export interface
		IPhyContextExport *pContextExport = (IPhyContextExport *)pPhysiqueExport->GetContextInterface(pNode);
		if(pContextExport == NULL)
		{
			pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
			return;
		}

		// set the flags in the context export interface
		pContextExport->ConvertToRigid(TRUE);
		pContextExport->AllowBlending(TRUE);

		// get the vertex export interface
		IPhyVertexExport *pVertexExport = (IPhyVertexExport *)pContextExport->GetVertexInterface(nVertexId);
		if(pVertexExport == NULL)
		{
			pPhysiqueExport->ReleaseContextInterface(pContextExport);
			pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);
			return;
		}

		// get the vertex type
		int vertexType = pVertexExport->GetVertexType();

		// handle the specific vertex type
		if(vertexType == RIGID_TYPE)
		{
			// typecast to rigid vertex
			IPhyRigidVertex *pTypeVertex = (IPhyRigidVertex *)pVertexExport;


			Influence infl;
			if( pTypeVertex->GetNode() )
			{
				strcpy( infl.szBoneName, pTypeVertex->GetNode()->GetName() );
				infl.fWeight = 1.0f;
				boneGroup.AddInfluence( infl );
			}
			else 
				return;
		}
		else if(vertexType == RIGID_BLENDED_TYPE)
		{
			// typecast to blended vertex
			IPhyBlendedRigidVertex *pTypeVertex = (IPhyBlendedRigidVertex *)pVertexExport;

			// loop through all influencing bones
			Influence infl;
			for(int nodeId = 0; nodeId < pTypeVertex->GetNumberNodes(); nodeId++)
			{
				strcpy( infl.szBoneName, pTypeVertex->GetNode( nodeId )->GetName() );
				infl.fWeight = pTypeVertex->GetWeight( nodeId );

				boneGroup.AddInfluence( infl );
			}
		}

		// release all interfaces
		pPhysiqueExport->ReleaseContextInterface(pContextExport);
		pModifier->ReleaseInterface(I_PHYINTERFACE, pPhysiqueExport);

	}
	else if( nModifierType == MODIFIER_SKIN)
	{
		assert( pModifier && "get bone group error, modifier is null" );
		// create a skin interface
		ISkin *pSkin = (ISkin*)pModifier->GetInterface(I_SKIN);
		if(pSkin == 0)
		{
			return;
		}

		// create a skin context data interface
		ISkinContextData *pSkinContextData;
		pSkinContextData = (ISkinContextData *)pSkin->GetContextInterface(pNode);
		if(pSkinContextData == NULL)
		{
			pModifier->ReleaseInterface(I_SKIN, pSkin);
			return;
		}

		// loop through all influencing bones
		for(int nodeId = 0; nodeId < pSkinContextData->GetNumAssignedBones(nVertexId); nodeId++)
		{
			// get the bone id
			int boneId = pSkinContextData->GetAssignedBone(nVertexId, nodeId);
			if(boneId < 0)
				continue;

			INode* pBone = pSkin->GetBone( boneId );
			Influence infl;
			strcpy( infl.szBoneName, pBone->GetName() );
			infl.fWeight = pSkinContextData->GetBoneWeight(nVertexId, nodeId);

			boneGroup.AddInfluence( infl );
		}

		// release all interfaces
		pModifier->ReleaseInterface(I_SKIN, pSkin);
	}
}
示例#17
0
	IMenuScreen::IMenuScreen()
	{
		ISkin* skin = PolyBomberApp::getISkin();		
		background.setImage(skin->loadImage(MENU_BACKGROUND));
		this->widgets.push_back(&background);
	}
示例#18
0
static void extractTriangleGeometry( GmModel* gm, INode* node, Mesh* mesh, Mtl* material )
{
#ifdef SGEXPORT_PHYSIQUE
	Modifier*			phyMod		= 0;
	IPhysiqueExport*	phyExport	= 0;
	IPhyContextExport*	mcExport	= 0;
#endif
	Modifier*			skinMod		= 0;
	ISkin*				skin		= 0;
	String				nodeName	( node->GetName() );

	try
	{
		// vertex transform to left-handed system
		Matrix3 pivot = TmUtil::getPivotTransform( node );
		Matrix3 vertexTM = pivot * s_convtm;
		bool insideOut = TmUtil::hasNegativeParity( pivot );

		/*Matrix4x4 pm = TmUtil::toLH( vertexTM );
		Debug::println( "Object {0} vertex local TM is", nodeName );
		Debug::println( "  {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(0,0), pm(0,1), pm(0,2), pm(0,3) );
		Debug::println( "  {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(1,0), pm(1,1), pm(1,2), pm(1,3) );
		Debug::println( "  {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(2,0), pm(2,1), pm(2,2), pm(2,3) );
		Debug::println( "  {0,#.###} {1,#.###} {2,#.###} {3,#.###}", pm(3,0), pm(3,1), pm(3,2), pm(3,3) );*/

		// add vertex positions
		int vertices = mesh->getNumVerts();
		for ( int vi = 0 ; vi < vertices ; ++vi )
		{
			Point3 v = vertexTM * mesh->verts[vi];
			mb::Vertex* vert = gm->addVertex();
			vert->setPosition( v.x, v.y, v.z );
		}

		// add vertex weights (from Physique modifier)
#ifdef SGEXPORT_PHYSIQUE
		phyMod = PhyExportUtil::findPhysiqueModifier( node );
		if ( phyMod )
		{
			Debug::println( "  Found Physique modifier: {0}", gm->name );

			// get (possibly shared) Physique export interface
			phyExport = (IPhysiqueExport*)phyMod->GetInterface( I_PHYINTERFACE );
			if( !phyExport )
				throw Exception( Format("No Physique modifier export interface") );

			// export from initial pose?
			phyExport->SetInitialPose( false );
			
			// get (unique) context dependent export inteface
			mcExport = (IPhyContextExport*)phyExport->GetContextInterface( node );
			if( !mcExport )
				throw Exception( Format("No Physique modifier context export interface") );

			// convert to rigid for time independent vertex assignment
			mcExport->ConvertToRigid( true );

			// allow blending to export multi-link assignments
			mcExport->AllowBlending( true );

			// list bones
			Vector<INode*> bones( Allocator<INode*>(__FILE__,__LINE__) );
			PhyExportUtil::listBones( mcExport, bones );

			// add vertex weight maps
			for ( int i = 0 ; i < bones.size() ; ++i )
			{
				INode* bone = bones[i];
				String name = bone->GetName();
				mb::VertexMap* vmap = gm->addVertexMap( 1, name, mb::VertexMapFormat::VERTEXMAP_WEIGHT );
				PhyExportUtil::addWeights( vmap, bone, mcExport );
			}
		}
#endif // SGEXPORT_PHYSIQUE

		// add vertex weights (from Skin modifier)
		skinMod = SkinExportUtil::findSkinModifier( node );
		if ( skinMod )
		{
			skin = (ISkin*)skinMod->GetInterface(I_SKIN);
			require( skin );
			ISkinContextData* skincx = skin->GetContextInterface( node );
			require( skincx );
			Debug::println( "  Found Skin modifier: {0} ({1} bones, {2} points)", gm->name, skin->GetNumBones(), skincx->GetNumPoints() );
			
			if ( skincx->GetNumPoints() != gm->vertices() )
				throw Exception( Format("Only some vertices ({0}/{1}) of {2} are skinned", skincx->GetNumPoints(), gm->vertices(), gm->name) );

			// list bones
			Vector<INode*> bones( Allocator<INode*>(__FILE__,__LINE__) );
			SkinExportUtil::listBones( skin, bones );

			// add vertex weight maps
			for ( int i = 0 ; i < bones.size() ; ++i )
			{
				INode* bone = bones[i];
				String name = bone->GetName();
				mb::VertexMap* vmap = gm->addVertexMap( 1, name, mb::VertexMapFormat::VERTEXMAP_WEIGHT );
				SkinExportUtil::addWeights( vmap, bone, skin, skincx );
				//Debug::println( "    Bone {0} is affecting {1} vertices", name, vmap->size() );
			}

			// DEBUG: print skin node tm and initial object tm
			/*Matrix3 tm;
			int ok = skin->GetSkinInitTM( node, tm );
			require( ok == SKIN_OK );
			Debug::println( "  NodeInitTM of {0}", nodeName );
			TmUtil::println( tm, 4 );
			ok = skin->GetSkinInitTM( node, tm, true );
			require( ok == SKIN_OK );
			Debug::println( "  NodeObjectTM of {0}", nodeName );
			TmUtil::println( tm, 4 );*/

			// DEBUG: print bones
			/*Debug::println( "  bones of {0}:", nodeName );
			for ( int i = 0 ; i < bones.size() ; ++i )
			{
				Debug::println( "    bone ({0}): {1}", i, String(bones[i]->GetName()) );
				skin->GetBoneInitTM( bones[i], tm );
				Debug::println( "      InitNodeTM:" );
				TmUtil::println( tm, 6 );
				skin->GetBoneInitTM( bones[i], tm, true );
				Debug::println( "      InitObjectTM:" );
				TmUtil::println( tm, 6 );
			}*/

			// DEBUG: print bones used by the points
			/*for ( int i = 0 ; i < skincx->GetNumPoints() ; ++i )
			{
				int bonec = skincx->GetNumAssignedBones(i);
				Debug::println( "    point {0} has {1} bones", i, bonec );
				for ( int k = 0 ; k < bonec ; ++k )
				{
					int boneidx = skincx->GetAssignedBone( i, k );
					float w = skincx->GetBoneWeight( i, k );
					Debug::println( "    point {0} boneidx ({1}): {2}, weight {3}", i, k, boneidx, w );
				}
			}*/
		}

		// ensure clockwise polygon vertex order
		int vx[3] = {2,1,0};
		if ( insideOut )
		{
			int tmp = vx[0];
			vx[0] = vx[2];
			vx[2] = tmp;
		}
	
		// list unique materials used by the triangles
		Vector<ShellMaterial> usedMaterials( Allocator<ShellMaterial>(__FILE__,__LINE__) );
		if ( material )
		{
			for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi )
			{
				Face& face = mesh->faces[fi];
				
				int mergesubmaterial = -1;
				int originalsubmaterial = -1;

				for ( int j = 0; j < material->NumSubMtls(); ++j)
				{
					// Get Sub Material Slot name 
					TSTR name = material->GetSubMtlSlotName(j);

					// Light maps are stored in sub material slot named "Baked Material"
					if ( strcmp( name, "Baked Material" ) == 0 ) 
						mergesubmaterial = j;
					else 
						originalsubmaterial = j;				
				}

				if ( mergesubmaterial != -1 ) // A baked material was found, shell materials will be created
				{
					Mtl* mat = material->GetSubMtl( originalsubmaterial );
					Mtl* bakedmtl = material->GetSubMtl( mergesubmaterial );
				
					if ( mat->NumSubMtls() > 0 ) // Check for nested multi-material
					{
						for ( int j = 0; j < mat->NumSubMtls(); ++j)
							usedMaterials.add( ShellMaterial( mat->GetSubMtl( face.getMatID() % mat->NumSubMtls() ), bakedmtl ) );
					} else
						usedMaterials.add( ShellMaterial( mat, bakedmtl ) );
				}
				else if ( material->NumSubMtls() > 0 ) // Multi-material without baked material 
				{  
					usedMaterials.add( ShellMaterial( material->GetSubMtl( face.getMatID() % material->NumSubMtls() ), 0 ) ); 
				}
				else	// Single material without baked material
				{
					usedMaterials.add( ShellMaterial( material, 0 ) );
				}				
			}
			std::sort( usedMaterials.begin(), usedMaterials.end() );
			usedMaterials.setSize( std::unique( usedMaterials.begin(), usedMaterials.end() ) - usedMaterials.begin() );
		}

		// create used materials
		for ( int mi = 0 ; mi < usedMaterials.size() ; ++mi )
		{
			ShellMaterial shellmtl = usedMaterials[mi];
			gm->materials.add( GmUtil::createGmMaterial( shellmtl.original, shellmtl.baked ) );
		}

		// add triangles
		for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi )
		{
			mb::Polygon* poly = gm->addPolygon();

			// triangle indices
			Face& face = mesh->faces[fi];
			for ( int vxi = 0 ; vxi < 3 ; ++vxi )
			{
				int vi = face.v[ vx[vxi] ];
				require( vi >= 0 && vi < gm->vertices() );
				mb::Vertex* vert = gm->getVertex( vi );
				poly->addVertex( vert );
			}

			// triangle material
			int polyMaterialIndex = 0;
			if ( material )
			{
				ShellMaterial mat( material, 0 );
				
				int numsubmaterials = material->NumSubMtls();  

				if ( numsubmaterials > 0 )
				{
					mat.original = material->GetSubMtl( face.getMatID() % material->NumSubMtls() );
		
					for ( int j = 0; j < numsubmaterials; ++j) // Is baked material present?
					{
						TSTR name = material->GetSubMtlSlotName(j);
						if ( strcmp( name, "Baked Material" ) == 0 )
							mat.baked = material->GetSubMtl( j );
						if ( strcmp( name, "Original Material" ) == 0 )
							mat.original = material->GetSubMtl( j );
					}
					if ( mat.original->NumSubMtls() > 0 )  // Is there a nested multi-material?
					{
						mat.original = mat.original->GetSubMtl( face.getMatID() % mat.original->NumSubMtls() );
					}
				}

				for ( int mi = 0 ; mi < usedMaterials.size() ; ++mi )
				{
					if ( usedMaterials[mi] == mat )
					{
						polyMaterialIndex = mi;
						break;
					}
				}
			}
			poly->setMaterial( polyMaterialIndex );
		}

		// add vertex colors
		int mp = 0;
		if ( mesh->mapSupport(mp) && mesh->getNumMapVerts(mp) > 0 )
		{
			mb::DiscontinuousVertexMap* vmad = gm->addDiscontinuousVertexMap( 3, "rgb", mb::VertexMapFormat::VERTEXMAP_RGB );

			int tverts = mesh->getNumMapVerts( mp );
			UVVert* tvert = mesh->mapVerts( mp );
			TVFace* tface = mesh->mapFaces( mp );

			//Debug::println( "Vertex colors:" );
			for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi )
			{
				Face& face = mesh->faces[fi];
				mb::Polygon* poly = gm->getPolygon( fi );

				for ( int vxi = 0 ; vxi < 3 ; ++vxi )
				{
					int vi = face.v[ vx[vxi] ];
					mb::Vertex* vert = gm->getVertex( vi );
					Point3 tc = tvert[ tface[fi].t[ vx[vxi] ] % tverts ];
					float rgb[3] = {tc.x, tc.y, tc.z};
					vmad->addValue( vert->index(), poly->index(), rgb, 3 );
					//Debug::println( "  vertex[{0}].rgb: {1} {2} {3}", vert->index(), rgb[0], rgb[1], rgb[2] );
				}
			}
		}

		// add texcoord layers
		int lastCoords = MAX_MESHMAPS-2;
		while ( lastCoords > 0 && (!mesh->mapSupport(lastCoords) || 0 == mesh->getNumMapVerts(lastCoords)) )
			--lastCoords;
		if ( lastCoords > 8 )
			throw IOException( Format("Too many texture coordinate sets ({1}) in {0}", gm->name, lastCoords) );

		for ( mp = 1 ; mp <= lastCoords ; ++mp )
		{
			mb::DiscontinuousVertexMap* vmad = gm->addDiscontinuousVertexMap( 2, "uv", mb::VertexMapFormat::VERTEXMAP_TEXCOORD );

			if ( mesh->mapSupport(mp) && mesh->getNumMapVerts(mp) > 0 )
			{
				int tverts = mesh->getNumMapVerts( mp );
				UVVert* tvert = mesh->mapVerts( mp );
				TVFace* tface = mesh->mapFaces( mp );
				
				for ( int fi = 0 ; fi < mesh->getNumFaces() ; ++fi )
				{
					Face& face = mesh->faces[fi];
					mb::Polygon* poly = gm->getPolygon( fi );

					for ( int vxi = 0 ; vxi < 3 ; ++vxi )
					{
						int vi = face.v[ vx[vxi] ];
						mb::Vertex* vert = gm->getVertex( vi );
						Point3 tc = tvert[ tface[fi].t[ vx[vxi] ] % tverts ];
						float uv[2] = {tc.x, 1.f-tc.y};
						vmad->addValue( vert->index(), poly->index(), uv, 2 );
					}
				}
			}
		}

		// compute face vertex normals from smoothing groups
		require( mesh->getNumFaces() == gm->polygons() );
		mb::DiscontinuousVertexMap* vmad = gm->addDiscontinuousVertexMap( 3, "vnormals", mb::VertexMapFormat::VERTEXMAP_NORMALS );
		for ( int fi = 0 ; fi < gm->polygons() ; ++fi )
		{
			mb::Polygon* poly = gm->getPolygon( fi );
			require( poly );
			require( poly->index() >= 0 && poly->index() < mesh->getNumFaces() );
			Face& face = mesh->faces[ poly->index() ];

			require( poly->vertices() == 3 );
			for ( int j = 0 ; j < poly->vertices() ; ++j )
			{
				Vector3 vn(0,0,0);
				mb::Vertex* vert = poly->getVertex( j );

				// sum influencing normals
				for ( int k = 0 ; k < vert->polygons() ; ++k )
				{
					mb::Polygon* vpoly = vert->getPolygon( k );
					require( vpoly );
					require( vpoly->index() >= 0 && vpoly->index() < mesh->getNumFaces() );
					Face& vface = mesh->faces[ vpoly->index() ];

					if ( 0 != (face.smGroup & vface.smGroup) || poly == vpoly )
					{
						Vector3 vpolyn;
						vpoly->getNormal( &vpolyn.x, &vpolyn.y, &vpolyn.z );
						vn += vpolyn;
					}
				}

				// normalize
				float lensqr = vn.lengthSquared();
				if ( lensqr > Float::MIN_VALUE )
					vn *= 1.f / Math::sqrt(lensqr);
				else
					vn = Vector3(0,0,0);

				vmad->addValue( vert->index(), poly->index(), vn.begin(), 3 );
			}
		}

		// re-export mesh points in non-deformed pose if Skin modifier present
		// NOTE: 3ds Mesh must not be used after this, because collapsing can invalidate it
		if ( skin )
		{
			// evaluate derived object before Skin modifier
			TimeValue time = 0;
			bool evalNext = false;
			bool evalDone = false;
			::ObjectState os;
			::Object* obj = node->GetObjectRef();
			while ( obj->SuperClassID() == GEN_DERIVOB_CLASS_ID && !evalDone )
			{
				IDerivedObject* derivedObj = static_cast<IDerivedObject*>(obj);
				for ( int modStack = 0 ; modStack < derivedObj->NumModifiers() ; ++modStack )
				{
					if ( evalNext )
					{
						os = derivedObj->Eval( time, modStack );
						evalDone = true;
						break;
					}

					Modifier* mod = derivedObj->GetModifier(modStack);
					if ( mod->ClassID() == SKIN_CLASSID )
						evalNext = true;
				}
				obj = derivedObj->GetObjRef();
			}

			// evaluate possible non-derived object
			if ( evalNext && !evalDone )
			{
				os = obj->Eval( time );
				evalDone = true;
			}

			// convert to TriObject and get points
			if ( evalDone && os.obj->CanConvertToType( Class_ID(TRIOBJ_CLASS_ID,0) ) )
			{
				Debug::println( "  Evaluating object {0} before Skin modifier", nodeName );

				// get TriObject
				std::auto_ptr<TriObject> triAutoDel(0);
				TriObject* tri = static_cast<TriObject*>( os.obj->ConvertToType( time, Class_ID(TRIOBJ_CLASS_ID,0) ) );
				if ( tri != os.obj )
					triAutoDel = std::auto_ptr<TriObject>( tri );

				// get mesh points before Skin is applied
				//Debug::println( "  Original collapsed mesh has {0} points, before Skin modifier {1} points", mesh->getNumVerts(), tri->mesh.getNumVerts() );
				require( gm->vertices() == tri->mesh.getNumVerts() );
				Mesh* mesh = &tri->mesh;
				int vertices = mesh->getNumVerts();
				for ( int vi = 0 ; vi < vertices ; ++vi )
				{
					Point3 v = vertexTM * mesh->verts[vi];
					mb::Vertex* vert = gm->getVertex( vi );
					vert->setPosition( v.x, v.y, v.z );
				}
			}
		}

		// split vertices with discontinuous vertex map values
		for ( int vmi = 0 ; vmi < gm->discontinuousVertexMaps() ; ++vmi )
		{
			mb::DiscontinuousVertexMap* vmad = gm->getDiscontinuousVertexMap( vmi );
			gm->splitVertexDiscontinuities( vmad );
		}

		// find base texcoord layer
		mb::DiscontinuousVertexMap* texcoords = 0;
		for ( int i = 0 ; i < gm->discontinuousVertexMaps() ; ++i )
		{
			mb::DiscontinuousVertexMap* vmad = gm->getDiscontinuousVertexMap(i);
			if ( vmad->dimensions() == 2 && vmad->format() == mb::VertexMapFormat::VERTEXMAP_TEXCOORD )
			{
				texcoords = vmad;
				break;
			}
		}
		if ( !texcoords )
			Debug::printlnError( "Object {0} must have texture coordinates", gm->name );
			// requires identification of footsteps in MySceneExport::isExportableGeometry
			//throw IOException( Format("Object {0} must have texture coordinates", gm->name) );

		// optimize
		gm->removeUnusedVertices();

		// cleanup export interfaces
#ifdef SGEXPORT_PHYSIQUE
		if ( mcExport )
		{
			require( phyExport );
			phyExport->ReleaseContextInterface( mcExport );
			mcExport = 0;
		}
		if ( phyExport )
		{
			require( phyMod );
			phyMod->ReleaseInterface( I_PHYINTERFACE, phyExport );
			phyExport = 0;
		}
#endif // SGEXPORT_PHYSIQUE
		if ( skin )
		{
			skinMod->ReleaseInterface( I_SKIN, skin );
			skin = 0;
			skinMod = 0;
		}
	}
	catch ( ... )
	{
		// cleanup export interfaces
#ifdef SGEXPORT_PHYSIQUE
		if ( mcExport )
		{
			require( phyExport );
			phyExport->ReleaseContextInterface( mcExport );
			mcExport = 0;
		}
		if ( phyExport )
		{
			require( phyMod );
			phyMod->ReleaseInterface( I_PHYINTERFACE, phyExport );
			phyExport = 0;
		}
#endif // SGEXPORT_PHYSIQUE
		if ( skin )
		{
			skinMod->ReleaseInterface( I_SKIN, skin );
			skin = 0;
			skinMod = 0;
		}
		throw;
	}
}
//----------------------------------------------------------------------------
void SceneBuilder::ProcessSkin(INode *node, Modifier *skinMod)
{
	// 构造皮肤控制器。如果Max的网格被按照材质细分,每一个网格都需要自己的蒙皮
	// 信息控制器。蒙皮信息中的offset,在动画起始时被计算,是骨骼的世界变换。
	//
	// node:
	//		指向蒙皮修改器指向的Max中的节点。
	// skinMod:
	//		指向蒙皮修改器

	// 1. 获得max蒙皮信息中的骨骼,对应的在Phoenix的骨骼节点列表
	// 2. 获得maxNode影响的Phoenix网格
	// 3. 获得max中每个骨骼所影响的Phoenix网格中的顶点的数量,忽略不受蒙皮信息
	//	  影响的网格
	// 4. 计算Phoenix mesh的蒙皮信息,生成SkinControl,AttachController到
	//    Phoenix mesh上。
	
	// 1

	bool needDel;
	TriObject *triObj = GetTriObject(node, &needDel);
	Mesh *maxMesh = &triObj->GetMesh();

	// Max皮肤控制器接口
	ISkin *skin = (ISkin*)skinMod->GetInterface(I_SKIN);
	ISkinContextData *skinData = skin->GetContextInterface(node);

	// max Skin Bones -> Phoenix2 Skin Bones
	int b, numSkinBone = skin->GetNumBones();
	PX2::Node **bones = new1<PX2::Node*>(numSkinBone);
	for (b=0; b<numSkinBone; b++)
	{
		INode *boneNode = skin->GetBone(b);
		const std::string &boneName = boneNode->GetName();
		PX2::Node *node = PX2::StaticCast<PX2::Node>(mScene->GetObjectByName(boneName));
		bones[b] = node;
	}

	// 1

	// 获得maxNode相关联的Phoenix mesh
	std::vector<PX2::TriMesh*> meshes;
	PX2::Object *object = mScene->GetObjectByName(node->GetName());
	if (object->IsExactly(PX2::TriMesh::TYPE))
	{
		meshes.push_back(PX2::StaticCast<PX2::TriMesh>(object));
	}
	else
	{
		PX2::Node *node = PX2::StaticCast<PX2::Node>(object);
		const char *nName = node->GetName().c_str();
		for (int c=0; c<node->GetNumChildren(); c++)
		{
			PX2::Movable *child = node->GetChild(c);
			const char *cName = child->GetName().c_str();
			if (strncmp(cName, nName, strlen(nName)) == 0) // 这里必须是strlen(nName),因为子节点有_1,_2
			{
				meshes.push_back(PX2::StaticCast<PX2::TriMesh>(child));
			}
		}
	}

	// 为Phoenix2的每个网格建立相关的皮肤控制器

	int *boneInfuseNumVert = new1<int>(numSkinBone);
	for (int m=0; m<(int)meshes.size(); m++)
	{
		PX2::TriMesh *mesh = meshes[m];

		// Phoenix顶点在max顶点中的索引
		PX2::VertexBuffer *vb = mesh->GetVertexBuffer();
		int px2MeshVertexNum = vb->GetNumElements();
		std::vector<int> MaxVertexIndex; // i->max索引
		int v, i, j, k;

		PX2::VertexBufferAccessor vba(mesh->GetVertexFormat(), vb);

		// 3

		for (int v=0; v<px2MeshVertexNum; ++v)
		{
			Float3 &position = vba.Position<Float3>(v);
			for (i=0; i<maxMesh->getNumVerts(); i++)
			{
				if (position[0] == maxMesh->verts[i].x
					&& position[1] == maxMesh->verts[i].y 
					&& position[2] == maxMesh->verts[i].z)
				{
					MaxVertexIndex.push_back(i);
					break;
				}
			}
		}

		// 确定每个骨骼所影响的顶点数量
		int maxVertexSize = (int)MaxVertexIndex.size();
		memset(boneInfuseNumVert, 0, sizeof(int)*numSkinBone);
		for (i=0; i<maxVertexSize; i++)
		{
			v = MaxVertexIndex[i];
			for (j=0; j<skinData->GetNumAssignedBones(v); j++)
			{ // 这个max中的顶点受到几个骨骼影响啊?!
				b = skinData->GetAssignedBone(v, j); // 获得这个影响的骨骼索引(这个j是第几个)
				boneInfuseNumVert[b]++; // 这个骨骼影响的顶点数量++
			}
		}

		// (通过PX2中的顶点找到Max中的顶点,找到Max中影响该顶点的骨骼)

		// 如果Max的网格是被按照材质分割的,可能一些骨骼对当前Phoenix2网格没有
		// 影响
		int bQuantity = 0; // 影响当前Phoenix2网格的骨骼数量
		for (b=0; b<numSkinBone; b++)
		{
			if (boneInfuseNumVert[b] > 0)
				bQuantity++;
		}

		if (bQuantity == 0)
		{
			// Phoenix网格不被任何骨骼影响,进入下一个网格
			continue;
		}

		// 4

		PX2::Node **theBones = new1<PX2::Node*>(bQuantity);
		float **weight = new2<float>(bQuantity, maxVertexSize);
		memset(weight[0],0,bQuantity*maxVertexSize*sizeof(float));
		PX2::APoint **offset = new2<PX2::APoint>(bQuantity, maxVertexSize);
		memset(offset[0],0,bQuantity*maxVertexSize*sizeof(PX2::APoint));
		PX2::HMatrix *mats = new1<PX2::HMatrix>(bQuantity);

		// 计算max骨骼到Phoenix骨骼对应的索引(k)
		std::vector<int> bIArray(numSkinBone);
		for (b=0, k=0; b<numSkinBone; b++)
		{
			if (boneInfuseNumVert[b] > 0)
			{
				theBones[k] = bones[b]; // 获取对Mesh有影响的骨骼
				bIArray[b] = k; // max bone index -> px2 可用bone index
				
				HMatrix boneWorldMat = theBones[k]->WorldTransform.Matrix();
				HMatrix meshWorldMat =  mesh->WorldTransform.Matrix();

				mats[k] = boneWorldMat.Inverse() * meshWorldMat;
				
				k++;
			}
		}

		// 遍历顶点,计算顶点权重和offset
		for (i=0; i<maxVertexSize; i++)
		{
			v = MaxVertexIndex[i];
			for (j=0; j<skinData->GetNumAssignedBones(v); j++)
			{ // 遍历影响该Max顶点的骨骼
				b = skinData->GetAssignedBone(v, j);
				k = bIArray[b];
				float wit = skinData->GetBoneWeight(v, j); // 第j个骨骼的影响权重
				weight[i][k] = wit;

				Float3 &position = vba.Position<Float3>(i);

				APoint point = theBones[k]->WorldTransform.Inverse() 
					* (mesh->WorldTransform * APoint(position));
				offset[i][k] = Float3(point.X(), point.Y(), point.Z()); // 在所受影响骨骼中的位置
			}
		}

		PX2::SkinController *skinCtrl = new0 PX2::SkinController
			(maxVertexSize, bQuantity);
		skinCtrl->SetName("SkinController");
		for (int i=0; i<bQuantity; i++)
		{
			skinCtrl->GetBones()[i] = theBones[i];
			skinCtrl->GetTMMatrixs()[i] = mats[i];
		}

		// offset
		for (int i=0; i<maxVertexSize; i++)
		{
			for (int j=0; j<bQuantity; j++)
			{
				skinCtrl->GetWeights()[i][j] = weight[i][j];
				skinCtrl->GetOffsets()[i][j] = offset[i][j]; 
			}
		}

		// index weights
		for (int i=0; i<maxVertexSize; i++)
		{
			Float4 inds = Float4(0.0f, 0.0f, 0.0f, 0.0f);
			Float4 wights = Float4(0.0f, 0.0f, 0.0f, 0.0f);

			In *pSortBone = new In[bQuantity];
			for (int j=0; j<bQuantity; j++)
			{
				pSortBone[j].index = j;
				pSortBone[j].data = weight[i][j];
			}
			qsort(pSortBone, bQuantity, sizeof(pSortBone[0]), cmp);

			int useBoneNum = bQuantity;
			if (useBoneNum > 4)
				useBoneNum = 4;

			float allWeight = 0.0f;
			for (int useBoneIndex=0; useBoneIndex<useBoneNum; useBoneIndex++)
			{
				allWeight += pSortBone[useBoneIndex].data;
			}
			if (allWeight <= 0.0f)
				allWeight = 1.0f;

			for (int useBoneIndex=0; useBoneIndex<useBoneNum; useBoneIndex++)
			{
				inds[useBoneIndex] = (float)(pSortBone[useBoneIndex].index);
				wights[useBoneIndex] = pSortBone[useBoneIndex].data/allWeight;
			}

			vba.TCoord<Float4>(1, i) = inds;
			vba.TCoord<Float4>(2, i) = wights;

			delete [] pSortBone;
		}
		
		skinCtrl->Repeat = Controller::RT_WRAP;
		skinCtrl->MinTime = 0.0f;
		skinCtrl->MaxTime = TicksToSec(mTimeEnd - mTimeStart);

		mesh->AttachController(skinCtrl);

		delete1(theBones);
		delete2(weight);
		delete2(offset);
		delete1(mats);
	}

	if (needDel)
	{
		delete0(triObj);
	}

	delete1(bones);
	delete1(boneInfuseNumVert);
}
示例#20
0
bool Exporter::makeSkin(NiTriBasedGeomRef shape, INode *node, FaceGroup &grp, TimeValue t)
{
   if (!mExportSkin)
      return false;

   if (grp.verts.empty())
      return false;

   //get the skin modifier
   Modifier *mod = GetSkin(node);
   if (!mod)
      return false;

   ISkin *skin = (ISkin *) mod->GetInterface(I_SKIN);
   if (!skin)
      return false;

   ISkinContextData *skinData = skin->GetContextInterface(node);
   if (!skinData)
      return false;

   if (grp.strips.empty())
      strippify(grp);

   // Create new call back to finish export
   SkinInstance* si = new SkinInstance(this);
   mPostExportCallbacks.push_back(si);

   skin->GetSkinInitTM(node, si->bone_init_tm, false);
   skin->GetSkinInitTM(node, si->node_init_tm, true);

   si->shape = shape;

   // Get bone references (may not actually exist in proper structure at this time)
   int totalBones = skin->GetNumBones();
   si->boneWeights.resize(totalBones);
   si->boneList.resize(totalBones);
   for (int i=0; i<totalBones; ++i) {
      si->boneList[i] = getNode(skin->GetBone(i));
   }

   vector<int>& vidx = grp.vidx;
   int nv = vidx.size();
   for (int i=0; i<nv; ++i)
   {
      int vi = vidx[i];
      int nbones = skinData->GetNumAssignedBones(vi);
      for (int j=0; j<nbones; ++j)
      {
         SkinWeight sw;
         sw.index = i;
         sw.weight = skinData->GetBoneWeight(vi,j);
         int boneIndex = skinData->GetAssignedBone(vi,j);

         SkinInstance::SkinWeightList& weights = si->boneWeights[boneIndex];
         weights.push_back(sw);
      }         
   }

   // remove unused bones
   vector<NiNodeRef>::iterator bitr = si->boneList.begin();
   SkinInstance::BoneWeightList::iterator switr = si->boneWeights.begin();
   for (int i=0; i<totalBones; ++i) {
      vector<SkinWeight> &weights = (*switr);
      if (weights.empty())
      {
         bitr = si->boneList.erase(bitr);
         switr = si->boneWeights.erase(switr);
      }
      else
      {
         ++bitr, ++switr;
      }      
   }

   // Check for dismemberment
   if (IsFallout3() || IsSkyrim()) {
      Modifier *dismemberSkinMod = GetBSDismemberSkin(node);
      if (dismemberSkinMod)
      {
         if (IBSDismemberSkinModifier *disSkin = (IBSDismemberSkinModifier *) dismemberSkinMod->GetInterface(I_BSDISMEMBERSKINMODIFIER)){
            Tab<IBSDismemberSkinModifierData*> modData = disSkin->GetModifierData();
            if (modData.Count() >= 1) {
               IBSDismemberSkinModifierData* bsdsmd = modData[0];
               si->SkinInstConstructor = BSDismemberSkinInstance::Create;
               Tab<BSDSPartitionData> &flags = bsdsmd->GetPartitionFlags();
               GenericNamedSelSetList &fselSet = bsdsmd->GetFaceSelList();

               FaceMap fmap;
               NiTriBasedGeomDataRef data = DynamicCast<NiTriBasedGeomData>(shape->GetData());
               vector<Triangle> tris = data->GetTriangles();
               for (int i=0; i<tris.size(); ++i) {
                  Triangle tri = tris[i];
                  fmap[ rotate(tri) ] = i;
               }
               // Build up list of partitions and face to partition map
               si->partitions.resize(flags.Count());
               si->facePartList.resize( grp.faces.size(), -1 );
               for (int i=0; i<flags.Count(); ++i) {
                  BodyPartList& bp = si->partitions[i];
                  bp.bodyPart = (BSDismemberBodyPartType)flags[i].bodyPart;
                  bp.partFlag = (BSPartFlag)(flags[i].partFlag | PF_START_NET_BONESET);

                  BitArray& fSelect = fselSet[i];
                  for (int j=0; j<fSelect.GetSize(); ++j){
                     if ( fSelect[j] ) {
                        Triangle tri = grp.faces[grp.fidx[j]];
                        FaceMap::iterator fitr = fmap.find( rotate(tri) );
                        if (fitr != fmap.end())
                           si->facePartList[ (*fitr).second ] = i;
                     }
                  }
               }
            }
         }
      }
   }


   return true;
}
示例#21
0
	KeyAssignMenu::KeyAssignMenu(unsigned int player) :
		title("Configuration des touches", TITLEFONT, 50),
		subtitle("Joueur 1", TITLEFONT, 100),
		errorKey("La touche est deja utilisee", TEXTFONT, 170),
		cancel("Annuler", 550, CONTROLLERSCONFIGMENU),
		save("Valider", 550, CONTROLLERSCONFIGMENU),
		player(player)
	{
		ISkin* skin = PolyBomberApp::getISkin();	
		title.setColor(skin->getColor(TITLECOLOR));
		subtitle.setColor(skin->getColor(TEXTCOLOR));
		errorKey.setColor(skin->getColor(ERRORCOLOR));

		std::ostringstream text;
		text << "Joueur " << player;

		subtitle.setString(text.str());

		errorKey.setVisible(false);

		this->widgets.push_back(&title);
		this->widgets.push_back(&subtitle);
		this->widgets.push_back(&errorKey);
		this->widgets.push_back(&cancel);
		this->widgets.push_back(&save);

		std::string actions[7] = {"Haut :", "Bas :", "Gauche :", "Droite :",
								  "Action 1 :", "Action 2 :", "Pause :"};

		for (int i=0; i<7; i++)
		{
			actionText[i] = new TextWidget(actions[i], TEXTFONT, 220 + 45*i, RIGHT);
			actionText[i]->setColor(skin->getColor(TEXTCOLOR));	
			actionText[i]->move(-420, 0);

			keyText[i] = new LinkWidget("touche", 220 + 45*i, NONEMENU);
			keyText[i]->move(70, 0);

			if (i > 0)
				keyText[i]->setPrevious(keyText[i-1]);
			
			this->widgets.push_back(actionText[i]);
			this->widgets.push_back(keyText[i]);
		}

		cancel.move(-100, 0);
		save.move(100, 0);

		for (int i=0; i<6; i++)
			keyText[i]->setNext(keyText[i+1]);

		keyText[6]->setNext(&cancel);		

		cancel.setPrevious(keyText[6]);
		cancel.setNext(&save);
			
		save.setPrevious(keyText[6]);
		save.setNext(&cancel);

		cancel.setSelected(true);

		this->window = NULL;
	}