饭后温柔

汉堡与老干妈同嚼 有可乐味
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

3D小地图(粗糙的仿造艾尔之光)

Posted on 2012-07-21 10:40  饭后温柔  阅读(658)  评论(0编辑  收藏  举报
//在小地图中描画出路径的轮廓.仿造艾尔之光副本中小地图
//粗糙的版本.自行修改.
#ifndef __UI3DRadarMap_H__
#define __UI3DRadarMap_H__ #include "Loki/Singleton.h" #include "SeerBaseConfig.h" #include <Ogre/Ogre.h> #include <map> #include "SeerNetProcotolData.h" #include "Loki/Singleton.h" #define UI3DRadarMapExport __declspec( dllexport ) namespace Orz { class CSeerEntityInterface; class UI3DRadarMapExport UI3DRadarMap { public: typedef std::vector<Ogre::Vector3> WayPointList; typedef std::map<std::string, WayPointList> PathList; private: typedef Loki::SingletonHolder<UI3DRadarMap> MySingleton; public: inline static UI3DRadarMap& Instance() { return MySingleton::Instance(); } UI3DRadarMap(); void init(Ogre::SceneManager* sm = NULL); void shutdown(); void update(TimeType time); void setup(); void loadPath(); void drawWay(WayPointList & waylist); void reset(); void updateMonstersCursor(); void hideMonsterCursor(guid_t id); void setSceneVisible(bool visible); struct Compare { typedef guid_t key_type; bool operator () (const key_type& ls, const key_type& rs) const { return ls.id < rs.id || ls.id == rs.id && ls.type < rs.type || ls.id == rs.id && ls.type == rs.type && ls.index < rs.index; } }; typedef std::map<guid_t, ComponentPtr, Compare> MonsterCursorMap; CEGUI::Window* _window; CEGUI::OgreRenderer* _render; CEGUI::RenderingWindow* _cerenderwindow; Ogre::SceneManager* _scenemgr; Ogre::TexturePtr _rtttexture; Ogre::RenderTarget * _renderTarget; Ogre::Camera * _camera; Ogre::SceneNode * _node; Ogre::ManualObject* _3dobject; Ogre::Entity* _entity; float _aspectFactor; MonsterCursorMap _monstersCursors; ComponentPtr _charCursorComp; CSeerEntityInterface* _charCursor; PathList _paths; }; } #endif

 

#include "SeerUIComponentStableHeaders.h"
#include "UI3DRadarMap.h"
#include <cegui/CEGUI.h>
#include <cegui/RendererModules/Ogre/CEGUIOgreRenderer.h>
#include <Orz/View_CEGUI/CEGUIManager.h>
#include "SimpleLogManager.h"
#include "RadarMapCursorInterface.h"
#include "SeerInterfaceManager.h"
#include "SeerMonsterLayoutInterface.h"
#include "CSeerEntityInterface.h"
#include "SeerInterfaceManager.h"
#include "SeerCharactorMoveInterface.h"
#include "SeerInterfaceManager.h"
#include "SeerHelper.h"
#include "SeerSquareInterface.h"

static float G_WIDTH_X = 3000;
static float G_HEIGHT_Y = 1500;

#define SMALLDELTA 0.05

namespace Orz
{
    //////////////////////////////////////////////////////////////////////////
    UI3DRadarMap::UI3DRadarMap():
            _window(NULL),
            _scenemgr(NULL),
            _cerenderwindow(NULL),
            _render(NULL),
            _renderTarget(NULL),
            _camera(NULL),
            _node(NULL),
            _3dobject(NULL)
    {

    }

    void UI3DRadarMap::init(Ogre::SceneManager* sm)
    {
        _window = CEGUI::WindowManager::getSingleton().getWindow("KJMainGame2_Nmap");
        _cerenderwindow = (CEGUI::RenderingWindow*)_window->getRenderingSurface();

        _render =  Orz::CEGUIManager::getSingletonPtr()->getRenderer();

        _aspectFactor = _window->getPixelSize().d_width / _window->getPixelSize().d_height;

        _rtttexture = Ogre::TextureManager::getSingleton().createManual("rtt_3dradarmap",
            Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
            Ogre::TEX_TYPE_2D, 256, 256, 1, 0, 
            Ogre::PF_R8G8B8A8, Ogre::TU_RENDERTARGET);

        _renderTarget = _rtttexture->getBuffer()->getRenderTarget();   
        _renderTarget->setActive(true);
        _renderTarget->setAutoUpdated(true);

        if (sm!=NULL) {
            _scenemgr = sm;
        } else {
            _scenemgr = Ogre::Root::getSingleton().createSceneManager(Ogre::ST_GENERIC, "ui3dradarmap_scenemanager");
        }

        _node =  _scenemgr->getRootSceneNode()->createChildSceneNode("ui3dradarmap_rootnode");

        _camera = _scenemgr->createCamera("ui3dradarmap_camera");
        _node->attachObject(_camera);
        _camera->setNearClipDistance(5);
        _camera->move(Ogre::Vector3(0, 0.0f, 100.0f));
        _camera->lookAt(Ogre::Vector3(0, 0.0f, -100.0f));
        _camera->setProjectionType(Ogre::PT_PERSPECTIVE);    
        _camera->setAspectRatio(_aspectFactor);//图片比例
        _camera->setFOVy(Ogre::Degree(45.0f));    


        Ogre::Viewport *vp = _renderTarget->addViewport(_camera);      
        vp->setAutoUpdated(true);
        vp->setBackgroundColour(Ogre::ColourValue(0,0,0,0));      
        vp->setOverlaysEnabled(false);      
        vp->setClearEveryFrame(true);  
        vp->setSkiesEnabled(false);

        CEGUI::Texture &ctex = CEGUIManager::getSingletonPtr()->getRenderer()->createTexture(_rtttexture,false);  
        CEGUI::Imageset &imgset = CEGUI::ImagesetManager::getSingleton().create("ui3dradarmap_imageset",ctex);      
        imgset.defineImage("RttImage",CEGUI::Point(0,0),ctex.getSize(),CEGUI::Point(0,0));  
        _window->setProperty("Image", CEGUI::PropertyHelper::imageToString(&imgset.getImage("RttImage")));
        _window->show();

        _charCursorComp =  Orz::ComponentFactories::getInstance().create("entity");
        _charCursor = _charCursorComp->queryInterface<CSeerEntityInterface>();
        _charCursor->load("ui3dradarmap_char_cursor", "Effect/map/cursor/char/char_cursor.mesh", false, _node);
        _charCursor->getSceneNode()->setScale(2.5, 2.5, 2.5);

    }

    void UI3DRadarMap::loadPath()
    {
        _paths.clear();
        SeerSquareInterface* square = SeerInterfaceManager::getSingleton().queryInterface<SeerSquareInterface>();
        typedef std::vector<SeerHelperPtr> PathNodeList;
        std::vector<SeerHelperPtr>& pathnodes = square->getHelperMap();
        std::vector<SeerHelperPtr>::iterator it = pathnodes.begin();
        for (; it != pathnodes.end(); ++it)
        {
            SeerHelperPtr helper = *it;

            if(helper->type == "path") continue;

            PathList::iterator it_path = _paths.find(helper->name);
            if (it_path == _paths.end())
            {
                WayPointList waylist;
                if(helper->node)
                    waylist.push_back(helper->node->_getDerivedPosition());
                _paths.insert(std::make_pair(helper->name, waylist));
            }
            else
            {
                if(helper->node)
                    it_path->second.push_back(helper->node->_getDerivedPosition());
            }
        }
    }

    void UI3DRadarMap::setup()
    {
        reset();
        PathList::iterator it_path = _paths.begin();
        for (; it_path != _paths.end(); ++it_path)
        {
            drawWay(it_path->second);
        }

        //WayPointList waylist;
        //for (int i = 0; i < 50; i+=2)
        //{
        //    waylist.push_back(Ogre::Vector3(-10000+400*i, -200, 0));
        //    waylist.push_back(Ogre::Vector3(-10000+400*(i+1), -200, 0));
        //    waylist.push_back(Ogre::Vector3(-10000+400*(i+1), 200, 0));
        //    waylist.push_back(Ogre::Vector3(-10000+400*(i+2), 200, 0));
        //}
        //drawWay(waylist);
        //waylist.clear();
        //waylist.push_back(Ogre::Vector3(-10000, -50, 0));
        //waylist.push_back(Ogre::Vector3(-5000, 50, 0));
        //waylist.push_back(Ogre::Vector3(5000, -50, 0));
        //waylist.push_back(Ogre::Vector3(10000, 50, 0));
        //drawWay(waylist);
    }

    void UI3DRadarMap::drawWay(WayPointList & waylist)
    {
        static int width = 40;

        _3dobject->begin("ui3dradarmap_road");

        WayPointList::iterator it_p = waylist.begin();
        _3dobject->position(*it_p);
        _3dobject->position(*it_p + width* Ogre::Vector3::UNIT_Y);

        ++it_p;
        if(it_p == waylist.end()) return;

        for (; (it_p + 1) != waylist.end(); ++it_p)
        {
            Ogre::Vector3 cur_point = *it_p;
            Ogre::Vector3 pre_point = *(it_p-1);
            Ogre::Vector3 nex_point = *(it_p+1);

            Ogre::Vector3 pre_dir = cur_point - pre_point;
            Ogre::Vector3 nex_dir = nex_point - cur_point;
            Ogre::Vector3 mid_dir = (nex_dir - pre_dir) / 2;
            Ogre::Vector3 vertical_dir(-pre_dir.y, pre_dir.x, pre_dir.z);

            pre_dir.normalise();
            nex_dir.normalise();
            mid_dir.normalise();
            vertical_dir.normalise();

            Ogre::Vector3 offset;
            float cos_v = nex_dir.dotProduct(pre_dir);
            float angle_v = std::acos(cos_v);

            if(angle_v < SMALLDELTA ) 
            {
                offset = width * vertical_dir;
            }
            else
            {
                if(nex_dir.crossProduct(pre_dir).z > 0)
                    mid_dir = - mid_dir;
                offset = ( width / std::abs(sin(angle_v/2)) ) * mid_dir;
            }


            Ogre::Vector3 cur_point_up = cur_point + offset;
            _3dobject->position(cur_point);
            _3dobject->position(cur_point_up);    
        }

        _3dobject->position(*it_p);
        _3dobject->position(*it_p + width* Ogre::Vector3::UNIT_Y);

        for (size_t i = 0; i < waylist.size()-1; i++)
            _3dobject->quad(2*i+3, 2*i+1,  2*i,  2*i+2);

        _3dobject->end();    
    }

    void UI3DRadarMap::shutdown()
    {

    }

    void UI3DRadarMap::update(TimeType time)
    {
        if(!_camera) return;

        Ogre::Camera* cam = OgreGraphicsManager::getSingletonPtr()->getCamera();
        _camera->setPosition(cam->getDerivedPosition());
        _camera->setDirection(cam->getDerivedDirection());

        SeerCharactorMoveInterface* move = SeerInterfaceManager::getSingletonPtr()->queryInterface<SeerCharactorMoveInterface>();
        if(move == NULL) return;
        Ogre::Vector3 charpos = move->getBodySceneNode()->_getDerivedPosition();
        _charCursor->getSceneNode()->_setDerivedPosition(charpos);
    
        updateMonstersCursor();
    }

    void UI3DRadarMap::updateMonstersCursor()
    {
        SeerMonsterLayoutInterface* monsterLayout =  SeerInterfaceManager::getSingleton().queryInterface<SeerMonsterLayoutInterface>();
        if(monsterLayout == NULL) return;
        std::vector<std::pair<guid_t, Ogre::Vector3>> monstersPosList = monsterLayout->getMonstersPosition();
        std::vector<std::pair<guid_t, Ogre::Vector3>>::iterator it_pair = monstersPosList.begin();
        for (; it_pair != monstersPosList.end(); ++it_pair)
        {
            MonsterCursorMap::iterator it = _monstersCursors.find(it_pair->first);
            ComponentPtr cursorComp;
            CSeerEntityInterface* cursorEnt;
            if (it == _monstersCursors.end())
            {
                cursorComp = Orz::ComponentFactories::getInstance().create("entity");
                cursorEnt = cursorComp->queryInterface<CSeerEntityInterface>();
                cursorEnt->setSceneManager(_scenemgr);
                cursorEnt->load(
                    "ui3dradarmap_monster_cursor_"+boost::lexical_cast<std::string>(_monstersCursors.size()),
                    "Effect/map/cursor/monster/monster_cursor.mesh", false, _node);
                cursorEnt->getSceneNode()->setScale(2.5, 2.5, 2.5);

                _monstersCursors.insert(std::make_pair(it_pair->first, cursorComp));
            }
            else 
            {
                cursorComp = it->second;
                cursorEnt = cursorComp->queryInterface<CSeerEntityInterface>();
            }
            cursorEnt->getSceneNode()->_setDerivedPosition(it_pair->second);
        }
    }


    void UI3DRadarMap::reset()
    {
        _monstersCursors.clear();
        if(_3dobject) {
            _3dobject->detachFromParent();
            if(_scenemgr) {
                _scenemgr->destroyManualObject(_3dobject->getName());
            }
        }

        _3dobject = _scenemgr->createManualObject("ui3dradarmap_manualobject");
        _node->attachObject(_3dobject);
    }

    void UI3DRadarMap::hideMonsterCursor(guid_t id)
    {
        MonsterCursorMap::iterator it = _monstersCursors.find(id);
        if(it == _monstersCursors.end()) return;

        CSeerEntityInterface* radarCursor = it->second->queryInterface<CSeerEntityInterface>();
        radarCursor->getSceneNode()->setVisible(false);
    }

    void UI3DRadarMap::setSceneVisible(bool visible)
    {
        if(_node)
            _node->setVisible(visible);
        CEGUI::Window* roleCursor = CEGUI::WindowManager::getSingleton().getWindow("KJMainGame2_mapRole");
        if(roleCursor)
            roleCursor->setVisible(!visible);
    }

}