osg,來寫一個控制魔方的小程序

前言

陸陸續續接觸osg有一段時間了. 也陸陸續續寫過很多小demo來做一些基礎的測試, 但是基本沒怎麼用在項目中,有的僅僅是顯示的部分.偶然間羣友就討論起了魔方來,其中一個小夥伴就問魔方的程序怎麼寫, 然後幾個小夥伴就本着無聊,就各自用自己知道的知識寫了一個玩, 我這個是c++osg的,其它的有個是.net的,還有一個是js的,本着學習記錄,說不定以後能回頭再完善些也好

展示

繪製出來的效果是這樣的
在這裏插入圖片描述
實際上爲了方便,將那個魔方可以任意調節節數
#define CUBEFSIZE 9;
在這裏插入圖片描述

功能羅列:

  1. 單個方塊的選擇
  2. 魔方面的選擇
  3. 魔方單個方塊的旋轉.
  4. 然後就是基本的旋轉等操作,

這裏如果選擇的話,我就讓他成爲白色.
在這裏插入圖片描述
在這裏插入圖片描述

這個是選擇面在這裏插入圖片描述

在這裏插入圖片描述
接下來讓選擇的小方塊旋轉.
在這裏插入圖片描述
旋轉一個90°
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

接下來是代碼部分

創建面->創建小方塊->創建魔方 是這個過程.

聲明的頭文件 command.h

//繪製面.
osg::ref_ptr<osg::Geode> CreateQuardFaceNode(osg::ref_ptr<osg::Vec3Array> v, osg::Vec4d color, osg::Vec3d normal);

//繪製小方塊
osg::ref_ptr<osg::Geode> createBox(osg::Vec4d front, osg::Vec4d back, osg::Vec4d left, osg::Vec4d right, osg::Vec4d top, osg::Vec4d bootom, float Sizewidth = 1.0f);

//繪製模塊.
osg::Node* creatCrub();

實現部分

osg::ref_ptr<osg::Geode> CreateQuardFaceNode(osg::ref_ptr<osg::Vec3Array> v, osg::Vec4d color, osg::Vec3d normal)
{

	//創建一個葉結點對象
	osg::ref_ptr<osg::Geode> geode = new osg::Geode;
	//創建一個幾何體對象
	osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;

	//設置頂點數據
	geom->setVertexArray(v);

	//創建顏色數組
	osg::ref_ptr<osg::Vec4Array> vc = new osg::Vec4Array;

	//設置顏色數組
	vc->push_back(color);
	geom->setColorArray(vc);
	//設置顏色綁定模式
	geom->setColorBinding(osg::Geometry::BIND_OVERALL);


	//創建法線數組
	osg::ref_ptr<osg::Vec3Array> nc = new osg::Vec3Array;
	//增加法線,幾何體頂點都是是在XOZ面上,所以法線是Y軸
	nc->push_back(normal);
	//設置法線
	geom->setNormalArray(nc);
	//設置法線的綁定方式爲全部節點
	/*BIND_OFF = 0,
		BIND_OVERALL = 1,
		BIND_PER_PRIMITIVE_SET = 2, 原始的.
		BIND_PER_VERTEX = 4 變色*/
	geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

	//添加圖元,繪圖基元爲四邊形,從第0個元素開始的四個元素,按照QUADS方式繪製四邊形
	geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));

	//添加到葉子節點中
	geode->addChild(geom);

	return geode.get();
}

osg::ref_ptr<osg::Geode> createBox(osg::Vec4d front, osg::Vec4d back, osg::Vec4d left, osg::Vec4d right, osg::Vec4d top, osg::Vec4d bootom, float Sizewidth)
{

	osg::ref_ptr<osg::Geode> root = new osg::Geode;

	//前
	{
		osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
		//逆時針添加數據
		v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
		v->push_back(osg::Vec3(Sizewidth, 0.0f, 0.0f));
		v->push_back(osg::Vec3(Sizewidth, 0.0f, Sizewidth));
		v->push_back(osg::Vec3(0, 0.0f, Sizewidth));
		root->addChild(CreateQuardFaceNode(v.get(), front, osg::Vec3d(0, -1, 0)).get());
	}



	//後
	{
		osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
		//逆時針添加數據
		v->push_back(osg::Vec3(0.0f, Sizewidth, 0.0f));
		v->push_back(osg::Vec3(Sizewidth, Sizewidth, 0.0f));
		v->push_back(osg::Vec3(Sizewidth, Sizewidth, Sizewidth));
		v->push_back(osg::Vec3(0.0f, Sizewidth, Sizewidth));
		root->addChild(CreateQuardFaceNode(v.get(), back, osg::Vec3d(0, 1, 0)).get());
	}

	//左
	{
		osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
		//逆時針添加數據
		v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
		v->push_back(osg::Vec3(0.0f, Sizewidth, 0.0f));
		v->push_back(osg::Vec3(0.0f, Sizewidth, Sizewidth));
		v->push_back(osg::Vec3(0.0f, 0.0f, Sizewidth));
		root->addChild(CreateQuardFaceNode(v.get(), left, osg::Vec3d(-1, 0, 0)).get());
	}

	//右
	{
		osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
		//逆時針添加數據
		v->push_back(osg::Vec3(Sizewidth, 0.0f, 0.0f));
		v->push_back(osg::Vec3(Sizewidth, Sizewidth, 0.0f));
		v->push_back(osg::Vec3(Sizewidth, Sizewidth, Sizewidth));
		v->push_back(osg::Vec3(Sizewidth, 0.0f, Sizewidth));
		root->addChild(CreateQuardFaceNode(v.get(), right, osg::Vec3d(1, 0, 0)).get());
	}

	//下
	{
		osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
		//逆時針添加數據
		v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
		v->push_back(osg::Vec3(0.0f, Sizewidth, 0.0f));
		v->push_back(osg::Vec3(Sizewidth, Sizewidth, 0.0f));
		v->push_back(osg::Vec3(Sizewidth, 0.0f, 0.0f));
		root->addChild(CreateQuardFaceNode(v.get(), top, osg::Vec3d(0, 0, -1)).get());
	}

	//上
	{
		osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array;
		//逆時針添加數據
		v->push_back(osg::Vec3(0.0f, 0.0f, Sizewidth));
		v->push_back(osg::Vec3(0.0f, Sizewidth, Sizewidth));
		v->push_back(osg::Vec3(Sizewidth, Sizewidth, Sizewidth));
		v->push_back(osg::Vec3(Sizewidth, 0.0f, Sizewidth));
		root->addChild(CreateQuardFaceNode(v.get(), bootom, osg::Vec3d(0, 0, 1)).get());
	}


	return root.release();
}

osg::Node* creatCrub()
{
	const int MagicCubeNumber = CUBEFSIZE;
	const float margin = 0.1;
	const float  coeff = 1.05f;

	osg::ref_ptr<osg::Group> crub = new osg::Group;

	for (int y = 0; y < MagicCubeNumber; y++)
	{
		for (int z = 0; z < MagicCubeNumber; z++)
		{
			for (int x = 0; x < MagicCubeNumber; x++)
			{
				osg::ref_ptr<osg::PositionAttitudeTransform> position = new osg::PositionAttitudeTransform();
				osg::ref_ptr<osg::MatrixTransform> matexiTrans = new osg::MatrixTransform();
				osg::ref_ptr<osg::Switch> _switch = new osg::Switch;
				osg::ref_ptr<osg::Geode> box = createBox(osg::Vec4d(1.0, 0, 0, 1), osg::Vec4d(1.0, 0, 0, 1), osg::Vec4d(0.0, 1, 0, 1), osg::Vec4d(0.0, 1, 0, 1), osg::Vec4d(0.0, 0, 1, 1), osg::Vec4d(0.0, 0, 1, 1)).get();
				osg::ref_ptr<osgFX::Scribe> scrip = new osgFX::Scribe();
				scrip->addChild(createBox(osg::Vec4d(1.0, 0, 0, 1), osg::Vec4d(1.0, 0, 0, 1), osg::Vec4d(0.0, 1, 0, 1), osg::Vec4d(0.0, 1, 0, 1), osg::Vec4d(0.0, 0, 1, 1), osg::Vec4d(0.0, 0, 1, 1)).get());
				_switch->addChild(box.get(), true);
				_switch->addChild(scrip.get(), false);
				_switch->setName("switch_node");
				matexiTrans->addChild(_switch.get());
				ostringstream str;
				str << "boxName_" << x << "_" << y << "_" << z;
				double xOffset = x * coeff + margin;
				double yoffset = y * coeff + margin;
				double zoffset = z * coeff + margin;
				osg::Matrix mtrix = matexiTrans->getMatrix();
				mtrix *= mtrix.translate(osg::Vec3d(xOffset, yoffset, zoffset));
				matexiTrans->setMatrix(mtrix);
				position->setName(str.str());
				position->addChild(matexiTrans.get());
				crub->addChild(position.get());

			}
		}
	}

	return crub.release();
}

這裏是主函數

int main()
{

	std::cout << "main_20_6" << std::endl;
	osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
	{
		//設置圖形環境特性.
		osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
		traits->x = WindPositionX;
		traits->y = WindPositionY;
		traits->width = WindRecWidth;
		traits->height = WindRecHeight;
		traits->windowDecoration = true; //是否支持窗口擴展功能.
		traits->doubleBuffer = true;//是否支持窗口縮放.
		traits->sharedContext = 0;//共享上下文.

		//創建圖形環境特性.
		osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits.get());
		if (gc.valid())
		{
			//創建成功.
			//清楚窗口顏色以及清除顏色和深度緩存.
			gc->setClearColor(osg::Vec4f(0.2f, 0.2f, 0.6f, 1.0f));
			gc->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
		}
		else
		{
			//這個圖形環境沒有被創建成功.
		}

		//根據分辨率確定合適的投影來保證顯示的圖形不變形.
		double fovy, aspectRatio, zNear, zFar;
		viewer->getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
		double newAspectRatio = double(traits->width / traits->height);
		double aspectRatioChange = newAspectRatio / aspectRatio;
		if (aspectRatioChange != 1.0)
		{
			//設置投影矩陣.
			viewer->getCamera()->getProjectionMatrix() *= osg::Matrix::scale(1.0 / aspectRatioChange, 1.0, 1.0);
		}

		viewer->getCamera()->setGraphicsContext(gc.get());
		viewer->getCamera()->setViewport(0, 0, traits->width, traits->height);
	}

	viewer->addEventHandler(new CRubPickHandler(viewer.get()));


	osg::ref_ptr<osg::Group> _box = new osg::Group();
	_box->setName("GroupMast");
	osg::ref_ptr<osg::Node> crub = creatCrub();
	if (crub)
	{
		crub->setName("crub");
		_box->addChild(crub.get());
	}

	osgUtil::Optimizer optimizer;
	optimizer.optimize(_box.get());
	viewer->setSceneData(_box.get());
	viewer->realize();
	viewer->run();
	return 0;

}

到這一步,就可以讓其顯示了

這裏添加一個選擇器併爲其賦予選擇,高亮,旋轉等基礎功能

class CRubPickHandler : public osgGA::GUIEventHandler
{
public:


	//事件處理函數
	bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
	{
		if (!view) return false;

		switch (ea.getEventType())
		{
			//鼠標按下
		case(osgGA::GUIEventAdapter::PUSH):
		{
			//更新鼠標位置
			_mx = ea.getX();
			_my = ea.getY();
			break;
		}
		case(osgGA::GUIEventAdapter::RELEASE):
		{
			if (_mx == ea.getX() && _my == ea.getY())
			{
				//執行對象選取
				//pick(view.get(), ea.getX(), ea.getY());
			}
			break;
		}
		case(osgGA::GUIEventAdapter::KEYDOWN):
		{

			if (ea.getKey() == 'w' || ea.getKey() == 'W')
			{
				//上
				BoxPosition.z()++;
				CheckBoxPosition();
				std::cout << BoxPosition.x() << " " << BoxPosition.y() << " " << BoxPosition.z() << std::endl;
			    UpdataSigleBox(BoxPosition);
				return true;

			}
			else if (ea.getKey() == 's' || ea.getKey() == 'S')
			{
				//下
				BoxPosition.z()--;
				CheckBoxPosition();
				UpdataSigleBox(BoxPosition);
				return true;

			}
			else if (ea.getKey() == 'a' || ea.getKey() == 'A')
			{

				//左
				BoxPosition.x()--;
				CheckBoxPosition();
			    UpdataSigleBox(BoxPosition);
				return true;

			}
			else if (ea.getKey() == 'd' || ea.getKey() == 'D')
			{

				//右
				BoxPosition.x()++;
				CheckBoxPosition();
			    UpdataSigleBox(BoxPosition);
				return true;
			}
			else if (ea.getKey() == 'x' || ea.getKey() == 'X')
			{
				//前進
				BoxPosition.y()++;
				CheckBoxPosition();
				getCurrentObj = UpdataSigleBox(BoxPosition);
				return true;
			}
			else if (ea.getKey() == 'q' || ea.getKey() == 'Q')
			{
				//選中行
				UpdataSigleBox(BoxPosition);
				std::vector<osg::Vec3d> positionList = getRowVects(BoxPosition);
				setSelctionsBox(positionList);
			}
			else if (ea.getKey() == 'e' || ea.getKey() == 'E')
			{
				//選中列
				UpdataSigleBox(BoxPosition);
				std::vector<osg::Vec3d> positionList = getColVects(BoxPosition);
				setSelctionsBox(positionList);

				//osg::Vec3d centerBoxPosition = getPositionsCenter(positionList);
				//osg::Node* centerBox = getNode(centerBoxPosition);
				//addNode2View(centerBox);
				//std::cout << centerBoxPosition.x() << "  " << centerBoxPosition.y() << " " << centerBoxPosition.z() << std::endl;
				return true;
			}
			else if (ea.getKey() == ea.KEY_Up) {
				//旋轉.
				std::cout << "上---旋轉....." << std::endl;
				getCurrentObj = getNode(BoxPosition);
				RotateNode2View(getCurrentObj , 90);
				return true;

			}
			else if (ea.getKey() == ea.KEY_Down)
			{
				//旋轉.
				std::cout << "下---旋轉....." << std::endl;
				getCurrentObj = getNode(BoxPosition);
				RotateNode2View(getCurrentObj, -90);
				return true;
			}
			else if (ea.getKey() == ea.KEY_Left)
			{
				//左旋轉
				std::cout << "左---旋轉....." << std::endl;
				getCurrentObj = getNode(BoxPosition);
				RotateNode2View(getCurrentObj, -90,osg::Vec3d(0,1,0));
				return true;
			}
			else if (ea.getKey() == ea.KEY_Right)
			{
				//右旋轉
				std::cout << "右---旋轉....." << std::endl;
				getCurrentObj = getNode(BoxPosition);
				RotateNode2View(getCurrentObj, 90, osg::Vec3d(0, 1, 0));
				return true;
			}

			CheckBoxPosition();
			break;
		}

		default:
			break;
		}
		return false;
	}

	//對象選取事件處理器
	void pick(osg::ref_ptr<osgViewer::View> view, float x, float y)
	{
		osgUtil::LineSegmentIntersector::Intersections intersections;

		if (view->computeIntersections(x, y, intersections))
		{
			osgUtil::LineSegmentIntersector::Intersections::iterator inter = intersections.begin();//獲取第一個點

			const osg::NodePath& nodePath = inter->nodePath;//獲取第一個交點的Path
			for (int i = 1; i < nodePath.size() - 1; i++) {
				std::string name = nodePath[i]->getName();
				std::cout << name << std::endl;
			}
		}

	}

protected:

	//根據映射,找出節點位置.
	std::map<osg::Vec3d, std::string> NodeMap;
	const int CuBSize = CUBEFSIZE;
	inline void initNodeMap()
	{
		for (int y = 0; y < CuBSize; y++)
		{
			for (int z = 0; z < CuBSize; z++)
			{
				for (int x = 0; x < CuBSize; x++)
				{
					ostringstream str;
					str << "boxName_" << x << "_" << y << "_" << z;
					NodeMap.insert(std::map<osg::Vec3d, std::string>::value_type(osg::Vec3d(x, y, z), str.str()));
				}
			}
		}
	}

	//依據節點,獲取當前的Node
	osg::ref_ptr<osg::Node> getNode(osg::Vec3d position, bool isOPenMonopLisze = false)
	{
		osg::ref_ptr <osg::Node> GetNodeObj = nullptr;
		//循環遍歷節點.
		std::map<osg::Vec3d, std::string>::iterator iter;
		iter = NodeMap.find(position);
		std::string  findNodeName;
		if (iter != NodeMap.end())
		{
			findNodeName = iter->second;
		}
		else
		{
			return nullptr;
		}

		osg::ref_ptr<osg::Group> root = { nullptr };
		if (view)
		{
			root = view->getSceneData()->asGroup();
		}
		std::cout << root->getName() << std::endl;
		//將當前對象中的boxName_0_0_0, 設置爲高亮..
		if (root)
		{
			for (int i = 0; i < root->getNumChildren(); i++)
			{
				osg::Node* temp = root->getChild(i);
				if (temp)
				{
					std::cout << temp->getName() << std::endl;
					if (temp->getName() == "crub")
					{
						osg::Group *mgroup = temp->asGroup();
						if (mgroup)
						{
							std::cout << "curb: childNumbers: " << mgroup->getNumChildren() << std::endl;
							for (int j = 0; j < mgroup->getNumChildren(); j++)
							{
								GetNodeObj = mgroup->getChild(j)->asGroup();
								if (GetNodeObj)
								{
									if (isOPenMonopLisze == false)
									{
										if (GetNodeObj->getName().compare(findNodeName.c_str()) == 0)
										{
											std::cout << "find Node: " << j << "  " << GetNodeObj->getName() << std::endl;
											break;
										}
									}
									else
									{
										if (GetNodeObj->getName().compare(findNodeName.c_str()) == 0)
										{
											std::cout << "getScribe: " << j << "  " << GetNodeObj->getName() << std::endl;
											UpData(GetNodeObj, false);
										}
										else
										{
											//顯示原色.
											UpData(GetNodeObj, true);
										}
									}

								}

							}
						}

					}
				}

			}
		}

		return GetNodeObj.release();

	}

	osg::ref_ptr<osg::Node>  UpdataSigleBox(osg::Vec3d &position)
	{
		return  getNode(position, true).release();
	}

	//選擇指定的節點
	void setSelctionsBox(std::vector<osg::Vec3d> &PositionList)
	{
		for (int i = 0; i < PositionList.size(); i++)
		{
			osg::Node* mNode = getNode(PositionList[i], false);
			if (mNode)
			{
				UpData(mNode, false);
			}
		}
	}

	//獲取當前節點的列截面所有的Node
	std::vector<osg::Vec3d> getColVects(osg::Vec3d position)
	{
		//查找所有x軸一樣的點.
		std::vector<osg::Vec3d> positionLists;
		std::map<osg::Vec3d, std::string>::iterator iter = NodeMap.begin();
		for (; iter != NodeMap.end(); ++iter)
		{
			if (iter->first.x() == position.x())
			{
				positionLists.push_back(iter->first);
			}
		}

		return positionLists;
	}


	//獲取當前節點的行界面所有的Node
	std::vector<osg::Vec3d> getRowVects(osg::Vec3d position)
	{
		//查找所有x軸一樣的點.
		std::vector<osg::Vec3d> positionLists;
		std::map<osg::Vec3d, std::string>::iterator iter = NodeMap.begin();
		for (; iter != NodeMap.end(); ++iter)
		{
			if (iter->first.z() == position.z())
			{
				positionLists.push_back(iter->first);
			}
		}

		return positionLists;

	}


	//替換當前子節點爲高亮顯示的節點.
	void UpData(osg::Node* CurrentNode, bool status = false)
	{
		//沒起作用....
		if (CurrentNode)
		{
			osg::Transform* transp = CurrentNode->asTransform();
			if (transp)
			{
				osg::PositionAttitudeTransform * position = transp->asPositionAttitudeTransform();
				if (position)
				{
					for (int i = 0; i < position->getNumChildren(); i++)
					{
						osg::Transform * transForm = position->getChild(i)->asTransform();
						if (transForm)
						{
							//轉換成matrixTransForm
							osg::MatrixTransform *matrixTrans = transForm->asMatrixTransform();
							if (matrixTrans)
							{
								for (int j = 0; j < matrixTrans->getNumChildren(); j++)
								{
									osg::Switch* _switch = matrixTrans->getChild(j)->asSwitch();
									if (_switch)
									{
										std::cout << "updata: " << _switch->getName() << std::endl;
										_switch->setValue(0, status);
										_switch->setValue(1, !status);

									}
								}

							}

						}

					}
				}
			}

		}
	}

	void CheckBoxPosition()
	{
		int cruBNumber = CUBEFSIZE - 1;
		if (BoxPosition.x() > cruBNumber) BoxPosition.x() = cruBNumber;
		else if (BoxPosition.x() < 0) BoxPosition.x() = 0;

		if (BoxPosition.y() > cruBNumber) BoxPosition.y() = 0;
		else if (BoxPosition.y() < 0) BoxPosition.y() = cruBNumber;

		if (BoxPosition.z() > cruBNumber) BoxPosition.z() = cruBNumber;
		else if (BoxPosition.z() < 0) BoxPosition.z() = 0;
	}

	//獲取當前選中面板的中心點.
	osg::Vec3d getPositionsCenter(std::vector<osg::Vec3d>& positions)
	{
		//這裏要依據獲取到的模板數目.計算其中心點的座標.
		osg::Vec3d center = { 0,0,0 };
		osg::Vec3 cecnterAixyzNumbers = { 0,0,0 };
		for (int i = 0; i < positions.size(); i++)
		{
			center.x() += positions[i].x();
			center.y() += positions[i].y();
			center.z() += positions[i].z();
		}

		return center / positions.size();
	}

	//在場景中添加模型.
	void RotateNode2View(osg::Node* _node, double angle, osg::Vec3 coordinate = osg::Vec3(1, 0, 0))
	{
		if (_node)
		{
			osg::Transform* trans = _node->asTransform();
			if (trans)
			{
				std::cout << "rotate:   " << trans->getName() << std::endl;

				osg::PositionAttitudeTransform *position = trans->asPositionAttitudeTransform();
				if (position)
				{

					//
					osg::Transform* trans_matrix = position->getChild(0)->asTransform();
					if (trans_matrix)
					{
						osg::ref_ptr<osg::MatrixTransform> matrixTrans = trans_matrix->asMatrixTransform();

						//獲取到當前旋轉矩陣下的要旋轉的模型物體.
						osg::Switch* getBox = { nullptr };
						for (int i = 0; i < matrixTrans->getNumChildren(); i++)
						{
							getBox = matrixTrans->getChild(i)->asSwitch();
						}

						if (getBox)
						{
							osg::Matrix originPos = matrixTrans->getMatrix();//獲取當前的矩陣.
							osg::Vec3d center = getBox->getBound().center();

							osg::Node* pParentNode;
							osg::MatrixTransform *pParent;

							//獲取當前模型在世界座標系中的矩陣以及位置信息.
							pParentNode = getBox->getParent(0);
							pParent = dynamic_cast<osg::MatrixTransform*>(pParentNode);
							while (pParent != nullptr)
							{
								originPos = originPos * pParent->getMatrix();
								pParentNode = pParent->getParent(0);
								pParent = dynamic_cast<osg::MatrixTransform*>(pParentNode);
							}

							//逆矩陣
							osg::Matrixd inverseALL = matrixTrans->getMatrix()*osg::Matrixd::inverse(originPos);

							//獲取中心點在世界座標系中的位置.
							osg::Vec3d originCenter = center * originPos;

							//開始旋轉,並設置信息.
							matrixTrans->setMatrix(originPos*osg::Matrixd::translate(-originCenter));
							matrixTrans->setMatrix(matrixTrans->getMatrix()*osg::Matrixd::rotate(osg::DegreesToRadians(angle), coordinate.x(), coordinate.y(), coordinate.z()));
							matrixTrans->setMatrix(matrixTrans->getMatrix()*osg::Matrixd::translate(originCenter)*inverseALL);
						}
					}
				}

			}
		}

	}

	//將選中的節點,放入選擇器中.
	void pushBackSelector(osg::Node* crubFace)
	{
		/*	if (crubFace && _CrubSelection && dragger)
			{
				if (_CrubSelection->getNumChildren() > 0)
				{
					while(_CrubSelection->getNumChildren() > 0)
					{
						_CrubSelection->removeChild(_CrubSelection->getChild(0));
					}

					return;
				}

				_CrubSelection->addChild(crubFace);
				float scale = crubFace->getBound().radius()*1.5;
				dragger->setMatrix(osg::Matrix::scale(scale*0.5, scale*0.5, scale*0.5)*osg::Matrix::translate(crubFace->getBound().center()));
				dragger->addTransformUpdating(_CrubSelection);
				osg::Group*group = view->getSceneData()->asGroup();
				if (group)
				{
					group->addChild(dragger);
				}

			}

	*/
	}

public:

	CRubPickHandler(osgViewer::View *vt) :
		_mx(0.0f),
		_my(0.0f)
	{
		view = vt;
		initNodeMap();

		outline->setColor(osg::Vec4(1, 1, 0, 1));
		outline->setWidth(8);

	}

	~CRubPickHandler()
	{

	}

	//得到鼠標的位置
	float _mx;
	float _my;
	osg::ref_ptr<osgViewer::View> view = { nullptr };
	osg::Vec3d BoxPosition = { 0,0,0 };
	osg::ref_ptr<osgFX::Outline> outline = new osgFX::Outline();
	osg::Node* getCurrentObj = { nullptr };

};

這個魔方只是一個粗製的版本,很多地方需要雕琢,有很多不完善的地方;

整個魔方的操作,注意一些旋轉操作細節,旋轉中,已經設計好任意點旋轉了,所以整個魔方旋轉基調已經定下了;

關於如何判斷魔方是否已經拼好。實際上,每個方塊的面有一個標識,而魔方中的每個小方塊,也有自己三維座標,到時候,判斷小方塊的面的法向的朝向,是否是一致(奇葩想法…額,實在不行, 三視圖直接判斷顏色…)

以後有機會再完善吧, 有什麼不懂的,可以留言一起討論

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章