/* * levelHead v1.0. * * Copyright Julian Oliver 2007-2008 * * This is the main levelHead application code. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . * * A comment about the license(s): * * Two different copyright licenses cover this project. One for the code, the * other for the art. * * Code: levelHead, like most software projects, is dependent on third-party * code. The code I've chosen to use is released under Free-Software licenses, * or licenses that encourage redistribution and modification. My right to use * this code in my projects is provided under the condition that the code I * write is released under a license that's compatible with theirs. I chose the * GPLv3. This is a relation of mutual benefit: I get to write a better project * in a fraction of the time and they get to use the outcome, while keeping * their code under the license they chose. The same applies to the code below: * if you want to use it in other projects, you have to abide by the above * license. All it takes is a decompiler to make sure this has happened! * * Art: The binary art assets (3D models etc) on which the below code depends * are released under the FSF endorsed Creative Commons CC-BY-SA 3.0 license, * meaning that whenever this project is presented using that art the proper * attribution must apply: "levelHead v1.0. Copyright Julian Oliver 2007-2008. * http://julianoliver.com/levelhead." * The license is here: http://creativecommons.org/licenses/by-sa/3.0/ * * A comment about scenegraph structure: * * There were several different approaches to moving the character between room * nodes. By far the most stable method where navigation itself is concerned is * to have one character as a child of each room itself, toggling the nodeMask * and positioning the character when it should be visible. This has two * difficulties however, one being the load time of setting up the character * when encountered in a room and secondly the issue of determining the * logically correct character orientation related to its orientation when * leaving the previous room. This was the setup I had in the BETA. * * The other approach was to addChild and removeChild a single character to * each room as required. This caused all sorts of problems where collision and * transformation was concerned, especially when a room the character was * supposed to be in was initialised quickly (with the player moving the cube * fast). I never got to the bottom of these issues but if solved, this * approach would be the best way forward I think. * * What I ended up going with was having just one character parented to a node * higher up than the room node and simply moving the character to the correct * position when needed. This has the disadvantage of needing to set the * character transformation matrix to that of the room node every frame, * something that's noticeable when the cube is being moved quickly. On a * sufficiently fast computer however, this discrepancy is barely noticeable * though. * * Here's a graph of what we have now: * * root * | * [+]projection matrix * | * [+]model matrix * | * [+]foreground * | | * | [+]scene * | | | * | | [+]rooms * | | | * | | [+]room labels * | | * | [+]screen labels * | * [+]character transform matrix * | * [+]character * * A comment about code quality: * * This code needs cleaning up and refactoring. An experienced C++ programmer * will notice all the C-isms in here (printf's etc) and other bad habits. I'm * gradually moving these statements over to the saner std::cout/std::endl. * * The code could do with a lot more Oo in general. In this respect consider it * as proof of concept code and feel free to contribute patches! * * Third-party contributions in this version: * * pix * * - Ported levelHead from ARToolkit to more robust ARToolkitPlus tracker (big * thanks!) * - Created a stencil buffer to replace the awkward mask node solution I used * in the beta. This allows more than one room to be overlayed at a time on * the same cube. (Note that I may remove that functionality in an upcoming * version, preferring just one room at a time being visible per cube) * */ #include "osgcal.h" #ifdef HAVE_CONFIG_H #include "config.h" #endif // HAVE_CONFIG_H #ifdef USE_NPROFILE #include #else // USE_NPROFILE #define NPROFILE_SAMPLE(a) #endif #include #include "osgcal.h" #include #include "osgviewer.h" //#include #include #include #include #include #include #include #include #include #include //#include #define DEFAULT_DATA_DIR "Data" #ifndef DATA_DIR #define DATA_DIR "." #endif // DATA_DIR #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* these needed anymore? */ using namespace osg; using namespace osgDB; /* node visitor utility class. used by lots of other functions. */ class findName : public osg::NodeVisitor { public: findName(const std::string &name): osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN), _name(name) {} virtual void apply(osg::Group &group) { if (group.getName()==_name) { _foundNodes.push_back(&group); osg::Vec3 pos = group.computeBound().center(); printf("findName found %s at position: %f %f %f \n", _name.c_str(), pos.x(), pos.y(), pos.z()); } traverse(group); } typedef std::vector< osg::ref_ptr > NodeList; std::string _name; NodeList _foundNodes; }; /* some utils from osgCal for loading cal3d files */ std::string getExtension(const std::string &file) { std::string::size_type dot = file.rfind('.'); std::string lcpath = file; std::string suffix; std::transform(lcpath.begin(), lcpath.end(), lcpath.begin(), tolower); if(dot != std::string::npos) { suffix = lcpath.substr(dot + 1); } return suffix; } ParseArguments::ParseArguments(int ac, char **av) { mArgc = ac; mArgv = av; mNumloops = 1; mNumframes = 500; mVerbose_flag = false; mVertexprogram_flag = false; mBenchmark_flag = false; mNumframes_flag = false; mDirectory_flag = false; mFile = -1; mError_occurred = false; mFixcam_flag = false; mDirectory = ""; } bool ParseArguments::Parse() { std::stringstream error; for (int i = -1; i < mArgc; i++) { if (mFile == -1) mFile = i; } if (!mError_occurred) { if (mFile != -1) { while (mFile < mArgc) { mPositional_arguments.push_back(std::string(mArgv[mFile++])); } } } mPath = ""; if (!mError_occurred) { if (!mPositional_arguments.empty()) { mPath = mPositional_arguments.front(); mPositional_arguments.erase(mPositional_arguments.begin()); } else { mError_occurred = true; error << "arguments missing you need at least a cal3d.xfg file and an outfit.xfg file"; } } if (!mError_occurred) { mSuffix = getExtension(mPath); if(! (mSuffix == "cfg" || mSuffix == "xfg")) { mError_occurred = true; error << "expected a .cfg or .xfg file but got " << mPath << " instead"; } } return true; } /* character is added by this function. called by setupChar. */ osg::Node *addCharacter() { { osgDB::FilePathList& path = osgDB::getDataFilePathList(); path.push_front(DATA_DIR); path.push_front(DEFAULT_DATA_DIR); } int num = 1; char* args[] = {"Data/character/man/man4man.cfg"}; ParseArguments arguments(num,args); if (!arguments.Parse()) { printf("%s", "files wrong/didn't load"); } osg::Timer_t start_tick = osg::Timer::instance()->tick(); osg::Group *group = new osg::Group(); osg::ref_ptr model = new osgCal::Model(); //osg::ref_ptr modelNode = dynamic_cast(model.get()); group->addChild(model.get()); //group->addChild(modelNode); osg::Object *object = osgDB::readObjectFile(arguments.mPath); osg::ref_ptr coreModelRef = dynamic_cast( object ); osgCal::CoreModel *coreModel = coreModelRef.get(); if(!model->setCoreModel(coreModel)) { std::cerr << "setCoreModel: " << CalError::getLastErrorDescription().c_str() << std::endl; } if(arguments.mSuffix == "cfg") { for(int coreMeshId = 0; coreMeshId < model->getCalCoreModel()->getCoreMeshCount(); coreMeshId++) { model->getCalModel()->attachMesh(coreMeshId); } // set the material set of the whole model model->getCalModel()->setMaterialSet(0); if(!model->create()) { std::cerr << "create: " << CalError::getLastErrorDescription().c_str() << std::endl; } } if (!model) { std::cerr << args[0] <<": No data loaded" << std::endl; //return 1; } osg::Timer_t end_tick = osg::Timer::instance()->tick(); std::cout << "Time to load = "<delta_s(start_tick,end_tick)<getCalModel()->getMixer(); group->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); return group; } template A* getNodeAttribute(osg::Node *srcNode) { if (srcNode == NULL) return NULL; osg::StateSet *state = srcNode->getOrCreateStateSet(); A* attr = dynamic_cast< A* > (state->getAttribute( SA )); if(!attr) { attr = new A; state->setAttribute(attr); } return attr; } void forceWireFrameModeOn ( osg::Node *srcNode) { getNodeAttribute(srcNode)->setMode(osg::PolygonMode::FRONT_AND_BACK, osg::PolygonMode::LINE); } osg::Geode *makeStencilClearingNode(int bin) { osg::Geode *stencilNode = new osg::Geode(); // disable color write getNodeAttribute(stencilNode) ->setMask(false,false,false,false); // disable depth write getNodeAttribute(stencilNode) ->setWriteMask(false); osg::StateSet *ss = stencilNode->getOrCreateStateSet(); ss->setRenderBinDetails(bin,"RenderBin"); osg::Stencil *stencil = new osg::Stencil(); // test always, write 1 stencil->setFunction(osg::Stencil::ALWAYS,0,~0u); // replace existing value stencil->setOperation(osg::Stencil::KEEP,osg::Stencil::KEEP,osg::Stencil::REPLACE); ss->setAttributeAndModes(stencil,osg::StateAttribute::ON); //ss->setMode(GL_CULL_FACE, //osg::StateAttribute::OFF); float boxSize = 3000.0f; osg::ShapeDrawable *sd = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), boxSize,boxSize,0)); //sd->setColor(osg::Vec4(1, 1, 1, 1)); stencilNode->addDrawable(sd); return stencilNode; } osg::Geode *makeStencilNode(int bin) { osg::Geode *stencilNode = new osg::Geode(); // disable color write getNodeAttribute(stencilNode) ->setMask(false,false,false,false); // disable depth write getNodeAttribute(stencilNode) ->setWriteMask(false); osg::StateSet *ss = stencilNode->getOrCreateStateSet(); ss->setRenderBinDetails(bin,"RenderBin"); osg::Stencil *stencil = new osg::Stencil(); // enable stencil test?? //osg::Stencil* stencil = getNodeAttribute(stencilNode); // test always, write 1 stencil->setFunction(osg::Stencil::ALWAYS,1,~0u); // replace existing value stencil->setOperation(osg::Stencil::KEEP,osg::Stencil::KEEP,osg::Stencil::REPLACE); ss->setAttributeAndModes(stencil,osg::StateAttribute::ON); //ss->setMode(GL_CULL_FACE, // osg::StateAttribute::OFF); float boxSize = 50.0f; osg::ShapeDrawable *sd = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), boxSize,boxSize,0)); //sd->setColor(osg::Vec4(1, 1, 1, 1)); stencilNode->addDrawable(sd); return stencilNode; } /* would like to use this at some point. found in osg demo files. */ class MotionBlurDrawCallback: public osgProducer::OsgSceneHandler::Callback { public: MotionBlurDrawCallback(double persistence) : cleared_(false), persistence_(persistence) { } virtual void operator()(osgProducer::OsgSceneHandler &handler, Producer::Camera &camera) { double t = handler.getSceneView()->getFrameStamp()->getReferenceTime(); if (!cleared_) { // clear the accumulation buffer glClearColor(0, 0, 0, 0); glClear(GL_ACCUM_BUFFER_BIT); cleared_ = true; t0_ = t; } double dt = fabs(t - t0_); t0_ = t; // call the scene handler's draw function handler.drawImplementation(camera); // compute the blur factor double s = powf(0.2, dt / persistence_); // scale, accumulate and return glAccum(GL_MULT, s); glAccum(GL_ACCUM, 1 - s); glAccum(GL_RETURN, 1.0f); } private: bool cleared_; double t0_; double persistence_; }; /* function used to add main rooms and triggers */ osg::Group *addARTModel(unsigned int markerId,char *name,float sizeModel,float shiftX, float shiftY, float heightMarker, float degrees, std::string trigFile, int bin,osg::Group *parent, std::map &stateMap) { osg::Group *maskedGroup = new osg::Group(); osg::Stencil *s = new osg::Stencil(); s->setFunction(osg::Stencil::EQUAL,1,~0u); s->setOperation(osg::Stencil::KEEP,osg::Stencil::KEEP,osg::Stencil::KEEP); osg::StateSet* mss = maskedGroup->getOrCreateStateSet(); mss->setAttributeAndModes(s,osg::StateAttribute::ON); mss->setRenderBinDetails(bin+1,"RenderBin"); stateMap[markerId] = mss; // create a new node by reading in model from file osg::Group *modelNode = osgDB::readNodeFile(name)->asGroup(); osg::Group *trigNode = osgDB::readNodeFile(trigFile)->asGroup(); //put model in origin osg::Matrix modelTranslate; osg::Matrix modelRot; osg::Matrix modelScale; osg::MatrixTransform *unitTransform = new osg::MatrixTransform; osg::BoundingSphere bound=modelNode->getBound(); modelTranslate.makeTranslate(-bound.center()); unitTransform->postMult(modelTranslate); modelScale.makeScale(sizeModel,sizeModel,sizeModel); unitTransform->postMult(modelScale); trigNode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON); modelNode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF); unitTransform->addChild(modelNode); unitTransform->addChild(trigNode); //put model on the marker (not on the middle) osg::MatrixTransform *trackerCenterTransform = new osg::MatrixTransform; osg::Matrix artCenter; artCenter.makeTranslate(shiftX,shiftY,heightMarker); trackerCenterTransform->postMult(artCenter); trackerCenterTransform->addChild(unitTransform); // create marker osg::ref_ptr marker = osgART::TrackerManager::getInstance()->getTracker(0)->getMarker(markerId); // check before accessing the linked marker if (!marker.valid()) { osg::notify(osg::FATAL) << "No Marker defined!" << std::endl; exit(-1); } // activate the marker marker->setActive(true); // create a matrix transform related to the marker osg::MatrixTransform *markerTrans = new osgART::ARTTransform(marker.get()); maskedGroup->addChild(trackerCenterTransform); markerTrans->addChild(maskedGroup); //markerTrans->addChild(trackerCenterTransform); markerTrans->addChild(makeStencilNode(bin)); markerTrans->addChild(makeStencilClearingNode(bin+2)); parent->addChild(markerTrans); return markerTrans; } float clampUnity( float x ) { if ( x > 1.0f ) return 1.0f; if ( x < -1.0f ) return -1.0f; return x ; } /* originally found in the Delta3D source. implementation converted from * plib's sg.cxx PLIB - A Suite of Portable Game Libraries Copyright (C) * 1998,2002 Steve Baker For further information visit * http://plib.sourceforge.net */ osg::Vec3 MatrixToHpr(const osg::Matrix &rotation ) { osg::Vec3 hpr; osg::Matrix mat; osg::Vec3 col1(rotation(0, 0), rotation(0, 1), rotation(0, 2)); double s = col1.length(); const double magic_epsilon = 0.00001; if ( s <= magic_epsilon ) { hpr.set(0.0f, 0.0f, 0.0f); return hpr; } double oneOverS = 1.0f / s; for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++) mat(i, j) = rotation(i, j) * oneOverS; double sin_pitch = clampUnity(mat(1, 2)); double pitch = asin(sin_pitch); hpr[1] = osg::RadiansToDegrees(pitch); double cp = cos(pitch); if ( cp > -magic_epsilon && cp < magic_epsilon ) { double cr = clampUnity(-mat(2,1)); double sr = clampUnity(mat(0,1)); hpr[0] = 0.0f; hpr[2] = osg::RadiansToDegrees(atan2(sr,cr)); } else { double one_over_cp = 1.0 / cp ; double sr = clampUnity(-mat(0,2) * one_over_cp); double cr = clampUnity(mat(2,2) * one_over_cp); double sh = clampUnity(-mat(1,0) * one_over_cp); double ch = clampUnity(mat(1,1) * one_over_cp); if ( ( osg::equivalent(sh,0.0,magic_epsilon) && osg::equivalent(ch,0.0,magic_epsilon) ) || ( osg::equivalent(sr,0.0,magic_epsilon) && osg::equivalent(cr,0.0,magic_epsilon) ) ) { cr = clampUnity(-mat(2,1)); sr = clampUnity(mat(0,1));; hpr[0] = 0.0f; } else { hpr[0] = osg::RadiansToDegrees(atan2(sh, ch)); } hpr[2] = osg::RadiansToDegrees(atan2(sr, cr)); } return hpr; } /* a struct for our triggers */ struct trigStruct { std::string trig; std::string room; std::string dest; }; /* check if we hit objects with bounding boxes unused but left here in case * it's useful one day. replaced by getHitObjectRay */ bool getHitObjectBbox(osg::Geode *triggerList[], int listSize, osg::Vec3f vecEnd) { printf("this is vecEnd %f %f %f \n ", vecEnd.x(), vecEnd.y(), vecEnd.z()); for (int i = 0; i < listSize; i++) { const osg::BoundingSphere &bbox = triggerList[i]->getBound(); printf("this is center of bbox %f %f %f \n", bbox.center().x(), bbox.center().y(), bbox.center().z()); if (bbox.contains(vecEnd)) // intersects never { printf("* * * hit trigger box * * * \n"); return 1; } } } /* return a geode based on string . this is important as is used to * iterate through the scenegraph to find actual objects whose names are * defined in Blender. */ osg::Geode *getGeode(std::string name, osg::Group *group) { //printf("getGeode(%d,group)\n",name.c_str()); findName _fn = findName(name); _fn.apply(*group); osg::ref_ptr _group = _fn._foundNodes.front(); osg::Geode *_geode = dynamic_cast(_group->getChild(0)); return _geode; } /* return the name of an object hit. messy but works fast enough. */ std::string getHitObjectRay(std::vector > triggerList, std::vector triggerNames, int arrayLen, osg::Group *scene, osg::Vec3f vecBegin, osg::Vec3f vecEnd, std::string room) { osg::LineSegment *ray = new osg::LineSegment(); osgUtil::IntersectVisitor intersectVisitor; intersectVisitor.setNodeMaskOverride(0x1); //setup ray related stuff ray->set(vecBegin, vecEnd); intersectVisitor.addLineSegment(ray); scene->accept(intersectVisitor); osgUtil::IntersectVisitor::HitList hitList; hitList = intersectVisitor.getHitList(ray); osgUtil::Hit hitResults; printf("our ray has hit %i objects \n", hitList.size()); //printf("this is the current node mask %i \n ", intersectVisitor.getNodeMaskOverride()); if (!hitList.empty()) { // not used, but it should be in here after the guard anyhow // osg::Geode *roomGeode = getGeode(room, scene); osgUtil::Hit results = hitList.front(); osg::Vec3 _vec = vecBegin - results.getWorldIntersectPoint(); float len = _vec.length(); printf("this is the length of the vector %f \n", len); osg::Geode *hitGeode = results.getGeode(); for (int j = 0; j < arrayLen ; j++) { if (results.getGeode() == triggerList[j].get() and len < 8) { printf("we hit trigger: %s \n", triggerNames[j].trig.c_str()); return triggerNames[j].trig; } } return std::string("wall"); } else { return std::string("NULL"); } } /* keep our feet on the ground.. */ float getFloor(osg::Group *scene, osg::Vec3f vecBegin, osg::Vec3f vecEnd) { osg::LineSegment *ray = new osg::LineSegment(); osgUtil::IntersectVisitor intersectVisitor; intersectVisitor.setNodeMaskOverride(0x1); //setup ray related stuff ray->set(vecBegin, vecEnd); intersectVisitor.addLineSegment(ray); scene->accept(intersectVisitor); osgUtil::IntersectVisitor::HitList hitList; hitList = intersectVisitor.getHitList(ray); osgUtil::Hit hitResults; printf("our floor ray has hit %i objects \n", hitList.size()); float len; if (!hitList.empty()) { osgUtil::Hit results = hitList.front(); osg::Vec3 _vec = vecBegin - results.getWorldIntersectPoint(); len = _vec.length(); printf("this is the distance to floor %f \n", len); return len; } else { return -1.0; // we fell through the floor } } /* get the intersection point on a ray collision. used every frame the character's in use. */ osg::Vec3 getRayIntersect(osg::Group *scene, osg::Vec3f vecBegin, osg::Vec3f vecEnd) { osg::Node::NodeMask mask = ~0x1; osg::LineSegment *ray = new osg::LineSegment(); osgUtil::IntersectVisitor intersectVisitor; intersectVisitor.setNodeMaskOverride(0x1); intersectVisitor.setTraversalMask(mask); //setup ray related stuff ray->set(vecBegin, vecEnd); intersectVisitor.addLineSegment(ray); scene->accept(intersectVisitor); osgUtil::IntersectVisitor::HitList hitList; hitList = intersectVisitor.getHitList(ray); if (!hitList.empty()) { osgUtil::Hit hitResults = hitList.front(); osg::Vec3 newVec = hitResults.getWorldIntersectPoint(); return newVec; } else { printf("we didn't hit anything\n"); } } /* make a path through a node hierachy to be traversed by utility functions. * credit goes to Loic Dachary for this (taken from the MAF code, license compatible) */ void createNodePath(osg::Node *_src, osg::NodePath &_path, int _parentValidMask) { assert(_src); osg::NodePath path; osg::Node *node = _src; while(node) { _path.push_back(node); int nbParents = node->getNumParents(); if (!nbParents) break; osg::Node *child; child = node->getParent(0); #if OPENSCENEGRAPH_VERSION >= 100 if (std::string(child->className()) == std::string("CameraNode")) { child = 0; break; } #endif node = child; } std::reverse(_path.begin(), _path.end()); } /* convert local coords to world coords. utility function used often. */ osg::Matrix computeLocalToWorld(osg::Group *group, int _parentValidMask, int _nodeMaskExclude, int _nodeMaskStop) { osg::Node *_src = group->getChild(0); static osg::NodePath path; path.resize(0); createNodePath(_src, path, _parentValidMask); return osg::computeLocalToWorld(path); } /* draws a bounding box in world coords around a group as argument. can't * remember why i wrote this, probably in an attempt to make more reliable * triggers. */ osg::BoundingBox bBoxToWorld(osg::Group *group, osg::BoundingBox bBox, osg::Vec3 worldCenter) { osg::Matrix nodeMatrix = computeLocalToWorld(group, 1, 0, 0); osg::Quat nodeOr = nodeMatrix.getRotate(); osg::Vec3 trans = nodeMatrix.getTrans(); osg::Vec3 mins = osg::Vec3(trans.x() + bBox.xMin(), trans.y() + bBox.yMin(), trans.z() + bBox.zMin()); osg::Vec3 maxs = osg::Vec3(trans.x() + bBox.xMax(), trans.y() + bBox.yMax(), trans.z() + bBox.zMax()); osg::BoundingBox newBox = osg::BoundingBox(mins, maxs); return newBox; } /* launch our cal3d anims. */ void launchAnim(int newAnim, int curAnim, float blendTime, CalModel *model) { model->getMixer()->clearCycle(curAnim, blendTime); model->getMixer()->blendCycle(newAnim, 1, blendTime); printf("this is newAnim, curAnim %d %d \n", newAnim, curAnim); } /* this was intended to find if the character's orientation matches that of a * trigger object it encounters. this would be needed if levelHead was written such that * the character was a child of each room node rather than the current implementation where * there is just one character in the sceneGroup rather than each room node. */ bool matchOrByName(const char *name, osg::Matrix charMatrix, osg::Group *searchGroup) { findName _fn = findName(name); _fn.apply(*searchGroup); osg::ref_ptr _group = _fn._foundNodes.front(); osg::Matrix nodeMatrix = computeLocalToWorld(_group.get(), 1, 0, 0); osg::Quat nodeOr = nodeMatrix.getRotate(); printf("this is nodeOr %f %f %f \n", nodeOr.x(), nodeOr.y(), nodeOr.z()); if (nodeOr == charMatrix.getRotate()) { return 1; } } /* make a list of geodes that contain the triggerable objects. these are cycled through in the detection of trigger events. * uses a struct 'trigStruct'. run once each time the character enters a room. */ osg::Geode *makeGeodeList(trigStruct *names, osg::Group &group, int length) { osg::Geode *geodes[length]; for (int i = 0; i < length; i++) { osg::Geode *_g; std::string _s = names[i].trig; _g = getGeode(_s, &group); geodes[i] = _g; printf("added %s to found triggers list \n", names[i].trig.c_str()); } return *geodes; } /* this function accepts a string for an object and returns its world * position in the scenegraph. */ osg::Vec3 findPosByName(std::string name, osg::Group *group) { findName _fn = findName(name); _fn.apply(*group); osg::ref_ptr _group = _fn._foundNodes.front(); osg::Vec3 pos = _group.get()->computeBound().center(); return pos; } /* function to set up the character. there's perhaps a lot done here that could * be optomised. note that i'm casting rays between actual nodes rather than * discrete points. this is due to the way i derive world-coordinates from * local-coords. it's also handy in the positioning of objects to help finding * out where the rays were during debugging. * */ osg::PositionAttitudeTransform *setupChar(std::string dest, osg::Group *searchGroup, float roomScale) { osg::Vec3 pos; osg::Matrix dummy; osg::Matrix charTrans; osg::Matrix charRotateZ; osg::Matrix charRotateY; osg::Matrix charRotateX; osg::Matrix modelScale; osg::PositionAttitudeTransform *charPAT = new osg::PositionAttitudeTransform; osg::Group *character = addCharacter()->asGroup(); character->setNodeMask(0x1); character->setName("character"); charPAT->addChild(character); osg::Group *rayEndGroup = new osg::Group(); osg::Matrix rayEndMat; rayEndMat.setTrans(0.0,100.0,0.0); osg::MatrixTransform *rayEndMatrixTransform = new osg::MatrixTransform; rayEndMatrixTransform->setMatrix(rayEndMat); rayEndMatrixTransform->addChild(rayEndGroup); osg::Group *floorRayGroup = new osg::Group(); osg::Matrix floorRayMat; floorRayMat.setTrans(0.0,0.0,-100.0); osg::MatrixTransform *floorRayMatrixTransform = new osg::MatrixTransform; floorRayMatrixTransform->setMatrix(floorRayMat); floorRayMatrixTransform->addChild(floorRayGroup); osg::Group *rayStepBeginGroup = new osg::Group(); osg::Matrix rayStepBeginMat; rayStepBeginMat.setTrans(0.0,0.0,6.0); osg::MatrixTransform *rayStepBeginMatrixTransform = new osg::MatrixTransform; rayStepBeginMatrixTransform->setMatrix(rayStepBeginMat); rayStepBeginMatrixTransform->addChild(rayStepBeginGroup); osg::Group *rayStepEndGroup = new osg::Group(); osg::Matrix rayStepEndMat; rayStepEndMat.setTrans(0.0,100,6.0); // step trigger indicator osg::MatrixTransform *rayStepEndMatrixTransform = new osg::MatrixTransform; rayStepEndMatrixTransform->setMatrix(rayStepEndMat); rayStepEndMatrixTransform->addChild(rayStepEndGroup); /* dummy node to see where end of the ray is osg::Group *testGroup = osgDB::readNodeFile("models/end.osg")->asGroup(); testGroup->setNodeMask(0x1); osg::Matrix testMat; //testMat.setTrans(0.0,10.0,7.5); testMat.setTrans(0.0,0.0,0.0); osg::MatrixTransform *testMatrixTransform = new osg::MatrixTransform; testMatrixTransform->setMatrix(testMat); testMatrixTransform->addChild(testGroup); osg::Group *testGroup2 = osgDB::readNodeFile("models/end.osg")->asGroup(); testGroup2->setNodeMask(0x1); osg::Matrix testMat2; //testMat.setTrans(0.0,10.0,7.5); testMat2.setTrans(0.0,6.0,6.0); osg::MatrixTransform *testMatrixTransform2 = new osg::MatrixTransform; testMatrixTransform2->setMatrix(testMat2); testMatrixTransform2->addChild(testGroup2); */ charPAT->setScale(osg::Vec3d(roomScale, roomScale, roomScale)); // inserted rather than added just to be sure i know what's where later. charPAT->insertChild(1, rayStepEndMatrixTransform); charPAT->insertChild(2, rayStepBeginMatrixTransform); charPAT->insertChild(3, floorRayMatrixTransform); charPAT->insertChild(4, rayEndMatrixTransform); //charPAT->insertChild(5, testMatrixTransform); //charPAT->insertChild(6, testMatrixTransform2); charPAT->setPosition(osg::Vec3(0, 0, 0)); return charPAT; } osg::Geode *addTimerLabel(int size, std::string label, osg::Vec3 pos, int beamer, osg::Vec4 colour) { osgText::Text *levelText = new osgText::Text(); levelText->setCharacterSize(size); levelText->setFontResolution(64, 48); //levelText->setBackdropType(osgText::Text::OUTLINE); //levelText->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); //levelText->setBackdropColor( osg::Vec4(.3, .3, .3, 1) ); levelText->setColor(colour); levelText->setFont("fonts/Bandal.ttf"); levelText->setText(label); levelText->setAxisAlignment(osgText::Text::XY_PLANE); levelText->setDrawMode(osgText::Text::TEXT | osgText::Text::ALIGNMENT); levelText->setPosition(osg::Vec3(pos[0], pos[1], pos[2])); levelText->setAlignment(osgText::Text::LEFT_TOP); osg::Matrix matBeamer; // for projectors matBeamer.makeRotate(osg::DegreesToRadians(180.0), osg::Vec3f(0.0, 1.0, 0.0)); osg::Quat beamerQuat = matBeamer.getRotate(); osg::Matrix matScreen; // for screens matScreen.makeRotate(osg::DegreesToRadians(0.0), osg::Vec3f(0.0, 0.0, 1.0)); osg::Quat screenQuat = matScreen.getRotate(); if (beamer) { levelText->setRotation(beamerQuat); } else { levelText->setRotation(screenQuat); } osg::Geode *levelTextGeode = new osg::Geode(); levelTextGeode->addDrawable(levelText); //levelTextGeode->setNodeMask(0); return levelTextGeode; } /* adds a label relevant to gameplay. */ osg::Geode *addGameLabel(int size, std::string label, osg::Vec3 pos, int beamer, osg::Vec4 colour) { osgText::Text *levelText = new osgText::Text(); levelText->setCharacterSize(size); levelText->setFontResolution(64, 48); //levelText->setBackdropType(osgText::Text::OUTLINE); //levelText->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); //levelText->setBackdropColor( osg::Vec4(.3, .3, .3, 1) ); levelText->setColor(colour); levelText->setFont("fonts/Bandal.ttf"); levelText->setText(label); levelText->setAxisAlignment(osgText::Text::XY_PLANE); levelText->setDrawMode(osgText::Text::TEXT | osgText::Text::ALIGNMENT); levelText->setPosition(osg::Vec3(pos[0], pos[1], pos[2])); levelText->setAlignment(osgText::Text::CENTER_TOP); osg::Matrix matBeamer; // for projectors matBeamer.makeRotate(osg::DegreesToRadians(180.0), osg::Vec3f(0.0, 1.0, 0.0)); osg::Quat beamerQuat = matBeamer.getRotate(); osg::Matrix matScreen; // for screens matScreen.makeRotate(osg::DegreesToRadians(0.0), osg::Vec3f(0.0, 0.0, 1.0)); osg::Quat screenQuat = matScreen.getRotate(); if (beamer) { levelText->setRotation(beamerQuat); } else { levelText->setRotation(screenQuat); } osg::Geode *levelTextGeode = new osg::Geode(); levelTextGeode->addDrawable(levelText); //levelTextGeode->setNodeMask(0); return levelTextGeode; } /* adds a room label. */ osg::Geode *addRoomLabel(int size, std::string label, std::string searchPos, osg::Vec3 adj, int beamer, osg::Group *searchGroup) { osg::Vec3f labelPos = findPosByName(searchPos, searchGroup); osgText::Text *levelText = new osgText::Text(); levelText->setCharacterSize(size); levelText->setFontResolution(64, 48); //levelText->setBackdropType(osgText::Text::OUTLINE); levelText->setBackdropType(osgText::Text::DROP_SHADOW_BOTTOM_RIGHT); levelText->setBackdropOffset(.2); levelText->setFont("fonts/Bandal.ttf"); levelText->setText(label); levelText->setAxisAlignment(osgText::Text::XY_PLANE); levelText->setDrawMode(osgText::Text::TEXT | osgText::Text::ALIGNMENT); levelText->setColor( osg::Vec4(.8f, .8f, .8f, 1.0f) ); //levelText->setPosition(osg::Vec3(labelPos[0]+adj[0], labelPos[1]+adj[1], labelPos[2]+adj[2])); levelText->setAlignment(osgText::Text::CENTER_TOP); osg::Matrix matBeamer; // for projectors matBeamer.makeRotate(osg::DegreesToRadians(180.0), osg::Vec3f(0.0, 1.0, 0.0)); osg::Quat beamerQuat = matBeamer.getRotate(); osg::Matrix matScreen; // for screens matScreen.makeRotate(osg::DegreesToRadians(0.0), osg::Vec3f(0.0, 0.0, 1.0)); osg::Quat screenQuat = matScreen.getRotate(); if (beamer) { levelText->setRotation(beamerQuat); } else { levelText->setRotation(screenQuat); } osg::Geode *levelTextGeode = new osg::Geode(); levelTextGeode->addDrawable(levelText); levelTextGeode->setNodeMask(0x1); return levelTextGeode; } /* function to get the marker Z position in world coords. actually it's the center of the art, * not the marker itself. */ float getMarkerZPos(osg::ref_ptr marker) { osg::Matrix mat; mat = computeLocalToWorld(marker->asGroup(), 1, 0, 0); osg::Vec3 vec = mat.getTrans(); return vec.z(); } /* function to turn off all markers other than the one nearest to the viewplane * on a per cube basis. works well but on resetting the nodeMask for the marker the character * cannot reliably collide against the room node. apparently a setNodeMaskOverride or simliar * will work to that end. * use with the room nodes like so: if (tracker->getMarker(0)->isValid() and closest == 0) */ int renderNearestMarker(std::vector > markerPtrVec, osg::ref_ptr tracker, int lastClosestMarker) { std::vector markerDistVec(6); int closestMarker = -1; int valid = 0; for (int i = 0; i < 6; i++) { if (tracker->getMarker(i)->isValid()) { osg::Vec3 markerPos = tracker->getMarker(i)->getTransform().getTrans(); float dX = markerPos.x(); float dY = markerPos.y(); float dZ = markerPos.z(); float markerDist = sqrt(dX*dX + dY*dY + dZ*dZ); markerDistVec.at(i) = 0-markerDist; } else { markerDistVec.at(i) = -1000.0; } } closestMarker = std::distance(markerDistVec.begin(), std::max_element (markerDistVec.begin(), markerDistVec.end())); // turn off the node masking here if (closestMarker != lastClosestMarker) { for (int j = 0; j < 6; j++) { if (j != closestMarker) { markerPtrVec[j].get()->getChild(0)->setNodeMask(0); } else { markerPtrVec[j].get()->getChild(0)->setNodeMask(1); } } } printf("closest %i lastclosest %i \n", closestMarker, lastClosestMarker); lastClosestMarker = closestMarker; return closestMarker; } void charMATUpdate(osg::MatrixTransform *charMAT, osg::Vec3f pos, osg::Matrix charTrans, osg::Matrix markerMAT, osg::Matrix charRotateX, osg::Matrix charRotateY, osg::Matrix charRotateZ) { /* translate the marker matrix in relation to the start position. * dumb to do this every frame but works well with ARToolkitPlus's last-known-good-position. */ markerMAT.preMult(charTrans); /* set the character transform matrix to this matrix. * must be done every frame if not a child of the marker node */ charMAT->setMatrix(markerMAT); /* multiply by 'normal' orientation. only orientation with character and skeleton aligned when * exported out of Blender. */ osg::Vec4 X; osg::Vec4 Y; osg::Vec4 Z; X = osg::Vec4(0, 0, 0, 0); Y = osg::Vec4(90, 0, 0, 1); Z = osg::Vec4(90, 0, 1, 0); charRotateX.makeRotate(osg::DegreesToRadians(X[0]), X[1], X[2], X[3]); charRotateY.makeRotate(osg::DegreesToRadians(Y[0]), Y[1], Y[2], Y[3]); charRotateZ.makeRotate(osg::DegreesToRadians(Z[0]), Z[1], Z[2], Z[3]); charMAT->preMult(charRotateX); charMAT->preMult(charRotateY); charMAT->preMult(charRotateZ); charMAT->setNodeMask(1); // ensure character is visible while marker is active. dumb to call this every frame. } /* RoomManager and RoomData were written by pix to do away with the need for * 'setup' and 'active' global bools in the room setup code. they were getting * in the way during stencil development. they may not survive the refactoring * i hope to do for the room setup code. */ class RoomData { public: bool setup; std::string name; void setActive(bool b = true); bool isActive(); friend class RoomManager; protected: RoomData(std::string name) { this->name = name; setup=0; } }; class RoomManager { private: std::map roomMap; RoomData *activeRoom; RoomManager() { activeRoom = 0; } public: void unsetAll() { std::map::iterator i; for(i=roomMap.begin();i!=roomMap.end();i++) { i->second->setup=false; } } static RoomManager *instance() { static RoomManager *instance = new RoomManager(); return instance; } RoomData *getRoom(std::string name) { return roomMap[name]; } RoomData *getActiveRoom() { return activeRoom; } void setActiveRoom(RoomData *room,bool b) { if (b) activeRoom = room; else if(activeRoom==room) activeRoom=0; } RoomData *createRoom(std::string name) { roomMap[name]=new RoomData(name); } void printRooms() { osg::notify() << "rooms:\n" << std::endl; std::map::iterator i; for(i = roomMap.begin();i!=roomMap.end();i++) { osg::notify() << "index: " << i->first << " setup: " << i->second->setup?1:0; osg::notify() << " active? " << (i->second->isActive()?1:0) << std::endl; } } }; void RoomData::setActive(bool b) { RoomManager::instance()->setActiveRoom(this,b); } bool RoomData::isActive() { return RoomManager::instance()->getActiveRoom()==this; } /* this function is called every time the character enters a room */ void setupCharInRoom(std::string dest, osg::Group *group, osg::MatrixTransform &charMAT, osg::PositionAttitudeTransform &charPAT, osg::Matrix &charTrans, float roomScale, int y, int z, std::map stateMap, int s) { osg::Matrix dummy; osg::Vec3f pos; charMAT.setNodeMask(1); // ensure this is on. charMAT.setMatrix(dummy); pos = findPosByName(dest, group); charPAT.setStateSet(stateMap[s]); charPAT.setPosition(osg::Vec3f(0, 0, 0)); charTrans.setTrans(roomScale*(pos.x()), roomScale*(pos.y()+y), roomScale*(pos.z()+z)); } /* the main loop. */ int main(int argc, char* argv[]) { //osg::setNotifyLevel(osg::ALWAYS); /* levelHead executable takes a bool argument. this bool is used to flip * game labels so that they can still be read when levelHead is played on a * beamer in mirrored mode. */ if (argc < 6) { std::cout<<"not enough args"<setMinimumNumStencilBits(8); viewer.setUpViewer(osgProducer::Viewer::ESCAPE_SETS_DONE); viewer.getCullSettings().setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); /* #ifndef __linux viewer.getCamera(0)->getRenderSurface()->fullScreen(false); viewer.getCamera(0)->getRenderSurface()->setWindowRectangle(0,0,320,240); #endif */ if (!atoi(argv[2])) { viewer.getCamera(0)->getRenderSurface()->setWindowRectangle(0,0,atoi(argv[3]),atoi(argv[4])); // viewer accepts W/H arguments from argv } // load a video plugin osg::ref_ptr video = osgART::VideoManager::createVideoFromPlugin("osgart_artoolkit"); if (!video.valid()) { osg::notify(osg::FATAL) << "Could not initialize video!" << std::endl; exit(1); // quit program } /* load a tracker plugin */ char* tracker_plugin_name = getenv("TRACKER"); if(!tracker_plugin_name) tracker_plugin_name = "osgart_artoolkit_tracker"; osg::ref_ptr tracker = osgART::TrackerManager::createTrackerFromPlugin(tracker_plugin_name); if (tracker.valid()) { // access a field within the tracker osg::ref_ptr< osgART::TypedField > _threshold = reinterpret_cast< osgART::TypedField* >(tracker->get("threshold")); // values can only be accessed through a get()/set() mechanism if (_threshold.valid()) { // set the threshold _threshold->set(150); // check what we actually get // osg::notify() << "Field 'threshold' = " << _threshold->get() << std::endl; } else { osg::notify() << "Field 'threshold' supported for this tracker" << std::endl; } } else { std::cerr << "Could not initialize tracker plugin!" << std::endl; exit(-1); // quit program } printf("video open....\n"); video->open(); //tracker->init(video->getWidth(), video->getHeight(),"Data/levelHead_markers.dat"); // ARToolkit markers used in the BETA //tracker->init(video->getWidth(), video->getHeight(),"Data/markerboard_480-499.cfg"); char *marker_file; if (strcmp(tracker_plugin_name,"osgart_artoolkitplus_tracker")==0) { marker_file = "Data/levelHead_simple.dat"; } else { marker_file = "Data/levelHead_markers.dat"; } tracker->init(video->getWidth(), video->getHeight(),marker_file); /* printf("lh:PROJECTION MATRIX:\n"); for(int j=0;j<4;j++) { for(int i=0;i<4;i++) { printf(" %f",tracker->getProjectionMatrix()[(j*4)+i]); } printf("\n"); } */ // adding the video background osg::Group *foregroundGroup = new osg::Group(); osgART::VideoBackground *videoBackground=new osgART::VideoBackground(video.get()); videoBackground->setTextureMode(osgART::GenericVideoObject::USE_TEXTURE_RECTANGLE); videoBackground->init(); foregroundGroup->addChild(videoBackground); foregroundGroup->getOrCreateStateSet()->setRenderBinDetails(2, "RenderBin"); osg::Projection* projectionMatrix = new osg::Projection(osg::Matrix(tracker->getProjectionMatrix())); //create scene to hold all markers osg::Group* sceneGroup = new osg::Group(); sceneGroup->getOrCreateStateSet()->setRenderBinDetails(5, "RenderBin"); foregroundGroup->addChild(sceneGroup); //normalize for environment mapping sceneGroup->getOrCreateStateSet()->setMode(GL_NORMALIZE, osg::StateAttribute::ON); sceneGroup->getOrCreateStateSet()->setAttribute(new osg::LightModel()); /* motion blur. would be good to find a non-gratutious use for it. osg::DisplaySettings::instance()->setMinimumNumAccumBits(8,8,8,8); osgProducer::Viewer::SceneHandlerList &shl = viewer.getSceneHandlerList(); for (osgProducer::Viewer::SceneHandlerList::iterator i=shl.begin(); i!=shl.end(); ++i) { (*i)->setDrawCallback(new MotionBlurDrawCallback(.25)); } */ /* playing around with this can look great.. double roomScale = 0.7; double roomZOff = -27; double roomScale = 1.0; try these. wrong scale does v'interesting things. double roomZOff = -40; */ double roomScale = 0.6; double roomZOff = -27; std::string lastRoom("entrance hall"); /* room/level start position starting positions definable for testing. */ /* level 1 start positions */ std::string presence("entrance hall"); std::string room("entrance hall"); std::string dest("l1startDest"); /* std::string presence("garage"); std::string room("garage"); std::string dest("l1r1t1"); */ /* std::string presence("machine room"); std::string room("machine room"); std::string dest("l1r2t1"); */ /* std::string presence("storeroom"); std::string room("storeroom"); std::string dest("l1r3t1"); */ /* std::string presence("causeway"); std::string room("causeway"); std::string dest("l1r6t3"); */ /* std::string presence("exit hall"); std::string room("exit hall"); std::string dest("l1r5t2"); */ /* level2 start positions */ /* std::string presence("chamber 1"); std::string room("chamber 1"); std::string dest("l2startDest"); */ /* std::string presence("workshop"); std::string room("workshop"); std::string dest("l2r1t1"); */ /* std::string presence("chamber 2"); std::string room("chamber 2"); std::string dest("l2r5t2"); */ /* std::string presence("interchange 2"); std::string room("interchange 2"); std::string dest("l2r4t1"); */ /* std::string presence("interchange 1"); std::string room("interchange 1"); std::string dest("l2r5t4"); */ /* std::string presence("dispatch bay"); std::string room("dispatch bay"); std::string dest("l2r4t3"); */ /* level3 start positions */ /* std::string presence("loft 1"); std::string room("loft 1"); std::string dest("l3startDest"); */ /* std::string presence("loft 3"); std::string room("loft 3"); std::string dest("l3r2t3"); */ /* std::string presence("loft 4"); std::string room("loft 4"); std::string dest("l3r1t2"); */ /* std::string presence("loft 5"); std::string room("loft 5"); std::string dest("l3r6t1"); */ /* std::string presence("loft 6"); std::string room("loft 6"); std::string dest("l3r4t2"); */ /* character setup */ osg::PositionAttitudeTransform *charPAT = setupChar(dest, foregroundGroup, roomScale); // make sure rays case don't collide with character mesh charPAT->getChild(0)->asGroup()->setNodeMask(0x1); // cast to the model itself so we can later call animations. osg::ref_ptr charModelPtr = dynamic_cast(charPAT->getChild(0)->asGroup()->getChild(0)); osg::MatrixTransform *charMAT = new osg::MatrixTransform; charMAT->addChild(charPAT); osg::Vec3 rayBegin; osg::Matrix rayEndGroupMatrix; osg::Matrix floorRayGroupMatrix; osg::Matrix rayStepBeginGroupMatrix; osg::Matrix rayStepEndGroupMatrix; osg::Vec3 baseRayBegin; osg::Vec3 stepRayBegin; osg::Vec3 stepRayEnd; osg::Vec3 baseRayEnd; osg::Vec3 floorRayIntersect; osg::Vec3 stepRayIntersect; osg::Vec3 baseRayIntersect; osg::Vec3 vecStart; osg::Vec3 vecEnd; osg::Vec3d newTrans; osg::Vec3 posWorld; osg::Vec3 curTrans = osg::Vec3(); // matrices for orientation osg::Matrix matEast; osg::Matrix matWest; osg::Matrix matNorth; osg::Matrix matSouth; // basic pivot axis osg::Vec3f pivotAxis = osg::Vec3f(0.0, 0.0, 1.0); // orientation rotations matWest.makeRotate(osg::DegreesToRadians(0.0), pivotAxis); matEast.makeRotate(osg::DegreesToRadians(180.0), pivotAxis); matNorth.makeRotate(osg::DegreesToRadians(-90.0), pivotAxis); matSouth.makeRotate(osg::DegreesToRadians(90.0), pivotAxis); // quats are better to work with osg::Quat quatEast = matEast.getRotate(); osg::Quat quatWest = matWest.getRotate(); osg::Quat quatNorth = matNorth.getRotate(); osg::Quat quatSouth = matSouth.getRotate(); // make a master transform matrix to handle global orientation osg::Matrix charTrans; osg::Matrix charRotateX; osg::Matrix charRotateY; osg::Matrix charRotateZ; osg::Vec3f pos; osg::Vec3d lastGoodPos; osg::Matrix dummy; osg::Matrixf markerMAT; osg::Matrix charPATMatrix; const char *dir = ""; float mov = 0.1; float step = 0.01; //float tiltSens = 6.0; float tiltSens = 8.0; float walkSens = 40.0; int start = 0; int newAnim = 0; int curAnim = -1; float jump = 0; int stairs = 0; int moving = 0; int gravIndex = 0; int NSIndex = 0; // North South selector int WEIndex = 0; // West East selector int hprX = 0; // HPR selectors int hprY = 0; /* trigger container setup */ trigStruct trigs[4]; typedef std::vector > geodeVec; geodeVec triggerList(10); typedef std::vector trigsVec; trigsVec triggerNames(10); osg::Vec3 *triggerPos; int numTriggers; float hitDist = 100; // big to begin with float gravity; float floorRayDiff; float stepHitDist; std::string hitResults; /* important global vars */ //int active = 0; int wall = 0; int count = 0; int entered = 0; double curTime = 0.0; int restart = 0; int level = 1; /* label setup */ // some colours for labels etc osg::Vec4 red = osg::Vec4(1, 0, 0, 1); osg::Vec4 green = osg::Vec4(0, 1, 0, 1); osg::Vec4 blue = osg::Vec4(0, 0, 1, 1); osg::Vec4 yellow = osg::Vec4(1, .9, 0, 1); osg::Vec4 orange = osg::Vec4(1, .5, 0, 1); osg::Vec4 grey = osg::Vec4(.5, .5, .5, 1); osg::Vec4 white = osg::Vec4(1, 1, 1, 1); osg::Vec4 black = osg::Vec4(0, 0, 0, 1); osg::Geode *roomLabelTop = addGameLabel(2, "find the room named entrance", osg::Vec3(0, 24, 1), atoi(argv[1]), yellow); osg::ref_ptr roomLabelTopPtr = dynamic_cast(roomLabelTop->getDrawable(0)); roomLabelTop->setNodeMask(1); osg::Geode *roomLabelBottom = addGameLabel(2, "look in the red cube", osg::Vec3(0, -23, 1), atoi(argv[1]), red); osg::ref_ptr roomLabelBottomPtr = dynamic_cast(roomLabelBottom->getDrawable(0)); std::map stateMap; /* level 1 setup */ /* the new index at the end is the render bin.. not that it will use bin, bin+1 and bin+2 */ osg::Node *l1room1Mesh = addARTModel(0,"models/l1room1.osg", roomScale, 0, 0 , roomZOff, 90, "models/l1room1_trigs.osg", 110, sceneGroup, stateMap); osg::Node *l1room2Mesh = addARTModel(1,"models/l1room2.osg", roomScale, 0, 0 , roomZOff, 90, "models/l1room2_trigs.osg", 120, sceneGroup, stateMap); osg::Node *l1room3Mesh = addARTModel(2,"models/l1room3.osg", roomScale, 0, 0 , roomZOff, 90, "models/l1room3_trigs.osg", 130, sceneGroup, stateMap); osg::Node *l1room4Mesh = addARTModel(3,"models/l1room4.osg", roomScale, 0, 0 , roomZOff, 90, "models/l1room4_trigs.osg", 140, sceneGroup, stateMap); osg::Node *l1room5Mesh = addARTModel(4,"models/l1room5.osg", roomScale, 0, 0 , roomZOff, 90, "models/l1room5_trigs.osg", 150, sceneGroup, stateMap); osg::Node *l1room6Mesh = addARTModel(5,"models/l1room6.osg", roomScale, 0, 0 , roomZOff, 90, "models/l1room6_trigs.osg", 160, sceneGroup, stateMap); osg::ref_ptr markerPtr1 = dynamic_cast(l1room1Mesh); osg::ref_ptr markerPtr2 = dynamic_cast(l1room2Mesh); osg::ref_ptr markerPtr3 = dynamic_cast(l1room3Mesh); osg::ref_ptr markerPtr4 = dynamic_cast(l1room4Mesh); osg::ref_ptr markerPtr5 = dynamic_cast(l1room5Mesh); osg::ref_ptr markerPtr6 = dynamic_cast(l1room6Mesh); /* osg::MatrixTransform* markerPtr1 = room1Mesh->asTransform()->asMatrixTransform(); osg::MatrixTransform* markerPtr2 = room2Mesh->asTransform()->asMatrixTransform(); osg::MatrixTransform* markerPtr3 = room3Mesh->asTransform()->asMatrixTransform(); osg::MatrixTransform* markerPtr4 = room4Mesh->asTransform()->asMatrixTransform(); osg::MatrixTransform* markerPtr5 = room5Mesh->asTransform()->asMatrixTransform(); osg::MatrixTransform* markerPtr6 = room6Mesh->asTransform()->asMatrixTransform(); */ osg::Group *l1room1Labels = new osg::Group(); osg::Group *l1room2Labels = new osg::Group(); osg::Group *l1room3Labels = new osg::Group(); osg::Group *l1room4Labels = new osg::Group(); osg::Group *l1room5Labels = new osg::Group(); osg::Group *l1room6Labels = new osg::Group(); l1room1Labels->addChild(roomLabelTop); l1room2Labels->addChild(roomLabelTop); l1room3Labels->addChild(roomLabelTop); l1room4Labels->addChild(roomLabelTop); l1room5Labels->addChild(roomLabelTop); l1room6Labels->addChild(roomLabelTop); l1room1Labels->addChild(roomLabelBottom); l1room2Labels->addChild(roomLabelBottom); l1room3Labels->addChild(roomLabelBottom); l1room4Labels->addChild(roomLabelBottom); l1room5Labels->addChild(roomLabelBottom); l1room6Labels->addChild(roomLabelBottom); l1room1Labels->addChild(addRoomLabel(3, "entrance", "l1r1label", osg::Vec3(0, 0, -10), atoi(argv[1]), foregroundGroup)); l1room2Labels->addChild(addRoomLabel(3, "garage", "l1r2label", osg::Vec3(0, 0, -10), atoi(argv[1]), foregroundGroup)); l1room3Labels->addChild(addRoomLabel(3, "machine room", "l1r3label", osg::Vec3(0, 0, -10), atoi(argv[1]), foregroundGroup)); l1room4Labels->addChild(addRoomLabel(3, "storeroom", "l1r4label", osg::Vec3(0, 0, -10), atoi(argv[1]), foregroundGroup)); l1room5Labels->addChild(addRoomLabel(3, "causeway", "l1r5label", osg::Vec3(0, 0, 0), atoi(argv[1]), foregroundGroup)); l1room6Labels->addChild(addRoomLabel(3, "exit hall", "l1r6label", osg::Vec3(0, 0, -10), atoi(argv[1]), foregroundGroup)); l1room1Labels->setStateSet(stateMap[0]); l1room2Labels->setStateSet(stateMap[1]); l1room3Labels->setStateSet(stateMap[2]); l1room4Labels->setStateSet(stateMap[3]); l1room5Labels->setStateSet(stateMap[4]); l1room6Labels->setStateSet(stateMap[5]); markerPtr1->addChild(l1room1Labels); markerPtr2->addChild(l1room2Labels); markerPtr3->addChild(l1room3Labels); markerPtr4->addChild(l1room4Labels); markerPtr5->addChild(l1room5Labels); markerPtr6->addChild(l1room6Labels); trigStruct l1r1t1 = {std::string("l1r1d1"), std::string("garage"), std::string("l1r1t1")}; numTriggers = 1; trigsVec l1r1TrigNames(10); l1r1TrigNames.clear(); geodeVec l1r1TrigList(10); l1r1TrigList.clear(); l1r1TrigNames.resize(1); l1r1TrigList.resize(1); l1r1TrigNames[0] = l1r1t1; osg::Geode *l1r1Trig = getGeode(l1r1TrigNames[0].trig, foregroundGroup); l1r1TrigList[0] = l1r1Trig; /* level 2 setup */ osg::Node *l2room1Mesh = addARTModel(6,"models/l2room1.osg", roomScale, 0, 0 , roomZOff, 90, "models/l2room1_trigs.osg", 210, sceneGroup, stateMap); osg::Node *l2room2Mesh = addARTModel(7,"models/l2room2.osg", roomScale, 0, 0 , roomZOff, 90, "models/l2room2_trigs.osg", 220, sceneGroup, stateMap); osg::Node *l2room3Mesh = addARTModel(8,"models/l2room3.osg", roomScale, 0, 0 , roomZOff, 90, "models/l2room3_trigs.osg", 230, sceneGroup, stateMap); osg::Node *l2room4Mesh = addARTModel(9,"models/l2room4.osg", roomScale, 0, 0 , roomZOff, 90, "models/l2room4_trigs.osg", 240, sceneGroup, stateMap); osg::Node *l2room5Mesh = addARTModel(10,"models/l2room5.osg", roomScale, 0, 0 , roomZOff, 90, "models/l2room5_trigs.osg", 250, sceneGroup, stateMap); osg::Node *l2room6Mesh = addARTModel(11,"models/l2room6.osg", roomScale, 0, 0 , roomZOff, 90, "models/l2room6_trigs.osg", 260, sceneGroup, stateMap); osg::ref_ptr markerPtr7 = dynamic_cast(l2room1Mesh); osg::ref_ptr markerPtr8 = dynamic_cast(l2room2Mesh); osg::ref_ptr markerPtr9 = dynamic_cast(l2room3Mesh); osg::ref_ptr markerPtr10 = dynamic_cast(l2room4Mesh); osg::ref_ptr markerPtr11 = dynamic_cast(l2room5Mesh); osg::ref_ptr markerPtr12 = dynamic_cast(l2room6Mesh); osg::Group *l2room1Labels = new osg::Group(); osg::Group *l2room2Labels = new osg::Group(); osg::Group *l2room3Labels = new osg::Group(); osg::Group *l2room4Labels = new osg::Group(); osg::Group *l2room5Labels = new osg::Group(); osg::Group *l2room6Labels = new osg::Group(); l2room1Labels->addChild(roomLabelTop); l2room2Labels->addChild(roomLabelTop); l2room3Labels->addChild(roomLabelTop); l2room4Labels->addChild(roomLabelTop); l2room5Labels->addChild(roomLabelTop); l2room6Labels->addChild(roomLabelTop); l2room1Labels->addChild(roomLabelBottom); l2room2Labels->addChild(roomLabelBottom); l2room3Labels->addChild(roomLabelBottom); l2room4Labels->addChild(roomLabelBottom); l2room5Labels->addChild(roomLabelBottom); l2room6Labels->addChild(roomLabelBottom); l2room1Labels->addChild(addRoomLabel(3, "chamber 1", "l2r1label", osg::Vec3(0, -10, -10), atoi(argv[1]), foregroundGroup)); l2room2Labels->addChild(addRoomLabel(3, "workshop", "l2r2label", osg::Vec3(0, -10, -10), atoi(argv[1]), foregroundGroup)); l2room3Labels->addChild(addRoomLabel(3, "chamber 2", "l2r3label", osg::Vec3(0, -10, -10), atoi(argv[1]), foregroundGroup)); l2room4Labels->addChild(addRoomLabel(3, "interchange 1", "l2r4label", osg::Vec3(0, -10, -10), atoi(argv[1]), foregroundGroup)); l2room5Labels->addChild(addRoomLabel(3, "interchange 2", "l2r5label", osg::Vec3(0, -10, -10), atoi(argv[1]), foregroundGroup)); l2room6Labels->addChild(addRoomLabel(3, "dispatch bay", "l2r6label", osg::Vec3(0, -10, -10), atoi(argv[1]), foregroundGroup)); l2room1Labels->setStateSet(stateMap[6]); l2room2Labels->setStateSet(stateMap[7]); l2room3Labels->setStateSet(stateMap[8]); l2room4Labels->setStateSet(stateMap[9]); l2room5Labels->setStateSet(stateMap[10]); l2room6Labels->setStateSet(stateMap[11]); markerPtr7->addChild(l2room1Labels); markerPtr8->addChild(l2room2Labels); markerPtr9->addChild(l2room3Labels); markerPtr10->addChild(l2room4Labels); markerPtr11->addChild(l2room5Labels); markerPtr12->addChild(l2room6Labels); /* level 3 setup */ osg::Node *l3room1Mesh = addARTModel(12,"models/l3room1.osg", roomScale, 0, 0 , roomZOff, 90, "models/l3room1_trigs.osg", 310, sceneGroup, stateMap); osg::Node *l3room2Mesh = addARTModel(13,"models/l3room2.osg", roomScale, 0, 0 , roomZOff, 90, "models/l3room2_trigs.osg", 320, sceneGroup, stateMap); osg::Node *l3room3Mesh = addARTModel(14,"models/l3room3.osg", roomScale, 0, 0 , roomZOff, 90, "models/l3room3_trigs.osg", 330, sceneGroup, stateMap); osg::Node *l3room4Mesh = addARTModel(15,"models/l3room4.osg", roomScale, 0, 0 , roomZOff, 90, "models/l3room4_trigs.osg", 340, sceneGroup, stateMap); osg::Node *l3room5Mesh = addARTModel(16,"models/l3room5.osg", roomScale, 0, 0 , roomZOff, 90, "models/l3room5_trigs.osg", 350, sceneGroup, stateMap); osg::Node *l3room6Mesh = addARTModel(17,"models/l3room6.osg", roomScale, 0, 0 , roomZOff, 90, "models/l3room6_trigs.osg", 360, sceneGroup, stateMap); osg::ref_ptr markerPtr13 = dynamic_cast(l3room1Mesh); osg::ref_ptr markerPtr14 = dynamic_cast(l3room2Mesh); osg::ref_ptr markerPtr15 = dynamic_cast(l3room3Mesh); osg::ref_ptr markerPtr16 = dynamic_cast(l3room4Mesh); osg::ref_ptr markerPtr17 = dynamic_cast(l3room5Mesh); osg::ref_ptr markerPtr18 = dynamic_cast(l3room6Mesh); osg::Group *l3room1Labels = new osg::Group(); osg::Group *l3room2Labels = new osg::Group(); osg::Group *l3room3Labels = new osg::Group(); osg::Group *l3room4Labels = new osg::Group(); osg::Group *l3room5Labels = new osg::Group(); osg::Group *l3room6Labels = new osg::Group(); l3room1Labels->addChild(roomLabelTop); l3room2Labels->addChild(roomLabelTop); l3room3Labels->addChild(roomLabelTop); l3room4Labels->addChild(roomLabelTop); l3room5Labels->addChild(roomLabelTop); l3room6Labels->addChild(roomLabelTop); l3room1Labels->addChild(roomLabelBottom); l3room2Labels->addChild(roomLabelBottom); l3room3Labels->addChild(roomLabelBottom); l3room4Labels->addChild(roomLabelBottom); l3room5Labels->addChild(roomLabelBottom); l3room6Labels->addChild(roomLabelBottom); l3room1Labels->addChild(addRoomLabel(3, "loft 1", "l3r1label", osg::Vec3(0, -10, -10), atoi(argv[1]), foregroundGroup)); l3room2Labels->addChild(addRoomLabel(3, "loft 2", "l3r2label", osg::Vec3(0, -10, -10), atoi(argv[1]), foregroundGroup)); l3room3Labels->addChild(addRoomLabel(3, "loft 3", "l3r3label", osg::Vec3(0, -10, -10), atoi(argv[1]), foregroundGroup)); l3room4Labels->addChild(addRoomLabel(3, "loft 4", "l3r4label", osg::Vec3(0, -10, -10), atoi(argv[1]), foregroundGroup)); l3room5Labels->addChild(addRoomLabel(3, "loft 5", "l3r5label", osg::Vec3(0, 0, 0), atoi(argv[1]), foregroundGroup)); l3room6Labels->addChild(addRoomLabel(3, "loft 6", "l3r6label", osg::Vec3(0, 0, 0), atoi(argv[1]), foregroundGroup)); l3room1Labels->setStateSet(stateMap[12]); l3room2Labels->setStateSet(stateMap[13]); l3room3Labels->setStateSet(stateMap[14]); l3room4Labels->setStateSet(stateMap[15]); l3room5Labels->setStateSet(stateMap[16]); l3room6Labels->setStateSet(stateMap[17]); markerPtr13->addChild(l3room1Labels); markerPtr14->addChild(l3room2Labels); markerPtr15->addChild(l3room3Labels); markerPtr16->addChild(l3room4Labels); markerPtr17->addChild(l3room5Labels); markerPtr18->addChild(l3room6Labels); /* these vectors are used by renderNearestMarker. */ std::vector > markerPtrVec1; markerPtrVec1.reserve(6); markerPtrVec1.push_back(markerPtr1); markerPtrVec1.push_back(markerPtr2); markerPtrVec1.push_back(markerPtr3); markerPtrVec1.push_back(markerPtr4); markerPtrVec1.push_back(markerPtr5); markerPtrVec1.push_back(markerPtr6); std::vector > markerPtrVec2; markerPtrVec2.reserve(6); markerPtrVec2.push_back(markerPtr7); markerPtrVec2.push_back(markerPtr8); markerPtrVec2.push_back(markerPtr9); markerPtrVec2.push_back(markerPtr10); markerPtrVec2.push_back(markerPtr11); markerPtrVec2.push_back(markerPtr12); std::vector > markerPtrVec3; markerPtrVec3.reserve(6); markerPtrVec3.push_back(markerPtr13); markerPtrVec3.push_back(markerPtr14); markerPtrVec3.push_back(markerPtr15); markerPtrVec3.push_back(markerPtr16); markerPtrVec3.push_back(markerPtr17); markerPtrVec3.push_back(markerPtr18); osg::MatrixTransform* modelViewMatrix = new osg::MatrixTransform(); modelViewMatrix->addChild(foregroundGroup); projectionMatrix->addChild(modelViewMatrix); osg::ref_ptr root = new osg::Group; // setup before/after markers osg::ref_ptr curMarker; osg::ref_ptr lastMarker; osg::Timer_t startTick = osg::Timer::instance()->tick(); // timer used in game clock osg::Timer_t restartTick = osg::Timer::instance()->tick(); osg::Timer_t restartEndTick = osg::Timer::instance()->tick(); //osg::Geode *restartLabel = addGameLabel(1, "", osg::Vec3(-5, 2, -20), atoi(argv[1]), red); // move the label at the bottom of the screen around here osg::Geode *restartLabel = addGameLabel(1, "", osg::Vec3(0, 2, -20), atoi(argv[1]), red); osg::ref_ptr restartLabelPtr = dynamic_cast(restartLabel->getDrawable(0)); restartLabel->setNodeMask(0); restartLabel->setStateSet(stateMap[18]); sceneGroup->addChild(restartLabel); osg::Geode *timerLabel = addTimerLabel(1, "0.0", osg::Vec3(-11, -8, -20), atoi(argv[1]), grey); osg::ref_ptr timerPtr = dynamic_cast(timerLabel->getDrawable(0)); timerLabel->setStateSet(stateMap[19]); timerLabel->setNodeMask(0); if (atoi(argv[5])) // enable timer if bool arg is true. { sceneGroup->addChild(timerLabel); } osg::Geode *screenLabel = addGameLabel(1, "to restart levelHead remove all cubes from view and count to 15", osg::Vec3(0, -22, -50), atoi(argv[1]), white); osg::ref_ptr screenLabelPtr = dynamic_cast(restartLabel->getDrawable(0)); screenLabel->setNodeMask(1); screenLabel->setStateSet(stateMap[18]); sceneGroup->addChild(screenLabel); // change the colour/position of the URL in the top left of the screen here. osg::Geode *urlLabel = addGameLabel(1, "http://julianoliver.com/levelhead", osg::Vec3(18.5, 20.5, -50), atoi(argv[1]), black); osg::ref_ptr urlLabelPtr = dynamic_cast(restartLabel->getDrawable(0)); urlLabel->setNodeMask(1); urlLabel->setStateSet(stateMap[18]); sceneGroup->addChild(urlLabel); sceneGroup->addChild(charMAT); // add character transform node to the sceneGroup const osg::BoundingSphere &rootBox = root.get()->getBound(); root->addChild(projectionMatrix); viewer.setSceneData(root.get()); viewer.realize(); video->start(); //int setup = 0; int firstRun = 1; int control = 0; // is the cube in the right orientation to allow navigation? double t1, t2, t3 = 0.0; // times for restart int exited = 0; int lastClosestMarker = 0; int closestLvl1 = 0; std::string cube("red cube"); osg::Timer_t lastFrameTime = osg::Timer::instance()->tick(); printf("this is sceneGroup numChildren %i \n", sceneGroup->getNumChildren()); // setup roomMap for(int level=1;level<=3;level++) for(int room=1;room<=6;room++) { std::stringstream label; label << "l" << level << "r" << room; osg::notify() << "label=" << label.str() << std::endl; RoomManager::instance()->createRoom(label.str()); } while (!viewer.done()) { osg::Timer_t now = osg::Timer::instance()->tick(); double frameTime = osg::Timer::instance()->delta_s(lastFrameTime,now); lastFrameTime = now; double movScale = frameTime * 75.0; osg::Timer_t endTick = osg::Timer::instance()->tick(); double curTime = osg::Timer::instance()->delta_s(startTick,endTick); /* lastClosestMarker = closestLvl1; closestLvl1 = renderNearestMarker(markerPtrVec1, tracker, lastClosestMarker); int closestLvl2 = renderNearestMarker(markerPtrVec2, tracker); int closestLvl3 = renderNearestMarker(markerPtrVec3, tracker); printf("these are the closest in each level %i %i %i\n", closestLvl1,closestLvl2,closestLvl3); */ /* LEVEL SETUP * currently room setup is done in a bloated, dumb way. i left it like * this while i was playing around with triggers and other events. i'll * roll it all into one function at some point. that should cut down on * about 600 LOC * * triggers and targets must be set up individually for each room. they * use a convention with trigger targets * ('dest') following the same convention, * such that 'l3r4d2' would correspond to a 'l3r4d2'. * * It may seem strange that the character is not a child of each marker * node, toggled out of view removed and added as it traverses from room to room. * I did have it this way in the beta but due to a long list of * curious problems related to character state after toggling node masks * and ray collision, this turned out to be the best way to approach it. */ //========================= LEVEL 1 ===========================================> // level1 room 1 if (tracker->getMarker(0)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l1r1"); printf("marker 1 is active \n"); room = "entrance hall"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr1; if (firstRun == 1) { roomLabelTop->setNodeMask(1); roomLabelTopPtr->setColor(white); roomLabelTopPtr->setText("tilt the cube on the table to walk."); t3 = curTime; firstRun = 0; // we've visited the entrance room of this level for the first time. } else { roomLabelTop->setNodeMask(0); } setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 0); // trigger setup trigStruct trig1 = {std::string("l1r1d1"), std::string("garage"), std::string("l1r1t1")}; numTriggers = 1; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; osg::Geode *_g = getGeode(triggerNames[0].trig, foregroundGroup); triggerList[0] = _g; level = 1; cube = "the red cube"; thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 and thisRoom->setup == 1) { if (curMarker == markerPtr1) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level1 room 2 else if (tracker->getMarker(1)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l1r2"); printf("marker 2 is active \n"); room = "garage"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker= markerPtr2; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 1); // trigger setup trigStruct trig1 = {std::string("l1r2d1"), std::string("machine room"), std::string("l1r2t1")}; trigStruct trig2 = {std::string("l1r2d2"), std::string("NULL"), std::string("NULL")}; trigStruct trig3 = {std::string("l1r2d3"), std::string("entrance hall"), std::string("l1r2t3")}; numTriggers = 3; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr2) { charMAT->setNodeMask(0); } thisRoom->setActive(); thisRoom->setup = 0; } } // level1 room 3 else if (tracker->getMarker(2)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l1r3"); printf("marker 3 is active \n"); room = "machine room"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr3; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 2); // trigger setup trigStruct trig1 = {std::string("l1r3d1"), std::string("storeroom"), std::string("l1r3t1")}; trigStruct trig2 = {std::string("l1r3d2"), std::string("exit hall"), std::string("l1r3t2")}; trigStruct trig3 = {std::string("l1r3d3"), std::string("garage"), std::string("l1r3t3")}; numTriggers = 3; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr3) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level1 room 4 else if (tracker->getMarker(3)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l1r4"); printf("marker 4 is active \n"); room = "storeroom"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr4; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 3); // trigger setup trigStruct trig1 = {std::string("l1r4d1"), std::string("causeway"), std::string("l1r4t1")}; trigStruct trig2 = {std::string("l1r4d2"), std::string("causeway"), std::string("l1r4t2")}; trigStruct trig3 = {std::string("l1r4d4"), std::string("machine room"), std::string("l1r4t4")}; numTriggers = 3; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } // thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr4) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level1 room 5 else if (tracker->getMarker(4)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l1r5"); printf("marker 5 is active \n"); room = "causeway"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr5; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 4); // trigger setup trigStruct trig1 = {std::string("l1r5d1"), std::string("storeroom"), std::string("l1r5t1")}; trigStruct trig2 = {std::string("l1r5d2"), std::string("exit hall"), std::string("l1r5t2")}; trigStruct trig3 = {std::string("l1r5d3"), std::string("storeroom"), std::string("l1r5t3")}; numTriggers = 3; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } // thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr5) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level1 room 6 else if (tracker->getMarker(5)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l1r6"); printf("marker 6 is active \n"); room = "exit hall"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr6; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 5); // trigger setup trigStruct trig1 = {std::string("l1r6d1"), std::string("NULL"), std::string("NULL")}; trigStruct trig2 = {std::string("l1r6d2"), std::string("machine room"), std::string("l1r6t2")}; trigStruct trig3 = {std::string("l1r6d3"), std::string("causeway"), std::string("l1r6t3")}; trigStruct trig4 = {std::string("l1r6d4"), std::string("chamber 1"), std::string("l2startDest")}; numTriggers = 4; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; triggerNames[3] = trig4; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } // thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr6) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } /* LEVEL 2 */ // level2 room 1 else if (tracker->getMarker(6)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l2r1"); printf("marker 7 is active \n"); room = "chamber 1"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr7; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 6); // trigger setup trigStruct trig1 = {std::string("l2r1d1"), std::string("workshop"), std::string("l2r1t1")}; trigStruct trig2 = {std::string("l2r1d2"), std::string("chamber 2"), std::string("l2r1t2")}; numTriggers = 2; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room level = 2; cube = "green cube"; } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr7) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level1 room 2 else if (tracker->getMarker(7)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l2r2"); printf("marker 8 is active \n"); room = "workshop"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker= markerPtr8; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 7); // trigger setup trigStruct trig1 = {std::string("l2r2d1"), std::string("chamber 1"), std::string("l2r2t1")}; trigStruct trig2 = {std::string("l2r2d2"), std::string("NULL"), std::string("NULL")}; numTriggers = 2; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr8) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level2 room 3 else if (tracker->getMarker(8)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l2r3"); printf("marker 9 is active \n"); room = "chamber 2"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr9; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 8); // trigger setup trigStruct trig1 = {std::string("l2r3d1"), std::string("chamber 1"), std::string("l2r3t1")}; trigStruct trig2 = {std::string("l2r3d2"), std::string("interchange 2"), std::string("l2r3t2")}; numTriggers = 2; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr9) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level2 room 4 else if (tracker->getMarker(9)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l2r4"); printf("marker 10 is active \n"); room = "interchange 1"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr10; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 9); // trigger setup trigStruct trig1 = {std::string("l2r4d1"), std::string("interchange 2"), std::string("l2r4t1")}; trigStruct trig2 = {std::string("l2r4d2"), std::string("NULL"), std::string("NULL")}; trigStruct trig3 = {std::string("l2r4d3"), std::string("dispatch bay"), std::string("l2r4t3")}; numTriggers = 3; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr10) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level2 room 5 else if (tracker->getMarker(10)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l2r5"); printf("marker 11 is active \n"); room = "interchange 2"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr11; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 10); // trigger setup trigStruct trig1 = {std::string("l2r5d1"), std::string("chamber 2"), std::string("l2r5t1")}; trigStruct trig2 = {std::string("l2r5d3"), std::string("NULL"), std::string("NULL")}; trigStruct trig3 = {std::string("l2r5d4"), std::string("interchange 1"), std::string("l2r5t4")}; numTriggers = 3; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr11) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level2 room 6 else if (tracker->getMarker(11)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l2r6"); printf("marker 12 is active \n"); room = "dispatch bay"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr12; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 11); // trigger setup trigStruct trig1 = {std::string("l2r6d1"), std::string("interchange 1"), std::string("l2r6t1")}; trigStruct trig2 = {std::string("l2r6d2"), std::string("NULL"), std::string("NULL")}; trigStruct trig3 = {std::string("l2r6d3"), std::string("loft 1"), std::string("l3startDest")}; numTriggers = 3; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr12) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } /* LEVEL 3 */ // level3 room 1 else if (tracker->getMarker(12)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l3r1"); printf("marker 13 is active \n"); room = "loft 1"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr13; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 12); // trigger setup //trigStruct trig1 = {std::string("l3r1d1"), std::string("NULL"), std::string("NULL")}; trigStruct trig1 = {std::string("l3r1d2"), std::string("loft 4"), std::string("l3r1t2")}; trigStruct trig2 = {std::string("l3r1d3"), std::string("loft 2"), std::string("l3r1t3")}; numTriggers = 2; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; //triggerNames[2] = trig3; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room level = 3; cube = "orange cube"; } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr13) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level3 room 2 else if (tracker->getMarker(13)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l3r2"); printf("marker 14 is active \n"); room = "loft 2"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker= markerPtr14; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 13); // trigger setup trigStruct trig1 = {std::string("l3r2d1"), std::string("NULL"), std::string("NULL")}; trigStruct trig2 = {std::string("l3r2d2"), std::string("loft 1"), std::string("l3r2t2")}; trigStruct trig3 = {std::string("l3r2d3"), std::string("loft 3"), std::string("l3r2t3")}; trigStruct trig4 = {std::string("l3r2d4"), std::string("loft 3"), std::string("l3r2t4")}; numTriggers = 4; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; triggerNames[3] = trig4; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr14) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level3 room 3 else if (tracker->getMarker(14)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l3r3"); printf("marker 15 is active \n"); room = "loft 3"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr15; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 14); // trigger setup trigStruct trig1 = {std::string("l3r3d1"), std::string("loft 4"), std::string("l3r3t1")}; trigStruct trig2 = {std::string("l3r3d2"), std::string("loft 4"), std::string("l3r3t2")}; trigStruct trig3 = {std::string("l3r3d3"), std::string("loft 2"), std::string("l3r3t3")}; trigStruct trig4 = {std::string("l3r3d4"), std::string("loft 2"), std::string("l3r3t4")}; numTriggers = 4; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; triggerNames[3] = trig4; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr15) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level3 room 4 else if (tracker->getMarker(15)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l3r4"); printf("marker 16 is active \n"); room = "loft 4"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr16; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 15); // trigger setup trigStruct trig1 = {std::string("l3r4d1"), std::string("loft 1"), std::string("l3r4t1")}; trigStruct trig2 = {std::string("l3r4d2"), std::string("loft 6"), std::string("l3r4t2")}; trigStruct trig3 = {std::string("l3r4d3"), std::string("loft 3"), std::string("l3r4t3")}; trigStruct trig4 = {std::string("l3r4d4"), std::string("loft 3"), std::string("l3r4t4")}; numTriggers = 4; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; triggerNames[3] = trig4; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } // thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr16) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level3 room 5 else if (tracker->getMarker(16)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l3r5"); printf("marker 17 is active \n"); room = "loft 5"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr17; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 16); // trigger setup trigStruct trig1 = {std::string("l3r5d1"), std::string("loft 6"), std::string("l3r5t1")}; trigStruct trig2 = {std::string("l3r5d2"), std::string("loft 6"), std::string("l3r5t2")}; trigStruct trig3 = {std::string("l3r5d3"), std::string("loft 6"), std::string("l3r5t3")}; trigStruct trig4 = {std::string("l3r5d4"), std::string("loft 6"), std::string("l3r5t4")}; trigStruct trig5 = {std::string("l3r5d5"), std::string("EXIT"), std::string("EXIT")}; numTriggers = 5; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; triggerNames[3] = trig4; triggerNames[4] = trig5; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr17) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } // level3 room 6 else if (tracker->getMarker(17)->isValid()) { RoomData* thisRoom = RoomManager::instance()->getRoom("l3r6"); printf("marker 18 is active \n"); room = "loft 6"; restartLabel->setNodeMask(0); t1 = curTime; t2 = curTime; if (room.compare(presence) == 0 and thisRoom->setup == 0) { curMarker = markerPtr18; roomLabelTop->setNodeMask(0); setupCharInRoom(dest, foregroundGroup, *charMAT, *charPAT, charTrans, roomScale, 10, -40, stateMap, 17); // trigger setup trigStruct trig1 = {std::string("l3r6d1"), std::string("loft 5"), std::string("l3r6t1")}; trigStruct trig2 = {std::string("l3r6d2"), std::string("loft 5"), std::string("l3r6t2")}; trigStruct trig3 = {std::string("l3r6d3"), std::string("loft 5"), std::string("l3r6t3")}; trigStruct trig4 = {std::string("l3r6d4"), std::string("loft 5"), std::string("l3r6t4")}; trigStruct trig5 = {std::string("l3r6d5"), std::string("loft 4"), std::string("l3r6t5")}; numTriggers = 5; triggerNames.clear(); triggerList.clear(); triggerNames.resize(numTriggers); triggerList.resize(numTriggers); triggerNames[0] = trig1; triggerNames[1] = trig2; triggerNames[2] = trig3; triggerNames[3] = trig4; triggerNames[4] = trig5; for (int i = 0; i < numTriggers; i++) { osg::Geode *_g = getGeode(triggerNames[i].trig, foregroundGroup); triggerList[i] = _g; } thisRoom->setup = 1; // setup is complete for this room } else if (room.compare(presence) == 0 and !thisRoom->isActive()) { thisRoom->setActive(); //active = 0; } else if (room.compare(presence) != 0 /*and thisRoom->isActive()*/ and thisRoom->setup == 1) { if (curMarker == markerPtr18) { charMAT->setNodeMask(0); } thisRoom->setActive(false); thisRoom->setup = 0; } } else // if no markers were detected, do: { charMAT->setNodeMask(0); //roomLabelTop->setNodeMask(0); mov = 0; gravity = 0; stairs = 0; jump = 0; double t1 = curTime; // notify the humans that the cube needs to before the camera after 10 seconds. if (t1 - t2 > 10) { restartLabel->setNodeMask(1); restartLabelPtr->setColor(yellow); timerLabel->setNodeMask(0); // for my english speaking audience restartLabelPtr->setText("place red cube \ninside square to \nbegin playing"); // for my spanish speaking audience //restartLabelPtr->setText("pon el cubo rojo \ndentro del cuandrado \npara jugar"); if (fmod(int(curTime), 3) ==0) { restartLabel->setNodeMask(0); } else { restartLabel->setNodeMask(1); } // reset a bunch of important vars entered = 0; charMAT->setNodeMask(0); dest = "l1startDest"; presence = "entrance hall"; room = "entrance hall"; firstRun = 1; //setup = 0; //bit of a hack RoomManager::instance()->unsetAll(); roomLabelTop->setNodeMask(1); roomLabelTopPtr->setText("find the room named entrance"); roomLabelTopPtr->setColor(yellow); roomLabelBottom->setNodeMask(1); roomLabelBottomPtr->setText("look in the red cube"); roomLabelBottomPtr->setColor(red); } } if (atoi(argv[5]) and !(firstRun)) // activate the timer if timer arg bool is true and we're on our first run. { if (!t3 == 0.0) { if (timerLabel->getNodeMask() == 0) { timerLabel->setNodeMask(1); } std::stringstream conv; conv << curTime - t3; timerPtr->setText("time: " + std::string(conv.str())); } } std::cout << "this is time " << t1 - t2 << std::endl; //RoomManager::instance()->printRooms(); RoomData* activeRoom = RoomManager::instance()->getActiveRoom(); if (activeRoom && activeRoom->setup && curMarker.get()) { // calculate Heading/Pitch/Roll osg::Vec3 hpr = MatrixToHpr(curMarker->getMatrix()); printf("this is HPR: %f %f %f \n", hpr[0], hpr[1], hpr[2]); // update position and orientation charMATUpdate(charMAT, pos, charTrans, curMarker->getMatrix(), charRotateX, charRotateY, charRotateZ); if (hpr[0] < -85 and hpr[0] > -95) { NSIndex = 2; WEIndex = 0; gravIndex=0; control = 0; } else if (fabs(hpr[0]) > 175) // could possibly play upside down { NSIndex = 1; WEIndex = 0; control = 1; gravIndex=1; } else if (hpr[0] > 85 and hpr[0] < 95) { NSIndex = 1; WEIndex = 0; gravIndex=0; control = 0; } else { WEIndex = 0; NSIndex = 2; control = 1; gravIndex=1; } osg::Vec3 rayBegin = osg::Vec3(charPAT->getPosition().x(),charPAT->getPosition().y(),charPAT->getPosition().z()); osg::Matrix rayEndGroupMatrix = computeLocalToWorld(charPAT->getChild(4)->asGroup(), 1, 0, 0); osg::Matrix floorRayGroupMatrix = computeLocalToWorld(charPAT->getChild(3)->asGroup(), 1, 0, 0); osg::Matrix rayStepBeginGroupMatrix = computeLocalToWorld(charPAT->getChild(2)->asGroup(), 1, 0, 0); osg::Matrix rayStepEndGroupMatrix = computeLocalToWorld(charPAT->getChild(1)->asGroup(), 1, 0, 0); charPATMatrix = computeLocalToWorld(charPAT->getChild(0)->asGroup(), 1, 0, 0); osg::Vec3 baseRayBegin = charPATMatrix.getTrans(); osg::Vec3 stepRayBegin = rayStepBeginGroupMatrix.getTrans(); osg::Vec3 stepRayEnd = rayStepEndGroupMatrix.getTrans(); osg::Vec3 baseRayEnd = rayEndGroupMatrix.getTrans(); //osg::Vec3 floorRayIntersect = getRayIntersect(sceneGroup, baseRayBegin, floorRayGroupMatrix.getTrans()); osg::Vec3 stepRayIntersect = getRayIntersect(sceneGroup, stepRayBegin, stepRayEnd); osg::Vec3 baseRayIntersect = getRayIntersect(sceneGroup, baseRayBegin, baseRayEnd); float floorDist = getFloor(curMarker->asGroup(), baseRayBegin, floorRayGroupMatrix.getTrans()); osg::notify() << "triggerNames:" << std::endl; //trigsVec::iterator iter; /* for(int i = 0;iasGroup(), stepRayBegin, stepRayEnd, room)); // updated charPAT->getChild(1) position into a vec curTrans = charPAT->getPosition(); float cx = curTrans[0]; float cy = curTrans[1]; float cz = curTrans[2]; // trigger distance for door reactivation osg::Vec3 destVec = pos + charPAT->getPosition(); float dX = destVec.x() - pos.x(); float dY = destVec.y() - pos.y(); float dZ = destVec.z() - pos.z(); float reTrigDist = sqrt(dX*dX + dY*dY + dZ*dZ); /* setup door un/locking so that when the character enters a room he * can't accidentally be nudged back through the door he came. * had to hack around the fact there's a balcony in l3r5 that would * trap the player without sufficient distance to walk. */ if (!hitResults.compare("l3r5d1") == 0) { if (reTrigDist > 15) // this dist is in world coords. { entered = 1; roomLabelTop->setNodeMask(0); } } else { if (reTrigDist > 5) // this dist is in world coords. { entered = 1; roomLabelTop->setNodeMask(0); } } if (strcmp(dir, "east")==0 or strcmp(dir, "west")==0) { hitDist = fabs(baseRayIntersect[WEIndex] - baseRayBegin[WEIndex]); stepHitDist = fabs(stepRayIntersect[WEIndex] - stepRayBegin[WEIndex]); } else if (strcmp(dir, "south")==0 or strcmp(dir, "north")==0) { hitDist = fabs(baseRayIntersect[NSIndex] - baseRayBegin[NSIndex]); stepHitDist = fabs(stepRayIntersect[NSIndex] - stepRayBegin[NSIndex]); } if ((hitResults.compare("wall") == 0) and hitDist < 3 and hitDist > 1.5 and fabs(stepHitDist - hitDist) < .01) // we hit a wall { wall = 1; } else if ((hitResults.compare("wall") == 0) and hitDist <= 1.5 and fabs(stepHitDist - hitDist) > .01) // we're probably close enough to be on the stairs { wall = 1; } else if (hitResults.compare("wall") !=0 and hitResults.compare("NULL") !=0) // we hit a door { if (entered == 1) { stairs = 0; // teleport the charPAT->getChild(1) to the new room for (int i = 0; isetColor(yellow); roomLabelTopPtr->setText("you have entered: " +presence); roomLabelTop->setNodeMask(1); entered = 0; // reset distance trigger if (dest.compare("NULL") == 0) // send them back to the beginning of that level if they hit an illogical door. { charMAT->setNodeMask(0); if (level == 1) { dest = "l1startDest"; presence = "entrance hall"; } else if (level == 2) { dest = "l2startDest"; presence = "chamber 1"; } else if (level == 3) { dest = "l3startDest"; presence = "loft 1"; } // roomLabelTopPtr->setColor(yellow); roomLabelTopPtr->setText("illogical door! back to " +presence +"!"); roomLabelTop->setNodeMask(1); roomLabelBottomPtr->setText("you are now in room " +presence); } else if (dest.compare("l2startDest") == 0) { roomLabelTopPtr->setColor(green); roomLabelTopPtr->setText("you escaped. now escape the green cube"); roomLabelTop->setNodeMask(1); roomLabelBottomPtr->setColor(green); roomLabelBottomPtr->setText("you're in " +presence +" in the green cube"); } else if (dest.compare("l3startDest") == 0) { roomLabelTopPtr->setColor(orange); roomLabelTopPtr->setText("you escaped. now escape the orange cube"); roomLabelTop->setNodeMask(1); roomLabelBottomPtr->setColor(orange); roomLabelBottomPtr->setText("you're in " +presence +" in the orange cube"); } else if (dest.compare("EXIT") == 0) { roomLabelTopPtr->setColor(orange); roomLabelTopPtr->setText("well done! now play it again, but faster"); roomLabelTop->setNodeMask(1); dest = "l1startDest"; presence = "entrance hall"; } } } } else { wall = 1; roomLabelTopPtr->setColor(white); roomLabelTop->setNodeMask(1); roomLabelTopPtr->setText("walk away to reactivate this door"); } } else if ((hitResults.compare("NULL") !=0)) { wall = 0; mov = 0; gravity = 0; jump = 0; } else if ((hitResults.compare("NULL") ==0) and floorDist == -1) { //find a way to pop him back to the last known good pos. RoomManager::instance()->unsetAll(); } // step detection: steps must be of square proportions! //if (hitDist - (stepHitDist/2) < .75) if (hitDist - (stepHitDist/2) < .3) { stairs = 1; } else { stairs = 0; } // setup falling if ( floorDist ==-1) // if below floor, fall up. { gravity = .2*movScale; cz +=gravity; std::cout << " * * * * * fallen through floor * * * * * *" << std::endl; //charPAT->setPosition(lastGoodPos); } else if (floorDist > 1 and !jump) // if above floor, fall down { gravity = (floorDist-.8);//*movScale; cz -=gravity; } else if (floorDist < .8 and floorDist != -1 and !jump) // if above walk threshold, fall down { gravity=(.8-floorDist);//*movScale; cz +=gravity; } else if (floorDist > .8 and jump) // if above floor, fall down { gravity = .1*movScale; } else { gravity = 0; } // setup step action if (stairs) { printf("on the stairs \n"); jump = .09*movScale; mov = .09*movScale; } else { mov = .1*movScale; jump = 0; } hprX = 0; hprY = 1; // walk if (presence == room) { if (fabs(hpr[hprX]) > fabs(hpr[hprY])) { if (hpr[hprX] < -tiltSens and strcmp(dir, "east") != 0) { printf("turning east \n "); dir = "east"; charPAT->setAttitude(quatEast); } else if (hpr[hprX] > -walkSens and hpr[hprX] < -tiltSens) { roomLabelBottom->setNodeMask(1); roomLabelBottomPtr->setColor(grey); roomLabelBottomPtr->setText("you are walking east.."); if (wall and stairs) { moving = 1; cy -=mov; cz +=jump; } else if (!wall) { moving = 1; cy -=mov; } } else if (hpr[hprX] > tiltSens and strcmp(dir,"west") != 0) { printf("turning west \n "); dir = "west"; charPAT->setAttitude(quatWest); } else if (hpr[hprX] < walkSens and hpr[hprX] > tiltSens) { roomLabelBottom->setNodeMask(1); roomLabelBottomPtr->setColor(grey); roomLabelBottomPtr->setText("you are walking west.."); if (wall and stairs) { moving = 1; cy +=mov; cz +=jump; } else if (!wall) { moving = 1; cy +=mov; } else { moving = 0; } } else { moving = 0; if (!firstRun ==1) { roomLabelBottomPtr->setText("you are in the " +cube); } if (level == 1) { roomLabelBottomPtr->setColor(red); } else if (level == 2) { roomLabelBottomPtr->setColor(green); } else if (level == 3) { roomLabelBottomPtr->setColor(orange); } } //roomLabelBottom->setNodeMask(0); } else {// FIXME: the top/front orientation check needs to be rolled into a simple switch if (hpr[hprY] < -tiltSens and strcmp(dir, "north") != 0) { printf("turning north \n "); dir = "north"; charPAT->setAttitude(quatNorth); } else if (hpr[hprY] > -walkSens and hpr[hprY] < -tiltSens) { if (wall and stairs) { moving = 1; cz +=jump; cx +=mov; roomLabelBottom->setNodeMask(1); roomLabelBottomPtr->setColor(grey); roomLabelBottomPtr->setText("you are walking north.."); } else if (!wall) { moving = 1; cx +=mov; roomLabelBottom->setNodeMask(1); roomLabelBottomPtr->setColor(grey); roomLabelBottomPtr->setText("you are walking north.."); } } else if (hpr[hprY] > tiltSens and strcmp(dir,"south") != 0) { // FIXME: the top/front orientation check needs to be rolled into a simple switch printf("turning south \n "); dir = "south"; charPAT->setAttitude(quatSouth); } else if (hpr[hprY] < walkSens and hpr[hprY] > tiltSens) { if (wall and stairs) { moving = 1; cz +=jump; cx -=mov; roomLabelBottom->setNodeMask(1); roomLabelBottomPtr->setColor(grey); roomLabelBottomPtr->setText("you are walking south.."); } else if (!wall) { moving = 1; cx -=mov; roomLabelBottom->setNodeMask(1); roomLabelBottomPtr->setColor(grey); roomLabelBottomPtr->setText("you are walking south.."); } } else { moving = 0; roomLabelBottomPtr->setText("you are in the " +cube); if (level == 1) { roomLabelBottomPtr->setColor(red); } else if (level == 2) { roomLabelBottomPtr->setColor(green); } else if (level == 3) { roomLabelBottomPtr->setColor(orange); } } //roomLabelBottom->setNodeMask(0); } } if (control) // are we allowed to move? { if (moving and !stairs) { if (curAnim != 1) { newAnim = 1; launchAnim(newAnim, curAnim, .05, charModelPtr->getCalModel()); curAnim = newAnim; } } else if (moving and stairs) { if (curAnim != 2) { newAnim = 2; launchAnim(newAnim, curAnim, .05, charModelPtr->getCalModel()); curAnim = newAnim; } } else { if (curAnim != 0) { newAnim = 0; launchAnim(newAnim, curAnim, .5, charModelPtr->getCalModel()); curAnim = newAnim; } } // update new position newTrans = osg::Vec3d(cx, cy, cz); lastGoodPos = newTrans; charPAT->setPosition(newTrans); } else { newAnim = 0; launchAnim(newAnim, curAnim, .1, charModelPtr->getCalModel()); curAnim = newAnim; mov = 0; } } //count += 1; //std::cout << "this is frame " << frame << "at time " << conv.str().c_str() << std::endl; //std::cout << "we are in room " << room << std::cout; viewer.sync(); video->update(); tracker->setImage(video.get()); tracker->update(); viewer.update(); viewer.frame(); } viewer.sync(); viewer.cleanup_frame(); viewer.sync(); video->stop(); video->close(); } // EOF