/*************************************************************** * Function: ANIMLoadSketchBook() ***************************************************************/ void ANIMLoadSketchBook(PositionAttitudeTransform** xformScaleFwd, PositionAttitudeTransform** xformScaleBwd, int &numPages, ANIMPageEntry ***pageEntryArray) { *xformScaleFwd = new PositionAttitudeTransform; *xformScaleBwd = new PositionAttitudeTransform; MatrixTransform *sketchbookTrans = new MatrixTransform; Matrixf transMat, scaleMat; transMat.makeTranslate(Vec3(0, 0, ANIM_VIRTUAL_SPHERE_RADIUS)); scaleMat.makeScale(Vec3(ANIM_PARA_PAINT_FRAME_ZOOM_FACTOR, ANIM_PARA_PAINT_FRAME_ZOOM_FACTOR, ANIM_PARA_PAINT_FRAME_ZOOM_FACTOR)); sketchbookTrans->setMatrix(transMat * scaleMat); (*xformScaleFwd)->addChild(sketchbookTrans); (*xformScaleBwd)->addChild(sketchbookTrans); // load sketch book node from VRML file, create page geodes Node* sketchbookNode = osgDB::readNodeFile(ANIMDataDir() + "VRMLFiles/SketchBook.WRL"); sketchbookTrans->addChild(sketchbookNode); // Load floorplan filenames from config file bool isFile = true; int j = 0, numTex; std::string file = "", dir, path; std::vector<std::string> filenames; dir = cvr::ConfigManager::getEntry("dir", "Plugin.CaveCADBeta.Floorplans", "/home/cehughes"); dir = dir + "/"; path = "Plugin.CaveCADBeta.Floorplans.0"; file = cvr::ConfigManager::getEntry(path, "", &isFile); while (isFile) { filenames.push_back(dir + file); j++; char buf[50]; sprintf(buf, "Plugin.CaveCADBeta.Floorplans.%d", j); std::string path = std::string(buf); file = cvr::ConfigManager::getEntry(path, "", &isFile); } numPages = j; //numPages = 3; // create tree structured page entry array *pageEntryArray = new ANIMPageEntry*[numPages]; for (int i = 0; i < numPages; i++) { /* char idxStr[16]; if (i < 10) { sprintf(idxStr, "0%d", i); } else if (i < 100) { sprintf(idxStr, "%d", i); }*/ string filename = filenames[i];//ANIMDataDir() + "Textures/Floorplans/Floorplan" + string(idxStr) + string(".JPG"); (*pageEntryArray)[i] = new ANIMPageEntry; Switch *singlePageSwitch = new Switch; PositionAttitudeTransform *flipUpTrans = new PositionAttitudeTransform; PositionAttitudeTransform *flipDownTrans = new PositionAttitudeTransform; sketchbookTrans->addChild(singlePageSwitch); singlePageSwitch->addChild(flipUpTrans); singlePageSwitch->addChild(flipDownTrans); singlePageSwitch->setAllChildrenOff(); // set up flip up / flip down animation paths for each page Geode *flipUpGeode, *flipDownGeode; AnimationPathCallback *flipUpCallback, *flipDownCallback; ANIMCreateSinglePageGeodeAnimation(filename, &flipUpGeode, &flipDownGeode, &flipUpCallback, &flipDownCallback); flipUpTrans->addChild(flipUpGeode); flipUpTrans->setUpdateCallback(flipUpCallback); flipDownTrans->addChild(flipDownGeode); flipDownTrans->setUpdateCallback(flipDownCallback); // write into page entry array record (*pageEntryArray)[i]->mSwitch = singlePageSwitch; (*pageEntryArray)[i]->mFlipUpAnim = flipUpCallback; (*pageEntryArray)[i]->mFlipDownAnim = flipDownCallback; (*pageEntryArray)[i]->mPageGeode = flipDownGeode; (*pageEntryArray)[i]->mTexFilename = filename; } (*pageEntryArray)[0]->mSwitch->setSingleChildOn(1); (*pageEntryArray)[1]->mSwitch->setSingleChildOn(0); // size of floorplan // FIX THIS - put sizes in the config file or something float alt = -2.9f; (*pageEntryArray)[0]->mLength = 32; (*pageEntryArray)[0]->mWidth = 16; (*pageEntryArray)[0]->mAlti = alt; (*pageEntryArray)[1]->mLength = 128; (*pageEntryArray)[1]->mWidth = 128; (*pageEntryArray)[1]->mAlti = alt; (*pageEntryArray)[2]->mLength = 32; (*pageEntryArray)[2]->mWidth = 16; (*pageEntryArray)[2]->mAlti = alt; (*pageEntryArray)[3]->mLength = 32; (*pageEntryArray)[3]->mWidth = 32; (*pageEntryArray)[3]->mAlti = alt; // set up the forward / backward scale animation paths for sketch book root switch AnimationPath* animationPathScaleFwd = new AnimationPath; AnimationPath* animationPathScaleBwd = new AnimationPath; animationPathScaleFwd->setLoopMode(AnimationPath::NO_LOOPING); animationPathScaleBwd->setLoopMode(AnimationPath::NO_LOOPING); Vec3 scaleFwd, scaleBwd; float step = 1.f / ANIM_VIRTUAL_SPHERE_NUM_SAMPS; for (int i = 0; i < ANIM_VIRTUAL_SPHERE_NUM_SAMPS + 1; i++) { float val = i * step; scaleFwd = Vec3(val, val, val); scaleBwd = Vec3(1.f-val, 1.f-val, 1.f-val); animationPathScaleFwd->insert(val, AnimationPath::ControlPoint(Vec3(),Quat(), scaleFwd)); animationPathScaleBwd->insert(val, AnimationPath::ControlPoint(Vec3(),Quat(), scaleBwd)); } AnimationPathCallback *animCallbackFwd = new AnimationPathCallback(animationPathScaleFwd, 0.0, 1.f / ANIM_VIRTUAL_SPHERE_LAPSE_TIME); AnimationPathCallback *animCallbackBwd = new AnimationPathCallback(animationPathScaleBwd, 0.0, 1.f / ANIM_VIRTUAL_SPHERE_LAPSE_TIME); (*xformScaleFwd)->setUpdateCallback(animCallbackFwd); (*xformScaleBwd)->setUpdateCallback(animCallbackBwd); }
/*************************************************************** * Function: ANIMCreateRefSkyDome() * ***************************************************************/ MatrixTransform *ANIMCreateRefSkyDome(StateSet **stateset) { /* sky dome geometry */ Sphere *skyShape = new Sphere(); ShapeDrawable* skyDrawable = new ShapeDrawable(skyShape); Geode* skyGeode = new Geode(); MatrixTransform *skyDomeTrans = new MatrixTransform; //osg::Matrix m; //m.makeRotate(osg::Quat(M_PI/2, osg::Vec3(0, 1, 0))); //skyDomeTrans->setMatrix(m); skyShape->setRadius(ANIM_SKYDOME_RADIUS); skyGeode->addDrawable(skyDrawable); skyDomeTrans->addChild(skyGeode); // apply simple colored materials Material* material = new Material; material->setDiffuse(Material::FRONT_AND_BACK, Vec4(1.0f, 1.0f, 1.0f, 1.0f)); material->setAlpha(Material::FRONT_AND_BACK, 1.0f); (*stateset) = new StateSet(); (*stateset)->setAttributeAndModes(material, StateAttribute::OVERRIDE | StateAttribute::ON); (*stateset)->setMode(GL_BLEND, StateAttribute::OVERRIDE | StateAttribute::ON ); (*stateset)->setRenderingHint(StateSet::TRANSPARENT_BIN); skyGeode->setStateSet(*stateset); // skyGeode->setNodeMask(0xFFFFFF & ~(0x2 | 0x3)); // load sky dome shader Uniform* sunrUniform = new Uniform("hazeRadisuMin", 0.975f); (*stateset)->addUniform(sunrUniform); Uniform* sunRUniform = new Uniform("hazeRadisuMax", 0.995f); (*stateset)->addUniform(sunRUniform); Uniform* sunDirUniform = new Uniform("sundir", Vec4(0.0, 0.0, 1.0, 1.0)); (*stateset)->addUniform(sunDirUniform); Uniform* suncolorUniform = new Uniform("suncolor", Vec4(1.0, 1.0, 1.0, 1.0)); (*stateset)->addUniform(suncolorUniform); Uniform* skycolorUniform = new Uniform("skycolor", Vec4(0.5, 0.5, 1.0, 1.0)); (*stateset)->addUniform(skycolorUniform); Uniform* skyfadingcolorUniform = new Uniform("skyfadingcolor", Vec4(0.8, 0.8, 0.8, 1.0)); (*stateset)->addUniform(skyfadingcolorUniform); Uniform* skymaskingcolorUniform = new Uniform("skymaskingcolor", Vec4(1.0, 1.0, 1.0, 1.0)); (*stateset)->addUniform(skymaskingcolorUniform); Uniform *matShaderToWorldUniform = new Uniform("shaderToWorldMat", Matrixd()); (*stateset)->addUniform(matShaderToWorldUniform); Image* imageSky = osgDB::readImageFile(ANIMDataDir() + "Textures/NightSky.JPG"); Texture2D* textureSky = new Texture2D(imageSky); (*stateset)->setTextureAttributeAndModes(0, textureSky, StateAttribute::ON); Image* imagePara = osgDB::readImageFile(ANIMDataDir() + "Textures/Paramounts/Paramount00.JPG"); Texture2D* texturePara = new Texture2D(imagePara); (*stateset)->setTextureAttributeAndModes(1, texturePara, StateAttribute::ON); Uniform* skyNightSampler = new Uniform("texNightSky", 0); (*stateset)->addUniform(skyNightSampler); Uniform* paraImageTextureSampler = new Uniform("texParamount", 1); (*stateset)->addUniform(paraImageTextureSampler); Program* programSky = new Program; (*stateset)->setAttribute(programSky); programSky->addShader(Shader::readShaderFile(Shader::VERTEX, ANIMDataDir() + "Shaders/EnvSky.vert")); programSky->addShader(Shader::readShaderFile(Shader::FRAGMENT, ANIMDataDir() + "Shaders/EnvSky.frag")); return skyDomeTrans; }
/*************************************************************** * Function: ANIMLoadGeometryCreator() * * xformScaleFwd: Root transform node for inflating geometries * xformScaleBwd: Root transform node for shrinking geometries * sphereExteriorSwitch: Switch control for single exterior sphere * ***************************************************************/ void ANIMLoadGeometryCreator(PositionAttitudeTransform** xformScaleFwd, PositionAttitudeTransform** xformScaleBwd, Switch **sphereExteriorSwitch, Geode **sphereExteriorGeode, int &numTypes, ANIMShapeSwitchEntry ***shapeSwitchEntryArray) { *xformScaleFwd = new PositionAttitudeTransform; *xformScaleBwd = new PositionAttitudeTransform; MatrixTransform *geomCreatorTrans = new MatrixTransform; MatrixTransform *sphereExteriorTrans = new MatrixTransform; *sphereExteriorSwitch = new Switch; Switch *createBoxSwitch = new Switch; Switch *createCylinderSwitch = new Switch; (*xformScaleFwd)->addChild(geomCreatorTrans); (*xformScaleBwd)->addChild(geomCreatorTrans); geomCreatorTrans->addChild(*sphereExteriorSwitch); geomCreatorTrans->addChild(createBoxSwitch); geomCreatorTrans->addChild(createCylinderSwitch); osg::Vec3 pos(-1, 0, 0); // create drawables, geodes and attach them to animation switches *sphereExteriorGeode = new Geode(); Sphere *sphere = new Sphere(osg::Vec3(), ANIM_VIRTUAL_SPHERE_RADIUS); ShapeDrawable *sphereDrawable = new ShapeDrawable(sphere); (*sphereExteriorGeode)->addDrawable(sphereDrawable); Box *box = new Box(osg::Vec3(0.1, 0, 0), ANIM_VIRTUAL_SPHERE_RADIUS / 1.9); (*sphereExteriorGeode)->addDrawable(new ShapeDrawable(box)); float r = ANIM_VIRTUAL_SPHERE_RADIUS / 3.0; Cylinder *cylinder = new Cylinder(osg::Vec3(-0.05, 0, -0.05), r, r * 2); (*sphereExteriorGeode)->addDrawable(new ShapeDrawable(cylinder)); Cone *cone = new osg::Cone(osg::Vec3(0, -0.1, 0.05), r, r * 2); (*sphereExteriorGeode)->addDrawable(new ShapeDrawable(cone)); Material *transmaterial = new Material; transmaterial->setDiffuse(Material::FRONT_AND_BACK, Vec4(1, 1, 1, 1)); transmaterial->setAlpha(Material::FRONT_AND_BACK, 0.6f); Image* envMap = osgDB::readImageFile(ANIMDataDir() + "Textures/ShapeContainer.JPG"); Texture2D* envTex = new Texture2D(envMap); StateSet *sphereStateSet = (sphereDrawable)->getOrCreateStateSet(); sphereStateSet->setMode(GL_BLEND, StateAttribute::OVERRIDE | StateAttribute::ON ); sphereStateSet->setRenderingHint(StateSet::TRANSPARENT_BIN); sphereStateSet->setAttributeAndModes(transmaterial, StateAttribute::OVERRIDE | StateAttribute::ON); sphereStateSet->setTextureAttributeAndModes(0, envTex, StateAttribute::ON); sphereStateSet->setMode(GL_CULL_FACE, StateAttribute::ON); sphereExteriorTrans->addChild(*sphereExteriorGeode); (*sphereExteriorSwitch)->addChild(sphereExteriorTrans); (*sphereExteriorSwitch)->setAllChildrenOn(); // write into shape switch entry array record numTypes = 2; *shapeSwitchEntryArray = new ANIMShapeSwitchEntry*[numTypes]; (*shapeSwitchEntryArray)[0] = new ANIMShapeSwitchEntry; (*shapeSwitchEntryArray)[1] = new ANIMShapeSwitchEntry; (*shapeSwitchEntryArray)[0]->mSwitch = createBoxSwitch; (*shapeSwitchEntryArray)[1]->mSwitch = createCylinderSwitch; ANIMCreateSingleShapeSwitchAnimation(&((*shapeSwitchEntryArray)[0]), CAVEGeodeShape::BOX); ANIMCreateSingleShapeSwitchAnimation(&((*shapeSwitchEntryArray)[1]), CAVEGeodeShape::CYLINDER); /* set up the forward / backward scale animation paths for geometry creator */ AnimationPath* animationPathScaleFwd = new AnimationPath; AnimationPath* animationPathScaleBwd = new AnimationPath; animationPathScaleFwd->setLoopMode(AnimationPath::NO_LOOPING); animationPathScaleBwd->setLoopMode(AnimationPath::NO_LOOPING); Vec3 scaleFwd, scaleBwd; float step = 1.f / ANIM_VIRTUAL_SPHERE_NUM_SAMPS; for (int i = 0; i < ANIM_VIRTUAL_SPHERE_NUM_SAMPS + 1; i++) { float val = i * step; scaleFwd = Vec3(val, val, val); scaleBwd = Vec3(1.f-val, 1.f-val, 1.f-val); animationPathScaleFwd->insert(val, AnimationPath::ControlPoint(pos, Quat(), scaleFwd)); animationPathScaleBwd->insert(val, AnimationPath::ControlPoint(pos, Quat(), scaleBwd)); } AnimationPathCallback *animCallbackFwd = new AnimationPathCallback(animationPathScaleFwd, 0.0, 1.f / ANIM_VIRTUAL_SPHERE_LAPSE_TIME); AnimationPathCallback *animCallbackBwd = new AnimationPathCallback(animationPathScaleBwd, 0.0, 1.f / ANIM_VIRTUAL_SPHERE_LAPSE_TIME); (*xformScaleFwd)->setUpdateCallback(animCallbackFwd); (*xformScaleBwd)->setUpdateCallback(animCallbackBwd); }
/*************************************************************** * Function: ANIMLoadSketchBook() ***************************************************************/ void ANIMLoadSketchBook(PositionAttitudeTransform** xformScaleFwd, PositionAttitudeTransform** xformScaleBwd, int &numPages, ANIMPageEntry ***pageEntryArray) { *xformScaleFwd = new PositionAttitudeTransform; *xformScaleBwd = new PositionAttitudeTransform; MatrixTransform *sketchbookTrans = new MatrixTransform; Matrixf transMat, scaleMat; transMat.makeTranslate(Vec3(0, 0, ANIM_VIRTUAL_SPHERE_RADIUS)); scaleMat.makeScale(Vec3(ANIM_PARA_PAINT_FRAME_ZOOM_FACTOR, ANIM_PARA_PAINT_FRAME_ZOOM_FACTOR, ANIM_PARA_PAINT_FRAME_ZOOM_FACTOR)); sketchbookTrans->setMatrix(transMat * scaleMat); (*xformScaleFwd)->addChild(sketchbookTrans); (*xformScaleBwd)->addChild(sketchbookTrans); /* load sketch book node from VRML file, create page geodes */ Node* sketchbookNode = osgDB::readNodeFile(ANIMDataDir() + "VRMLFiles/SketchBook.WRL"); sketchbookTrans->addChild(sketchbookNode); /* create tree structured page entry array */ numPages = 3; *pageEntryArray = new ANIMPageEntry*[numPages]; for (int i = 0; i < numPages; i++) { char idxStr[16]; if (i < 10) sprintf(idxStr, "0%d", i); else if (i < 100) sprintf(idxStr, "%d", i); string filename = ANIMDataDir() + "Textures/Floorplans/Floorplan" + string(idxStr) + string(".JPG"); (*pageEntryArray)[i] = new ANIMPageEntry; Switch *singlePageSwitch = new Switch; PositionAttitudeTransform *flipUpTrans = new PositionAttitudeTransform; PositionAttitudeTransform *flipDownTrans = new PositionAttitudeTransform; sketchbookTrans->addChild(singlePageSwitch); singlePageSwitch->addChild(flipUpTrans); singlePageSwitch->addChild(flipDownTrans); singlePageSwitch->setAllChildrenOff(); /* set up flip up / flip down animation paths for each page */ Geode *flipUpGeode, *flipDownGeode; AnimationPathCallback *flipUpCallback, *flipDownCallback; ANIMCreateSinglePageGeodeAnimation(filename, &flipUpGeode, &flipDownGeode, &flipUpCallback, &flipDownCallback); flipUpTrans->addChild(flipUpGeode); flipUpTrans->setUpdateCallback(flipUpCallback); flipDownTrans->addChild(flipDownGeode); flipDownTrans->setUpdateCallback(flipDownCallback); /* write into page entry array record */ (*pageEntryArray)[i]->mSwitch = singlePageSwitch; (*pageEntryArray)[i]->mFlipUpAnim = flipUpCallback; (*pageEntryArray)[i]->mFlipDownAnim = flipDownCallback; (*pageEntryArray)[i]->mPageGeode = flipDownGeode; (*pageEntryArray)[i]->mTexFilename = filename; } (*pageEntryArray)[0]->mSwitch->setSingleChildOn(1); (*pageEntryArray)[1]->mSwitch->setSingleChildOn(0); /* size of floorplan */ (*pageEntryArray)[0]->mLength = 32; (*pageEntryArray)[0]->mWidth = 16; (*pageEntryArray)[0]->mAlti = -1.5f; (*pageEntryArray)[1]->mLength = 128; (*pageEntryArray)[1]->mWidth = 128; (*pageEntryArray)[1]->mAlti = -1.5f; (*pageEntryArray)[2]->mLength = 32; (*pageEntryArray)[2]->mWidth = 16; (*pageEntryArray)[2]->mAlti = -1.5f; /* set up the forward / backward scale animation paths for sketch book root switch */ AnimationPath* animationPathScaleFwd = new AnimationPath; AnimationPath* animationPathScaleBwd = new AnimationPath; animationPathScaleFwd->setLoopMode(AnimationPath::NO_LOOPING); animationPathScaleBwd->setLoopMode(AnimationPath::NO_LOOPING); Vec3 scaleFwd, scaleBwd; float step = 1.f / ANIM_VIRTUAL_SPHERE_NUM_SAMPS; for (int i = 0; i < ANIM_VIRTUAL_SPHERE_NUM_SAMPS + 1; i++) { float val = i * step; scaleFwd = Vec3(val, val, val); scaleBwd = Vec3(1.f-val, 1.f-val, 1.f-val); animationPathScaleFwd->insert(val, AnimationPath::ControlPoint(Vec3(),Quat(), scaleFwd)); animationPathScaleBwd->insert(val, AnimationPath::ControlPoint(Vec3(),Quat(), scaleBwd)); } AnimationPathCallback *animCallbackFwd = new AnimationPathCallback(animationPathScaleFwd, 0.0, 1.f / ANIM_VIRTUAL_SPHERE_LAPSE_TIME); AnimationPathCallback *animCallbackBwd = new AnimationPathCallback(animationPathScaleBwd, 0.0, 1.f / ANIM_VIRTUAL_SPHERE_LAPSE_TIME); (*xformScaleFwd)->setUpdateCallback(animCallbackFwd); (*xformScaleBwd)->setUpdateCallback(animCallbackBwd); }
/*************************************************************** * Function: ANIMCreateVirtualSphere() * ***************************************************************/ void ANIMCreateVirtualSphere(osg::PositionAttitudeTransform** xformScaleFwd, osg::PositionAttitudeTransform** xformScaleBwd) { // create sphere geometry *xformScaleFwd = new PositionAttitudeTransform; *xformScaleBwd = new PositionAttitudeTransform; Geode* sphereGeode = new Geode(); Sphere* virtualSphere = new Sphere(); Drawable* sphereDrawable = new ShapeDrawable(virtualSphere); virtualSphere->setRadius(ANIM_VIRTUAL_SPHERE_RADIUS); sphereGeode->addDrawable(sphereDrawable); (*xformScaleFwd)->addChild(sphereGeode); (*xformScaleBwd)->addChild(sphereGeode); osg::StateSet* stateset; // highlights /* Sphere* highlightSphere = new Sphere(); ShapeDrawable* highlightDrawable = new ShapeDrawable(highlightSphere); Geode* highlightGeode = new Geode(); highlightSphere->setRadius(ANIM_VIRTUAL_SPHERE_RADIUS * 1.3); highlightDrawable->setColor(osg::Vec4(0,0,1,0.3)); highlightGeode->addDrawable(highlightDrawable); (*xformScaleFwd)->addChild(highlightGeode); (*xformScaleBwd)->addChild(highlightGeode); stateset = highlightDrawable->getOrCreateStateSet(); stateset->setMode(GL_BLEND, StateAttribute::ON); stateset->setMode(GL_CULL_FACE, StateAttribute::ON); stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF); stateset->setRenderingHint(StateSet::TRANSPARENT_BIN); */ // set up the forward / backward scale animation path AnimationPath* animationPathScaleFwd = new AnimationPath; AnimationPath* animationPathScaleBwd = new AnimationPath; animationPathScaleFwd->setLoopMode(AnimationPath::NO_LOOPING); animationPathScaleBwd->setLoopMode(AnimationPath::NO_LOOPING); osg::Vec3 pos(-1.5, 0, 0); Vec3 scaleFwd, scaleBwd; float step = 1.f / ANIM_VIRTUAL_SPHERE_NUM_SAMPS; for (int i = 0; i < ANIM_VIRTUAL_SPHERE_NUM_SAMPS + 1; i++) { float val = i * step; scaleFwd = Vec3(val, val, val); scaleBwd = Vec3(1-val, 1-val, 1-val); animationPathScaleFwd->insert(val, AnimationPath::ControlPoint(pos, Quat(), scaleFwd)); animationPathScaleBwd->insert(val, AnimationPath::ControlPoint(pos, Quat(), scaleBwd)); } AnimationPathCallback *animCallbackFwd = new AnimationPathCallback(animationPathScaleFwd, 0.0, 1.f / ANIM_VIRTUAL_SPHERE_LAPSE_TIME); AnimationPathCallback *animCallbackBwd = new AnimationPathCallback(animationPathScaleBwd, 0.0, 1.f / ANIM_VIRTUAL_SPHERE_LAPSE_TIME); (*xformScaleFwd)->setUpdateCallback(animCallbackFwd); (*xformScaleBwd)->setUpdateCallback(animCallbackBwd); /* apply shaders to geode stateset */ stateset = new StateSet(); stateset->setMode(GL_BLEND, StateAttribute::OVERRIDE | StateAttribute::ON ); stateset->setRenderingHint(StateSet::TRANSPARENT_BIN); //sphereGeode->setStateSet(stateset); sphereDrawable->setStateSet(stateset); Program* shaderProg = new Program; stateset->setAttribute(shaderProg); shaderProg->addShader(Shader::readShaderFile(Shader::VERTEX, ANIMDataDir() + "Shaders/VirtualSphere.vert")); shaderProg->addShader(Shader::readShaderFile(Shader::FRAGMENT, ANIMDataDir() + "Shaders/VirtualSphere.frag")); Image* envMap = osgDB::readImageFile(ANIMDataDir() + "Textures/EnvMap.JPG"); Texture2D* envTex = new Texture2D(envMap); stateset->setTextureAttributeAndModes(0, envTex, StateAttribute::ON); Uniform* envMapSampler = new Uniform("EnvMap", 0); stateset->addUniform(envMapSampler); Uniform* baseColorUniform = new Uniform("BaseColor", Vec3(0.2, 1.0, 0.2)); stateset->addUniform(baseColorUniform); Uniform* lightPosUniform = new Uniform("LightPos", Vec4(1.0, 0.0, 0.2, 0.0)); stateset->addUniform(lightPosUniform); }