#include <osgViewer/Viewer> #include <osgDB/WriteFile> #include <osg/StateSet> #include <osg/Texture> #include <osg/Texture2D> #include <osg/Image> #include <cmath> #include <osgDB/ReadFile> #pragma comment(lib, "osgd.lib") #pragma comment(lib, "osgViewerd.lib") #pragma comment(lib, "osgDBd.lib") #pragma comment(lib, "osgGAd.lib") const int FFT_SIZE = 256; const int PASSES = 8; const int N = 256; const float M_PI = osg::PI; int bitReverse(int i, int N) { int j = i; int M = N; int Sum = 0; int W = 1; M = M / 2; while (M != 0) { j = (i & M) > M - 1; Sum += j * W; W *= 2; M = M / 2; } return Sum; } void computeWeight(int N, int k, float &Wr, float &Wi) { Wr = cosl(2.0 * M_PI * k / float(N)); Wi = sinl(2.0 * M_PI * k / float(N)); } osg::ref_ptr<osg::Image> CreateImage() { osg::ref_ptr<osg::Image> image = new osg::Image; image->allocateImage(FFT_SIZE, PASSES, 1, GL_RGBA, GL_FLOAT); image->setInternalTextureFormat(GL_RGBA16); osg::Vec4 * data = (osg::Vec4 *)image->data(); for (int i = 0; i < PASSES; i++) { int nBlocks = (int) powf(2.0, float(PASSES - 1 - i)); int nHInputs = (int) powf(2.0, float(i)); for (int j = 0; j < nBlocks; j++) { for (int k = 0; k < nHInputs; k++) { int i1, i2, j1, j2; if (i == 0) { i1 = j * nHInputs * 2 + k; i2 = j * nHInputs * 2 + nHInputs + k; j1 = bitReverse(i1, FFT_SIZE); j2 = bitReverse(i2, FFT_SIZE); } else { i1 = j * nHInputs * 2 + k; i2 = j * nHInputs * 2 + nHInputs + k; j1 = i1; j2 = i2; } float wr, wi; computeWeight(FFT_SIZE, k * nBlocks, wr, wi); int offset1 = (i1 + i * FFT_SIZE); data[offset1]._v[0] = (j1 + 0.5) / FFT_SIZE; data[offset1]._v[1] = (j2 + 0.5) / FFT_SIZE; data[offset1]._v[2] = wr; data[offset1]._v[3] = wi; int offset2 = (i2 + i * FFT_SIZE); data[offset2]._v[0] = (j1 + 0.5) / FFT_SIZE; data[offset2]._v[1] = (j2 + 0.5) / FFT_SIZE; data[offset2]._v[2] = -wr; data[offset2]._v[3] = -wi; } } } return image.get(); } osg::ref_ptr<osg::Geode> CreateQuad() { osg::ref_ptr<osg::Geode> quad = new osg::Geode; osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry; osg::ref_ptr<osg::Vec3Array> vArray = new osg::Vec3Array; osg::ref_ptr<osg::Vec2Array> tArray = new osg::Vec2Array; vArray->push_back(osg::Vec3(-1.0, -1.0, 0.0)); vArray->push_back(osg::Vec3(1.0, -1.0, 0.0)); vArray->push_back(osg::Vec3(1.0, 1.0, 0.0)); vArray->push_back(osg::Vec3(-1.0, 1.0, 0.0)); tArray->push_back(osg::Vec2(0.0, 0.0)); tArray->push_back(osg::Vec2(1.0, 0.0)); tArray->push_back(osg::Vec2(1.0, 1.0)); tArray->push_back(osg::Vec2(0.0, 1.0)); geometry->setVertexArray(vArray.get()); geometry->setTexCoordArray(0, tArray.get()); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vArray->size())); quad->addDrawable(geometry.get()); return quad.get(); } osg::ref_ptr<osg::StateSet> SetUpImageStateSet(osg::ref_ptr<osg::Image> image) { osg::ref_ptr<osg::StateSet> stateSet = new osg::StateSet; osg::ref_ptr<osg::Texture2D> texture2D = new osg::Texture2D; texture2D->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST); texture2D->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST); texture2D->setWrap(osg::Texture2D::WRAP_S, osg::Texture2D::CLAMP_TO_EDGE); texture2D->setWrap(osg::Texture2D::WRAP_T, osg::Texture2D::CLAMP_TO_EDGE); texture2D->setImage(image.get()); stateSet->setTextureAttributeAndModes(0, texture2D.get(), osg::StateAttribute::ON); return stateSet.get(); } int main() { osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer; viewer->setUpViewInWindow(35, 35, 1024, 800); osg::ref_ptr<osg::Geode> quad = CreateQuad(); quad->setStateSet(SetUpImageStateSet(CreateImage().get())); viewer->setSceneData(quad.get()); viewer->getCamera()->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); viewer->run(); return EXIT_SUCCESS; }