irrlicht实现沿平面移动物体

使用到的原理:射线与面相交性检测

源码引用地址:http://irrlicht.sourceforge.net/forum/viewtopic.php?f=1&t=33059&p=190974&hilit=drag+move+model#p190974


// IrrEditor.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <irrlicht.h>

using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

#pragma comment(lib, "Irrlicht.lib")

IrrlichtDevice         *device         = 0;
IVideoDriver         *driver         = 0;
ISceneManager         *smgr         = 0;
IGUIEnvironment         *guienv         = 0;
ICameraSceneNode      *camera         = 0;
ISceneCollisionManager   *CollMan      = 0;

enum EditorMode
{
   MODE_NONE,
   MODE_QUIT,
   MODE_TRANSLATE,
   MODE_ROTATE,
   MODE_SCALE,
};

position2di            initialCursorPosition;      // where mouse cursor started
position2di            initialObjectPosition;      // where ray from camera to object intersected screen
ISceneNode*            SelectedNode      = 0;   // the selected node
bool               ShiftIsPressed      = 0;   // is the shift key pressed?
bool               LMouseButtonDown   = 0;   // is the left mouse button down?
EditorMode            Mode            = MODE_TRANSLATE;
float               RotateSpeed         = 0.01f;
float               ScaleSpeed         = 0.01f;

#define ID_QUIT         101
#define ID_TRANSLATE   102
#define ID_ROTATE      103
#define ID_SCALE      104

class MyEventReceiver : public IEventReceiver
{
public:
  virtual bool OnEvent(const SEvent& anevent)
  {
       switch(anevent.EventType)
       {
         case EET_GUI_EVENT :
         {
            switch (anevent.GUIEvent.EventType)
               {
                  case EGET_BUTTON_CLICKED:
                     {
                        switch (anevent.GUIEvent.Caller->getID())
                          {
                             case ID_QUIT      : 
                                {
                                   Mode = MODE_QUIT;         
                                } break; 
                             case ID_TRANSLATE   : 
                                {
                                   Mode = MODE_TRANSLATE;   
                                } break; 
                             case ID_ROTATE   : 
                                {
                                   Mode = MODE_ROTATE;
                                } break; 
                             case ID_SCALE      : 
                                {
                                   Mode = MODE_SCALE;
                                } break; 
                          } break;
                     } break;
               }
         }  break;
         
         case EET_KEY_INPUT_EVENT :
         {
            if (anevent.KeyInput.Shift) ShiftIsPressed = true; 
            else ShiftIsPressed = false;
         } break;

         // if it is a mouse event
         case EET_MOUSE_INPUT_EVENT :
         {
            // based upon the mouse event type
            switch (anevent.MouseInput.Event)
            {
               case EMIE_LMOUSE_PRESSED_DOWN :
                { 
                  // what a freakin hack
                  LMouseButtonDown = true;

                   // check for a node being selected 
                  SelectedNode = CollMan->getSceneNodeFromScreenCoordinatesBB(device->getCursorControl()->getPosition(),0,true); 

                   // If we selected a node 
                   if(SelectedNode) 
                   { 
                     // Remember where the node and cursor were when it was clicked on 
                     initialCursorPosition = device->getCursorControl()->getPosition(); 
                     initialObjectPosition = CollMan->getScreenCoordinatesFrom3DPosition(SelectedNode->getAbsolutePosition(), camera); 
                   }

                   // we used this message?
                   return (SelectedNode != 0);
                } break;

               case EMIE_LMOUSE_LEFT_UP :
                { 
                  LMouseButtonDown = false;
                  return false;
                } break;

               case EMIE_MOUSE_MOVED :
               {
                  if (!LMouseButtonDown) return false;

                  if (Mode == MODE_TRANSLATE)
                  {
                     if (SelectedNode)
                     {
                        vector3df p = SelectedNode->getPosition();
                        
                        if (ShiftIsPressed)
                         {
                           plane3df const planeXY(SelectedNode->getAbsolutePosition(), vector3df(1.f, 0.f, 0.f)); 
                           position2di currentCursorPosition(device->getCursorControl()->getPosition()); 
                           position2di effectiveObjectPosition = initialObjectPosition + currentCursorPosition - initialCursorPosition;
                           line3df ray(CollMan->getRayFromScreenCoordinates(effectiveObjectPosition, camera)); 
                           vector3df intersectWithPlane; 
                           vector3df oldPos = SelectedNode->getAbsolutePosition();

                           if(planeXY.getIntersectionWithLine(ray.start, ray.getVector(), intersectWithPlane)) 
                           {
                              intersectWithPlane.X = oldPos.X;
                              intersectWithPlane.Z = oldPos.Z;
                              SelectedNode->setPosition(intersectWithPlane);
                           }
                         }
                         else
                         {
                           plane3df const planeXZ(SelectedNode->getAbsolutePosition(), vector3df(0.f, 1.f, 0.f)); 
                           position2di currentCursorPosition(device->getCursorControl()->getPosition()); 
                           position2di effectiveObjectPosition = initialObjectPosition + currentCursorPosition - initialCursorPosition;
                           line3df ray(CollMan->getRayFromScreenCoordinates(effectiveObjectPosition, camera)); 
                           vector3df intersectWithPlane; 
                           if(planeXZ.getIntersectionWithLine(ray.start, ray.getVector(), intersectWithPlane)) 
                           {
                              SelectedNode->setPosition(intersectWithPlane);
                           }
                         }
                     }
                  } // end mode translate
                  else
                  if (Mode == MODE_ROTATE)
                  {
                     if (SelectedNode)
                     {
                        vector3df rot = SelectedNode->getRotation();
                        position2di currentCursorPosition(device->getCursorControl()->getPosition()); 
                        if (ShiftIsPressed)
                        {
                           if (initialObjectPosition.X < currentCursorPosition.X) rot.X -= RotateSpeed;
                           if (initialObjectPosition.X > currentCursorPosition.X) rot.X += RotateSpeed;
                        }
                        else
                        {
                           if (initialObjectPosition.X < currentCursorPosition.X) rot.Y -= RotateSpeed;
                           if (initialObjectPosition.X > currentCursorPosition.X) rot.Y += RotateSpeed;
                           if (initialObjectPosition.Y < currentCursorPosition.Y) rot.Z -= 1;
                           if (initialObjectPosition.Y > currentCursorPosition.Y) rot.Z += 1;
                        }
                        initialObjectPosition = currentCursorPosition;
                        SelectedNode->setRotation(rot);
                     }
                  }
                  else 
                  if (Mode == MODE_SCALE)
                  {
                     if (SelectedNode)
                     {
                        vector3df scale = SelectedNode->getScale();
                        position2di currentCursorPosition(device->getCursorControl()->getPosition()); 
                        if (initialObjectPosition.X > currentCursorPosition.X) 
                        {
                           scale.X -= ScaleSpeed;
                           scale.Y -= ScaleSpeed;
                           scale.Z -= ScaleSpeed;
                        }
                        if (initialObjectPosition.X < currentCursorPosition.X) 
                        {
                           scale.X += ScaleSpeed;
                           scale.Y += ScaleSpeed;
                           scale.Z += ScaleSpeed;
                        }
                        initialObjectPosition = currentCursorPosition;
                        SelectedNode->setScale(scale);
                     }
                  }

               } break;
            }
         }
      }
      return 0;
   }
};

int _tmain(int argc, _TCHAR* argv[])
{
   // create the device
   device =  createDevice( video::EDT_OPENGL, dimension2d<s32>(640, 480), 16, false, false, false, 0);
    if (!device) return 1;

   MyEventReceiver receiver;
    device->setEventReceiver(&receiver);

   // get a pointer to all of the irr items
   driver      = device->getVideoDriver();
    smgr      = device->getSceneManager();
    guienv      = device->getGUIEnvironment();
   CollMan      = smgr->getSceneCollisionManager();

   // add my little plug
   int x      = 10;
   int y      = 10;
   int width   = 100;
   int height   = 20;
   int space   = 5;

   guienv->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_QUIT,L"QUIT");
   y += height + space;
   guienv->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_TRANSLATE,L"Translate");
   y += height + space;
   guienv->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_ROTATE,L"Rotate");
   y += height + space;
   guienv->addButton(core::rect<s32>(x,y,x+width,y+height),0,ID_SCALE,L"Scale");

   // load a mesh
   IAnimatedMesh* mesh = smgr->getMesh("../media/sydney.md2");
    if (!mesh) return 1;

   // create a node
   IAnimatedMeshSceneNode* node = smgr->addAnimatedMeshSceneNode( mesh );
   if (node)
    {
      node->setMaterialFlag(EMF_LIGHTING, false);
      node->setMD2Animation(scene::EMAT_STAND);
      node->setMaterialTexture( 0, driver->getTexture("../media/sydney.bmp") );
    }

   // add a camera
   camera = smgr->addCameraSceneNode(0, vector3df(0,30,-40), vector3df(0,5,0));
   camera->setIsDebugObject(true);

   // run the scne
   while(Mode != MODE_QUIT)
   {
      device->run();
      driver->beginScene(true, true, SColor(255,100,101,140));
        smgr->drawAll();
        guienv->drawAll();
        driver->endScene();
    }

   // kill the device
   device->drop();

   return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值