游戏开发论坛

 找回密码
 立即注册
搜索
查看: 5252|回复: 1

关于地表贴图(贴花),纹理投射的问题..(附:Mesh Decals与Projec

[复制链接]

9

主题

55

帖子

59

积分

注册会员

Rank: 2

积分
59
发表于 2008-2-20 20:32:00 | 显示全部楼层 |阅读模式
关于地表贴图(贴花),纹理投射的问题..(附:Mesh Decals与Projective Decals的资料)..自己实验好久无解,欢迎大家来指教.论讨

建立了一个高度地型之后...就是给地表加入不同的原素.

如地面上有路道..草皮,,沙漠等等...

一般是通过什么方法贴在地表上的..精确的与地表吻合..

我查过以下资料..

第一种方法:

Mesh Decals

代码如下:  编辑通过..执行也无错..就是没有显示我要的地表贴图.
MovableObject* createDecal( SceneManager& sceneMgr,
                            const String& name,
                            const String& materialName,
                            const Vector2& size )
{
        NameValuePairList params;
        params["materialName"] = materialName;
        params["width"] = StringConverter::toString( size.x );
        params["height"] = StringConverter::toString( size.y );
        params["sceneMgrInstance"] = sceneMgr.getName();

        return sceneMgr.createMovableObject( name,
                                             &quotagingLandScapeMeshDecal",
                                             &params );
}

执行报"PagingLandScapeMeshDecal"不存在...不知道怎么处理了..这个type究竟应该是什么?


第二种方法rojective Decals

class TerrainDecal
{
protected:
        Ogre::Vector3 mPos;                        // center
        Ogre::Vector2 mSize;                // size of decal

        std::string mTexture;                // texture to apply

        Ogre::SceneNode* mNode;                // the projection node
        Ogre::Frustum* mFrustum;        // the projection frustum

        Ogre::SceneManager* mSceneManager;        // pointer to PLSM2

        bool mVisible;                                // is the decal visible/active or not?

        // info about materials that are receiving the decal
        std::map<std::string,Ogre::Pass*> mTargets;                        // passes mapped by material names

        bool isPosOnTerrain(Ogre::Vector3 pos)
        {
                // get the terrain boundaries
                Ogre::AxisAlignedBox box;
                mSceneManager->getOption("MapBoundaries",&box);

                // check if pos is in box, ignore y
                pos.y = 0;
                return box.intersects(pos);
        }

        std::string getMaterialAtPosition(Ogre::Vector3 pos)
        {
                void* myOptionPtr = &pos;

                // check if position is on battlefield
                if( isPosOnTerrain(pos) )
                {
                        mSceneManager->getOption ("getMaterialPageName", myOptionPtr);
                        std::string name = **static_cast<std::string**>(myOptionPtr);
                        return name;
                }
                else
                        return "";
        }


        void addMaterial(std::string matName)
        {
                // check if material is already decalled
                if( mTargets.find(matName) != mTargets.end() )
                {
                        Ogre:ogManager::getSingleton().getDefaultLog()->logMessage("material should be added to decal but was already!");
                        return;
                }

                using namespace Ogre;

                // get the material ptr
                MaterialPtr mat = (MaterialPtr)MaterialManager::getSingleton().getByName(matName);

                // create a new pass in the material to render the decal
                Pass* pass = mat->getTechnique(0)->createPass();

                // set up the decal's texture unit
                TextureUnitState *texState = pass->createTextureUnitState(mTexture);
                texState->setProjectiveTexturing(true, mFrustum);
                texState->setTextureAddressingMode(TextureUnitState::TAM_CLAMP);
                texState->setTextureFiltering(FO_POINT, FO_LINEAR, FO_NONE);

                // set our pass to blend the decal over the model's regular texture
                pass->setSceneBlending(SBT_TRANSPARENT_ALPHA);
                pass->setDepthBias(1);

                // set the decal to be self illuminated instead of lit by scene lighting
                pass->setLightingEnabled(false);

                // save pass in map
                mTargets[matName] = pass;

                Ogre::LogManager::getSingleton().getDefaultLog()->logMessage(std::string("added material to decal: ") + matName +
                        "(" + Ogre::StringConverter::toString(mTargets.size()) + " materials loaded)");
        }

        std::map<std::string,Ogre::Pass*>::iterator removeMaterial(std::string matName)
        {
                // remove our pass from the given material
                mTargets[matName]->getParent()->removePass(mTargets[matName]->getIndex());

                Ogre::LogManager::getSingleton().getDefaultLog()->logMessage(std::string("removed material from decal: ") + matName +
                        "(" + Ogre::StringConverter::toString(mTargets.size()-1) + " materials loaded)");

                // remove from map
                return mTargets.erase(mTargets.find(matName));
        }

public:
        TerrainDecal()
        {
                mVisible = false;
                mNode = 0;
                mFrustum = 0;
        };

        ~TerrainDecal()
        {
                hide();

                // delete frustum
                mNode->detachAllObjects();
                delete mFrustum;

                // destroy node
                mNode->getParentSceneNode()->removeAndDestroyChild(mNode->getName());
        };

        void init( Ogre::SceneManager* man, Ogre::Vector2 size, std::string tex )
        {
                using namespace Ogre;

                // set SM
                mSceneManager = man;

                // init projective decal
                // set up the main decal projection frustum
                mFrustum = new Ogre::Frustum();
                mNode = mSceneManager->getRootSceneNode()->createChildSceneNode();
                mNode->attachObject(mFrustum);
                mFrustum->setProjectionType(Ogre::PT_ORTHOGRAPHIC);
                mNode->setOrientation(Ogre:uaternion(Ogre:egree(90),Ogre::Vector3::UNIT_X));

                // set given values
                updateSize(size);
                mTexture = tex;                // texture to apply

                // load the images for the decal and the filter
                TextureManager::getSingleton().load
                        (mTexture, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, TEX_TYPE_2D, 1);


                mVisible = false;
        }

        void show()
        {
                if( !mVisible )
                {
                        mVisible = true;
                        updatePosition(mPos);
                }
        }

        void hide()
        {
                if( mVisible )
                {
                        // remove all added passes
                        while( !mTargets.empty() )
                                removeMaterial(mTargets.begin()->first);

                        mVisible = false;
                }
        }

        void updatePosition( Ogre::Vector3 pos )
        {
                // don`t do anything if pos didn`t change
                //if( pos == mPos )
                //        return;

                // save the new position
                mPos = pos;
                mNode->setPosition(pos.x,pos.y+1000,pos.z);

                // don`t show if invisible
                if( !isVisible() )
                        return;

                // check near pages (up to 4)
                std::list<std::string> neededMaterials;
                Ogre::Vector3 t;

                // x high                z high
                t = Ogre::Vector3(mPos.x+mSize.x/2.0f,1000,mPos.z+mSize.y/2.0f);
                neededMaterials.push_back(getMaterialAtPosition(t));

                // x high                z low
                t = Ogre::Vector3(mPos.x+mSize.x/2.0f,1000,mPos.z-mSize.y/2.0f);
                neededMaterials.push_back(getMaterialAtPosition(t));

                // x low                z low
                t = Ogre::Vector3(mPos.x-mSize.x/2.0f,1000,mPos.z-mSize.y/2.0f);
                neededMaterials.push_back(getMaterialAtPosition(t));

                // x low                z high
                t = Ogre::Vector3(mPos.x-mSize.x/2.0f,1000,mPos.z+mSize.y/2.0f);
                neededMaterials.push_back(getMaterialAtPosition(t));

                // remove empties
                neededMaterials.remove("");

                // remove doubles
                neededMaterials.unique();


                // compare needed materials with used
               
                // for every used material
                std::map<std::string,Ogre::Pass*>::iterator used = mTargets.begin();
                while(true)
                {
                        // stop if we are through
                        if( used == mTargets.end() )
                                break;

                        // find in needed
                        std::list<std::string>::iterator needed =
                                std::find(neededMaterials.begin(),neededMaterials.end(),used->first);
                       
                        if( needed == neededMaterials.end() )
                        {
                                // material is not needed any longer, so remove it
                                used = removeMaterial(used->first);
                        }
                        else
                        {                               
                                // remove it from needed list, bedause it is already loaded
                                neededMaterials.remove(used->first);

                                // go further
                                used++;
                        }
                }

                // add all remaining needed to used list
                while( !neededMaterials.empty() )
                {
                        addMaterial(neededMaterials.front());
                        neededMaterials.erase(neededMaterials.begin());
                }
        }

        void updateSize(Ogre::Vector2 size)
        {
                if( mSize != size )
                {
                        // save param
                        mSize = size;

                        // update aspect ratio
                        mFrustum->setAspectRatio(mSize.x/mSize.y);

                        // set fovy so that tan = 1, so 45 degree
                        mFrustum->setFOVy(Ogre::Degree(45));

                        // set near clip plane according to fovy:
                        // distance = halfsize.y / tan(fovy)
                        mFrustum->setNearClipDistance(mSize.y);
                }
        }

        bool isVisible()
        {
                return mVisible;
        }
};



第三种方法:在别人的BLOG上看到要用manualObject来实现...正在测试中..


有经验的朋友指点一下..谢谢了.

9

主题

55

帖子

59

积分

注册会员

Rank: 2

积分
59
 楼主| 发表于 2008-2-20 20:44:00 | 显示全部楼层

Re:关于地表贴图(贴花),纹理投射的问题..(附:Mesh Decals与Pro

又找到资料,,可能是我没有安装plsm2的原因..

\ogreaddons\paginglandscape from Ogre CVS

下载试一下..
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-12-20 04:34

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表