前言
陆陆续续接触osg有一段时间了. 也陆陆续续写过很多小demo来做一些基础的测试, 但是基本没怎么用在项目中,有的仅仅是显示的部分.偶然间群友就讨论起了魔方来,其中一个小伙伴就问魔方的程序怎么写, 然后几个小伙伴就本着无聊,就各自用自己知道的知识写了一个玩, 我这个是c++osg的,其它的有个是.net的,还有一个是js的,本着学习记录,说不定以后能回头再完善些也好
展示
绘制出来的效果是这样的
实际上为了方便,将那个魔方可以任意调节节数
#define CUBEFSIZE 9;
功能罗列:
- 单个方块的选择
- 魔方面的选择
- 魔方单个方块的旋转.
- 然后就是基本的旋转等操作,
这里如果选择的话,我就让他成为白色.
这个是选择面
接下来让选择的小方块旋转.
旋转一个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 };
};
这个魔方只是一个粗制的版本,很多地方需要雕琢,有很多不完善的地方;
整个魔方的操作,注意一些旋转操作细节,旋转中,已经设计好任意点旋转了,所以整个魔方旋转基调已经定下了;
关于如何判断魔方是否已经拼好。实际上,每个方块的面有一个标识,而魔方中的每个小方块,也有自己三维坐标,到时候,判断小方块的面的法向的朝向,是否是一致(奇葩想法…额,实在不行, 三视图直接判断颜色…)
以后有机会再完善吧, 有什么不懂的,可以留言一起讨论