在利用OSG节点文件导入两个不同类型的模型文件时,其在OSG中的世界坐标系不一定在一个地方,也就无法在同一视图中同时显示。需要进行位置变换和矩阵变换使多个模型在同一视图中显示。主要思路是通过利用包围盒来查看各模型所在世界坐标系中的位置,之后进行变换。当同时利用位置变换和矩阵变换时,需要按照root->矩阵变换->位置变换->模型节点的形式。先通过位置变换设置原点进行缩放,再通过矩阵变换进行平移和旋转。主要参考代码如下:
#include<osgViewer/Viewer>
#include<osg/Group>
#include<osgDB/ReadFile>
#include<osgUtil/Optimizer>
#include<osgDB/FileUtils>
#include<osgDB/ReadFile>
#include<osg/PositionAttitudeTransform>
#include<osg/Node>
#include<osg/ComputeBoundsVisitor>
#include<osg/MatrixTransform>
#include<iostream>
#include<osg/lightModel>
int main()
{
osg::ref_ptr<osg::Node> topNode = osgDB::readNodeFile("模型1文件");
osg::ref_ptr<osg::Node> bottomNode = osgDB::readNodeFile(“模型2文件");
osg::ComputeBoundsVisitor cbvtop;
topNode->accept(cbvtop);
osg::BoundingBox topBox = cbvtop.getBoundingBox();
std::cout<<"模型1坐标:"<<topBox.xMin()<<","<<topBox.xMax()<<","<<topBox.yMin()<<","<<topBox.yMax()<<","<<topBox.zMin()<<","<<topBox.zMax()<<std::endl;
osg::ref_ptr<osg::PositionAttitudeTransform> topPat = new
osg::PositionAttitudeTransform();
topPat->setPivotPoint(osg::Vec3(topBox.center().x(),topBox.center().y(),topBox.center().z()));
//设置按照X坐标以0.0025的大小的结果进行等比缩放,可任意根据需要修改
topPat->setScale(osg::Vec3(0.00125/(topBox.xMax()-
topBox.xMin()),0.00125/(topBox.xMax()-topBox.xMin()),0.00125/(topBox.xMax()-
topBox.xMin())));
topPat->addChild(topNode);
osg::ComputeBoundsVisitor cbvtopPat;
topPat->accept(cbvtopPat);
osg::BoundingBox topPatBox = cbvtopPat.getBoundingBox();
std::cout<<"位置变换坐标:"<<topPatBox.xMin()<<","<<topPatBox.xMax()<<","
<<topPatBox.yMin()<<","<<topPatBox.yMax()<<","<<topPatBox.zMin()<<","<<topPatBox.zMax()<<std::endl;
osg::ref_ptr<osg::MatrixTransform> topMt = new osg::MatrixTransform;
osg::Matrix m1;
m1.makeTranslate(osg::Vec3(-topPatBox.center().x(),-topPatBox.center().y(),-
topPatBox.center().z()));
topMt->setMatrix(m1);
topMt->addChild(topPat);
osg::ComputeBoundsVisitor cbvtopMt;
topMt->accept(cbvtopMt);
osg::BoundingBox topMtBox = cbvtopMt.getBoundingBox();
std::cout<<"矩阵变换坐标:"<<topMtBox.xMin()<<","<<topMtBox.xMax()<<","<<topMtBox.yMin()<<","<<topMtBox.yMax()<<","<<topMtBox.zMin()<<","<<topMtBox.zMax()<<std::endl;
osg::ComputeBoundsVisitor cbvbot;
bottomNode->accept(cbvbot);
osg::BoundingBox botBox = cbvbot.getBoundingBox();
std::cout<<"模型2坐标:"<<botBox.xMin()<<","<<botBox.xMax()<<","<<botBox.yMin()<<","<<botBox.yMax()<<","<<botBox.zMin()<<","<<botBox.zMax()<<std::endl;
osg::ref_ptr<osg::PositionAttitudeTransform> botPat = new
osg::PositionAttitudeTransform();
botPat->setPivotPoint(osg::Vec3(botBox.center().x(),botBox.center().y(),botBox.center().z()));
//设置按照X坐标以0.02的大小的结果进行等比缩放,可任意根据需要修改
botPat->setScale(osg::Vec3(0.01/(botBox.xMax()-
botBox.xMin()),0.01/(botBox.xMax()-botBox.xMin()),0.01/(botBox.xMax()-
botBox.xMin())));
botPat->addChild(bottomNode);
osg::ComputeBoundsVisitor cbvbotPat;
botPat->accept(cbvbotPat);
osg::BoundingBox botPatBox = cbvbotPat.getBoundingBox();
std::cout<<"位置变换坐标:"<<botPatBox.xMin()<<","<<botPatBox.xMax()<<","
<<botPatBox.yMin()<<","<<botPatBox.yMax()<<","<<botPatBox.zMin()<<","<<botPatBox.zMax()<<std::endl;
osg::ref_ptr<osg::MatrixTransform> botMt = new osg::MatrixTransform;
osg::Matrix m2;
m2.makeTranslate(osg::Vec3(-botPatBox.center().x(),-botPatBox.center().y(),-botPatBox.center().z()-(botPatBox.zMax() - topPatBox.zMin())));
botMt->setMatrix(m2);
botMt->addChild(botPat);
osg::ComputeBoundsVisitor cbvbotMt;
botMt->accept(cbvbotMt);
osg::BoundingBox botMtBox = cbvbotMt.getBoundingBox();
std::cout<<"矩阵变换坐标:"<<botMtBox.xMin()<<","<<botMtBox.xMax()<<","<<botMtBox.yMin()<<","<<botMtBox.yMax()<<","<<botMtBox.zMin()<<","<<botMtBox.zMax()<<std::endl;
osg::Group* root = new osg::Group;
root->addChild(topMt.get());
root->addChild(botMt.get());
osgViewer::Viewer viewer;
osgUtil::Optimizer optimizer;
optimizer.optimize(root);
viewer.setSceneData(root);
viewer.setUpViewInWindow(100, 100, 800, 600);
return viewer.run();
}
最后控制台输出的矩阵变换坐标和位置变换坐标是一样的。