148 lines
4.7 KiB
C++
148 lines
4.7 KiB
C++
#include "myNodeVisitor.h"
|
||
#include "mainwindow.h"
|
||
|
||
#include <osg/Texture2D>
|
||
#include <osg/ProxyNode>
|
||
#include <osg/PagedLOD>
|
||
#include <osgDB/ReadFile>
|
||
#include <osgDB/WriteFile>
|
||
|
||
myNodeVisitor::myNodeVisitor()
|
||
{
|
||
opt->setOptionString("WriteImageHint=IncludeFile");
|
||
}
|
||
|
||
void myNodeVisitor::apply(osg::Geode &node)
|
||
{
|
||
// 遍历Geode里面的所有Geometry,即形状(点、线、面)
|
||
for(uint i = 0; i<node.getNumDrawables(); i++){
|
||
osg::Geometry* pGeo = node.getDrawable(i)->asGeometry();
|
||
if(pGeo){
|
||
osg::Vec3Array* vertex = dynamic_cast<osg::Vec3Array*>(pGeo->getVertexArray());
|
||
if (!vertex){
|
||
continue;
|
||
}
|
||
for (int i = 0; i < vertex->size(); i++){
|
||
// 对于满足条件的点
|
||
int index = pointsNearVertex((*vertex)[i]);
|
||
if (index != -1)
|
||
{
|
||
(*vertex)[i].z() = vertexArray->at(index).z();
|
||
affected = true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (affected && !node.getName().empty()){
|
||
// 和PagedLOD的处理方式一致
|
||
newFileName = QString::fromStdString(node.getName()).split('.').first() + "~.osgb";
|
||
node.accept(*tv);
|
||
node.setName(newFileName.toStdString());
|
||
// 写文件
|
||
osgDB::writeNodeFile(node, (workingDir + '/' + newFileName).toStdString(), opt);
|
||
childAffected = true;
|
||
}
|
||
}
|
||
|
||
void myNodeVisitor::apply(osg::Group &node)
|
||
{
|
||
bool groupAffected = false;
|
||
for(uint i = 0; i<node.getNumChildren(); i++){
|
||
childAffected = false;
|
||
node.getChild(i)->accept(*this);
|
||
if(childAffected){
|
||
groupAffected = true;
|
||
}
|
||
}
|
||
|
||
if(groupAffected && !node.getName().empty()){
|
||
// 和PagedLOD的处理方式一致
|
||
newFileName = QString::fromStdString(node.getName()).split('.').first() + "~.osgb";
|
||
node.accept(*tv);
|
||
node.setName(newFileName.toStdString());
|
||
// 写文件
|
||
osgDB::writeNodeFile(node, (workingDir + '/' + newFileName).toStdString(), opt);
|
||
childAffected = true;
|
||
}
|
||
}
|
||
|
||
void myNodeVisitor::apply(osg::PagedLOD &node)
|
||
{
|
||
affected = false;
|
||
childAffected = false;
|
||
for(uint i = 0; i < node.getNumChildren(); i++){
|
||
// 这个遍历过程可能会修改文件
|
||
node.getChild(i)->accept(*this);
|
||
}
|
||
|
||
// // 使用affected作为初步判断,以尽可能地减少计算量, 非affected文件都不会被修改
|
||
// if(!affected && ! childAffected){
|
||
// return;
|
||
// }
|
||
|
||
// 如果真的被修改了文件,那么,
|
||
workingDir = QString::fromStdString(node.getDatabasePath());
|
||
// for(uint i = 0; i < node.getNumFileNames(); i++){
|
||
for(uint i = 1; i < node.getNumFileNames(); i++){
|
||
// 遍历这个LOD文件中的所有子文件,即金字塔中更精细的那一层,他们也要改
|
||
childAffected = false;
|
||
// 读文件以继续遍历
|
||
osg::ref_ptr<osg::Node> fileNode = osgDB::readNodeFile(workingDir.toStdString() + '/' + node.getFileName(i));
|
||
if(!fileNode.valid()){
|
||
continue;
|
||
}
|
||
// 将fileNode和文件名链接在一起,这样当节点被修改时,可以及时更新对应的文件
|
||
fileNode->setName(node.getFileName(i));
|
||
// 两个遍历器都要遍历
|
||
fileNode->accept(*tv);
|
||
fileNode->accept(*this);
|
||
if(childAffected){
|
||
//更改文件名链接
|
||
node.setFileName(i, newFileName.toStdString());
|
||
// 此时也应该相应地修改pLOD对应的文件
|
||
}
|
||
}
|
||
|
||
if(!node.getName().empty()){
|
||
newFileName = QString::fromStdString(node.getName()).split('.').first() + "~.osgb";
|
||
node.accept(*tv);
|
||
node.setName(newFileName.toStdString());
|
||
// 写文件
|
||
osgDB::writeNodeFile(node, (workingDir + '/' + newFileName).toStdString(), opt);
|
||
}
|
||
|
||
// 作为别人的儿子,文件被修改了
|
||
childAffected = true;
|
||
}
|
||
|
||
bool myNodeVisitor::pointInPolygon(osg::Vec3 &point)
|
||
{
|
||
for(osg::ref_ptr<osg::Vec3Array> boundary: boundaryList){
|
||
int i, j, nvert = boundary->size();
|
||
bool c = false;
|
||
|
||
// 射线法
|
||
for (i = 0, j = nvert - 1; i < nvert; j = i++) {
|
||
if (((boundary->at(i).y() >= point.y()) != (boundary->at(j).y() >= point.y())) &&
|
||
(point.x() <= (boundary->at(j).x() - boundary->at(i).x()) * (point.y() - boundary->at(i).y()) / (boundary->at(j).y() - boundary->at(i).y()) + boundary->at(i).x())
|
||
)
|
||
c = !c;
|
||
}
|
||
if(c && point.z() > boundary->at(0).z()){
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
|
||
int myNodeVisitor::pointsNearVertex(osg::Vec3 &point)
|
||
{
|
||
for(int i = 0; i < vertexArray->size(); i++){
|
||
if(pow(point.x() - vertexArray->at(i).x(), 2) + pow(point.y() - vertexArray->at(i).y(), 2) < 4 && point.z() > vertexArray->at(i).z()){
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|