- 编译osgOcean和fftss
osgOcean是海洋仿真,可以设置风速,光反射等,缺点是不可与osgEarth相结合,用sundog中的海洋与云可以与osgearth结合。
osgOcean为成熟的库,接口简单方便。
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <osgOcean/OceanScene>
#include <osgOcean/FFTOceanSurface>
#include <osgViewer/ViewerEventHandlers>
#include <osg/TextureCubeMap>
#include <osg/MatrixTransform>
#include "SkyDome.h"
#include "SphereSegment.h"
osg::ref_ptr<osg::TextureCubeMap> loadMap() {
osg::ref_ptr<osg::TextureCubeMap> cubeMap = new osg::TextureCubeMap;
cubeMap->setInternalFormat(GL_RGB);
cubeMap->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR);
cubeMap->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
cubeMap->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
cubeMap->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_X, osgDB::readImageFile("resources/textures/west.png"));
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_X, osgDB::readImageFile("resources/textures/east.png"));
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_Y, osgDB::readImageFile("resources/textures/up.png"));
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_Y, osgDB::readImageFile("resources/textures/down.png"));
cubeMap->setImage(osg::TextureCubeMap::NEGATIVE_Z, osgDB::readImageFile("resources/textures/south.png"));
cubeMap->setImage(osg::TextureCubeMap::POSITIVE_Z, osgDB::readImageFile("resources/textures/north.png"));
return cubeMap;
}
class CameraTrackCallback : public osg::NodeCallback
{
public:
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if (nv->getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
{
osgUtil::CullVisitor* cv = static_cast<osgUtil::CullVisitor*>(nv);
osg::Vec3f centre, up, eye;
cv->getRenderStage()->getCamera()->getViewMatrixAsLookAt(eye, centre, up);
osg::MatrixTransform* mt = static_cast<osg::MatrixTransform*>(node);
mt->setMatrix(osg::Matrix::translate(eye.x(), eye.y(), mt->getMatrix().getTrans().z()));
}
traverse(node, nv);
}
};
class BoatPositionCallback :public osg::NodeCallback {
public:
BoatPositionCallback(osgOcean::OceanScene * scene) {
_scene = scene;
}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) {
if (nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR)
{
osg::MatrixTransform * mat = dynamic_cast<osg::MatrixTransform*>(node);
if (mat) {
osg::Matrix matrix = osg::computeLocalToWorld(nv->getNodePath());
osg::Vec3d pos = matrix.getTrans();
osg::Vec3f normal;
float height = _scene->getOceanSurfaceHeightAt(pos[0], pos[1], &normal);
static float a = 0;
matrix.makeTranslate(osg::Vec3(pos[0] + cosf(a), pos[1] + sinf(a), height));
osg::Matrixf rot;
rot.makeIdentity();
rot.makeRotate(normal.x(), osg::X_AXIS,
normal.y(), osg::Y_AXIS,
a, osg::Z_AXIS);
a += 0.005;
matrix = rot * matrix;
mat->setMatrix(matrix);
}
}
}
private:
osgOcean::OceanScene * _scene;
};
int main()
{
osg::ref_ptr<osgViewer::Viewer>viewer = new osgViewer::Viewer;
viewer->setUpViewInWindow(150, 150, 1024, 768, 0);
osg::ref_ptr<osgOcean::FFTOceanSurface>surface = new osgOcean::FFTOceanSurface(64, 256, 17, osg::Vec2(1.1f, 1.1f), 12, 10, 0.8, 1e-8, true, 2.5, 20.0, 256);
osg::ref_ptr<osgOcean::OceanScene> scene = new osgOcean::OceanScene(surface.get());
//天空盒
osg::ref_ptr<osg::TextureCubeMap> cubeMAP = loadMap();
osg::ref_ptr<SkyDome> sky = new SkyDome(1900, 16, 16, cubeMAP.get());
sky->setNodeMask(scene->getReflectedSceneMask() | scene->getNormalSceneMask());
osg::MatrixTransform * mat = new osg::MatrixTransform;
mat->setDataVariance(osg::Object::DYNAMIC);
mat->setMatrix(osg::Matrixf::translate(osg::Vec3d(0, 0, 0)));
mat->addChild(sky.get());
mat->setCullCallback(new CameraTrackCallback);
scene->addChild(mat);
//雾效和反射
scene->setAboveWaterFog(0.0012, osg::Vec4(0.67, 0.87, 0.97, 1.0));
scene->enableReflections(true);
surface->setEnvironmentMap(cubeMAP);
//水花
surface->setFoamBottomHeight(2.2);
surface->setFoamTopHeight(3.0);
surface->enableCrestFoam(true);
viewer->addEventHandler(surface->getEventHandler());
viewer->addEventHandler(scene->getEventHandler());
//添加小船
osg::ref_ptr<osg::Node> galley = osgDB::readNodeFile("resources/boat/boat.3ds");
//galley->setNodeMask(scene->getNormalSceneMask() | scene->getReflectedSceneMask() | scene->getRefractedSceneMask());
osg::MatrixTransform * trans = new osg::MatrixTransform;
trans->setMatrix(osg::Matrix::translate(osg::Vec3(0, 0, 0)));
trans->setUpdateCallback(new BoatPositionCallback(scene));
trans->addChild(galley);
scene->addChild(trans);
osgGA::TrackballManipulator *tb = new osgGA::TrackballManipulator;
tb->setHomePosition(osg::Vec3d(0, 0, 20), osg::Vec3d(0, 20, 20), osg::Z_AXIS);
viewer->setCameraManipulator(tb);
viewer->addEventHandler(new osgViewer::StatsHandler);
viewer->setSceneData(scene.get());
return viewer->run();
}
以上代码还参考了osgocean中的天空盒例子,时间搬运了其天空盒。## OSG第65-72讲(海洋篇)