Object* ObjectManager::collision(const Ogre::Vector3& fromPoint, const Ogre::Vector3& toPoint, float collisionRadius, int queryMask) { Ogre::Entity* entity = mCollision->collidesWithObject(fromPoint, toPoint, collisionRadius, queryMask); if (entity && entity->isVisible()) return getObject(entity->getName()); return 0; }
bool PlaypenApp::appFrameStarted(opal::real dt) { // Do per-frame application-specific things here. // Handle speech input. bool keepLooping = true; bool makeObject = false; std::string material; ObjectType type; std::string outputString; while (voce::getRecognizerQueueSize() > 0) { std::string s = voce::popRecognizedString(); //// Check if the string contains 'quit'. //if (std::string::npos != s.rfind("quit")) //{ // keepLooping = false; //} // Check if we should reset. if (std::string::npos != s.rfind("reset")) { // Make sure the PhysicalCamera isn't grabbing anything. mPhysicalCamera->release(); destroyAllPhysicalEntities(); setupInitialPhysicalEntities(); voce::synthesize("reset"); return true; } // Check for material color. if (std::string::npos != s.rfind("yellow")) { outputString += "yellow"; material = "Plastic/Yellow"; } else if (std::string::npos != s.rfind("red")) { outputString += "red"; material = "Plastic/Red"; } else if (std::string::npos != s.rfind("blue")) { outputString += "blue"; material = "Plastic/Blue"; } else if (std::string::npos != s.rfind("green")) { outputString += "green"; material = "Plastic/Green"; } else if (std::string::npos != s.rfind("purple")) { outputString += "purple"; material = "Plastic/Purple"; } else if (std::string::npos != s.rfind("orange")) { outputString += "orange"; material = "Plastic/Orange"; } else { // Default to dark gray. material = "Plastic/DarkGray"; } // Check for object type. if (std::string::npos != s.rfind("box")) { outputString += " box"; type = OBJECT_TYPE_BOX; makeObject = true; } else if (std::string::npos != s.rfind("sphere")) { outputString += " sphere"; type = OBJECT_TYPE_SPHERE; makeObject = true; } else if (std::string::npos != s.rfind("wall")) { outputString += " wall"; type = OBJECT_TYPE_WALL; makeObject = true; } else if (std::string::npos != s.rfind("tower")) { outputString += " tower"; type = OBJECT_TYPE_TOWER; makeObject = true; } else if (std::string::npos != s.rfind("character")) { outputString += " character"; type = OBJECT_TYPE_RAGDOLL; makeObject = true; } if (makeObject) { voce::synthesize(outputString); createObject(material, type); } } // Update the grasping spring line. if (mPhysicalCamera->isGrasping()) { Ogre::Entity* pickingSphere = mSceneMgr->getEntity("pickingSphere"); if (!pickingSphere->isVisible()) { pickingSphere->setVisible(true); } Ogre::Entity* springLine = mSceneMgr->getEntity("springLine"); if (!springLine->isVisible()) { springLine->setVisible(true); } opal::Point3r desiredPos = mPhysicalCamera->getGraspGlobalPos(); Ogre::Vector3 point0(desiredPos[0], desiredPos[1], desiredPos[2]); opal::Point3r attachPos = mPhysicalCamera->getAttachGlobalPos(); Ogre::Vector3 point1(attachPos[0], attachPos[1], attachPos[2]); pickingSphere->getParentSceneNode()->setPosition(point1); Ogre::Vector3 lineVec = point0 - point1; if (!lineVec.isZeroLength()) { Ogre::SceneNode* springLineNode = springLine->getParentSceneNode(); springLineNode->setPosition(0.5 * (point0 + point1)); springLineNode->setDirection(lineVec); springLineNode->setScale(0.1, 0.1, lineVec.length()); } else { springLine->setVisible(false); } } else { Ogre::Entity* pickingSphere = mSceneMgr->getEntity("pickingSphere"); if (pickingSphere->isVisible()) { pickingSphere->setVisible(false); } Ogre::Entity* springLine = mSceneMgr->getEntity("springLine"); if (springLine->isVisible()) { springLine->setVisible(false); } } // Return true to continue looping. return keepLooping; }
bool PlaypenApp::appFrameStarted(opal::real dt) { // Do per-frame application-specific things here. // Update the grasping spring line. if (mPhysicalCamera->isGrasping()) { Ogre::Entity* pickingSphere = mSceneMgr->getEntity("pickingSphere"); if (!pickingSphere->isVisible()) { pickingSphere->setVisible(true); } Ogre::Entity* springLine = mSceneMgr->getEntity("springLine"); if (!springLine->isVisible()) { springLine->setVisible(true); } opal::Point3r desiredPos = mPhysicalCamera->getGraspGlobalPos(); Ogre::Vector3 point0(desiredPos[0], desiredPos[1], desiredPos[2]); opal::Point3r attachPos = mPhysicalCamera->getAttachGlobalPos(); Ogre::Vector3 point1(attachPos[0], attachPos[1], attachPos[2]); pickingSphere->getParentSceneNode()->setPosition(point1); Ogre::Vector3 lineVec = point0 - point1; if (!lineVec.isZeroLength()) { Ogre::SceneNode* springLineNode = springLine->getParentSceneNode(); springLineNode->setPosition(0.5 * (point0 + point1)); springLineNode->setDirection(lineVec, Ogre::Node::TS_WORLD); springLineNode->setScale(0.1, 0.1, lineVec.length()); } else { springLine->setVisible(false); } } else { Ogre::Entity* pickingSphere = mSceneMgr->getEntity("pickingSphere"); if (pickingSphere->isVisible()) { pickingSphere->setVisible(false); } Ogre::Entity* springLine = mSceneMgr->getEntity("springLine"); if (springLine->isVisible()) { springLine->setVisible(false); } } // Return true to continue looping. return true; }
// BETWEEN FRAME OPERATION void VisCalcFrustDist::calculateEntityVisibility(Ogre::Node* regionNode, Ogre::Node* node, bool recurse) { if (recurse && node->numChildren() > 0) { // if node has more children nodes, visit them recursivily Ogre::SceneNode::ChildNodeIterator nodeChildIterator = node->getChildIterator(); while (nodeChildIterator.hasMoreElements()) { Ogre::Node* nodeChild = nodeChildIterator.getNext(); // 'false' causes it to not visit sub-children which are included in parent and pos relative to parent calculateEntityVisibility(regionNode, nodeChild, false); visChildren++; } } visNodes++; // children taken care of... check fo attached objects to this node Ogre::SceneNode* snode = (Ogre::SceneNode*)node; // the camera needs to be made relative to the region // Ogre::Vector3 relCameraPos = LG::RendererOgre::Instance()->m_camera->getPosition() - regionNode->getPosition(); // float snodeDistance = LG::RendererOgre::Instance()->m_camera->getPosition().distance(snode->_getWorldAABB().getCenter()); // float snodeDistance = relCameraPos.distance(snode->getPosition()); float snodeDistance = LG::RendererOgre::Instance()->m_camera->getDistanceFromCamera(regionNode, snode->getPosition()); Ogre::SceneNode::ObjectIterator snodeObjectIterator = snode->getAttachedObjectIterator(); while (snodeObjectIterator.hasMoreElements()) { Ogre::MovableObject* snodeObject = snodeObjectIterator.getNext(); if (snodeObject->getMovableType() == "Entity") { visEntities++; Ogre::Entity* snodeEntity = (Ogre::Entity*)snodeObject; // check it's visibility if it's not world geometry (terrain and ocean) if ((snodeEntity->getQueryFlags() & Ogre::SceneManager::WORLD_GEOMETRY_TYPE_MASK) == 0) { // computation if it should be visible // Note: this call is overridden by derived classes that do fancier visibility rules bool shouldBeVisible = this->CalculateVisibilityImpl(LG::RendererOgre::Instance()->m_camera, snodeEntity, snodeDistance); if (snodeEntity->isVisible()) { // we currently think this object is visible. make sure it should stay that way if (shouldBeVisible) { // it should stay visible visVisToVis++; } else { // not visible any more... make invisible nad unload it` /* Ogre::Vector3 cPos = LG::RendererOgre::Instance()->m_camera->getPosition(); Ogre::Vector3 rPos = regionNode->getPosition(); Ogre::Vector3 sPos = snode->getPosition(); LG::Log("VisToInVis: cPos=<%f,%f,%f>, rPos=<%f,%f,%f>, sPos(%s)=<%f,%f,%f>, d=%f", cPos.x, cPos.y, cPos.z, rPos.x, rPos.y, rPos.z, snode->getName().c_str(), sPos.x, sPos.y, sPos.z, snodeDistance); */ snodeEntity->setVisible(false); snode->needUpdate(true); visVisToInvis++; if (!snodeEntity->getMesh().isNull()) { queueMeshUnload(snodeEntity->getMesh()); } } } else { // the entity currently thinks it's not visible. // check to see if it should be visible by checking a fake bounding box if (shouldBeVisible) { // it should become visible again if (!snodeEntity->getMesh().isNull()) { // queueMeshLoad(snodeEntity, snodeEntity->getMesh()); LG::OLMeshTracker::Instance()->MakeLoaded(snodeEntity->getMesh()->getName(), Ogre::String(""), Ogre::String("visible"), snodeEntity); } // snodeEntity->setVisible(true); // must happen after mesh loaded visInvisToVis++; } else { visInvisToInvis++; } } } } } }
void MeshCollisionDetector::testCollision(Ogre::Ray& ray, CollisionResult& result) { // at this point we have raycast to a series of different objects bounding boxes. // we need to test these different objects to see which is the first polygon hit. // there are some minor optimizations (distance based) that mean we wont have to // check all of the objects most of the time, but the worst case scenario is that // we need to test every triangle of every object. Ogre::Real closest_distance = -1.0f; Ogre::Vector3 closest_result = Ogre::Vector3::ZERO; const Model::Model::SubModelSet& submodels = mModel->getSubmodels(); for (Model::Model::SubModelSet::const_iterator I = submodels.begin(); I != submodels.end(); ++I) { Ogre::Entity* pentity = (*I)->getEntity(); if (pentity->isVisible() && pentity->getParentNode()) { // mesh data to retrieve size_t vertex_count; size_t index_count; Ogre::Vector3 *vertices; unsigned long *indices; // get the mesh information getMeshInformation(pentity->getMesh(), vertex_count, vertices, index_count, indices, pentity->getParentNode()->_getDerivedPosition(), pentity->getParentNode()->_getDerivedOrientation(), pentity->getParentNode()->getScale()); // test for hitting individual triangles on the mesh bool new_closest_found = false; for (int i = 0; i < static_cast<int>(index_count); i += 3) { // check for a hit against this triangle std::pair<bool, Ogre::Real> hit = Ogre::Math::intersects(ray, vertices[indices[i]], vertices[indices[i+1]], vertices[indices[i+2]], true, false); // if it was a hit check if its the closest if (hit.first) { if ((closest_distance < 0.0f) || (hit.second < closest_distance)) { // this is the closest so far, save it off closest_distance = hit.second; new_closest_found = true; } } } // free the verticies and indicies memory delete[] vertices; delete[] indices; // if we found a new closest raycast for this object, update the // closest_result before moving on to the next object. if (new_closest_found) { closest_result = ray.getPoint(closest_distance); } } } // return the result if (closest_distance >= 0.0f) { // raycast success result.collided = true; result.position = closest_result; result.distance = closest_distance; } else { // raycast failed result.collided = false; } }