void DefaultZone::_checkNodeAgainstPortals(PCZSceneNode * pczsn, Portal * ignorePortal) { if (pczsn == mEnclosureNode || pczsn->allowedToVisit() == false) { // don't do any checking of enclosure node versus portals return; } PCZone * connectedZone; for ( PortalList::iterator it = mPortals.begin(); it != mPortals.end(); ++it ) { Portal * p = *it; //Check if the portal intersects the node if (p != ignorePortal && p->intersects(pczsn) != Portal::NO_INTERSECT) { // node is touching this portal connectedZone = p->getTargetZone(); // add zone to the nodes visiting zone list unless it is the home zone of the node if (connectedZone != pczsn->getHomeZone() && !pczsn->isVisitingZone(connectedZone)) { pczsn->addZoneToVisitingZonesMap(connectedZone); // tell the connected zone that the node is visiting it connectedZone->_addNode(pczsn); //recurse into the connected zone connectedZone->_checkNodeAgainstPortals(pczsn, p->getTargetPortal()); } } } }
void World::shootPortal(int button) { //Shooting Vector3f cameraDir = Math::toDirection(scene->camera.rotation); //Find the closest intersection Entity closestWall; float intersection = INT_MAX; for (unsigned int i = 0; i < scene->walls.size(); i++) { Entity wall = scene->walls[i]; Ray bullet = Ray(scene->camera.position, cameraDir); float tNear, tFar; if (bullet.collides(wall, &tNear, &tFar)) { if (wall.texture.handle == TextureLoader::getTexture("wall.png").handle) { if (tNear < intersection) { closestWall = wall; intersection = tNear; } } } } BoxCollider wall(closestWall.position, closestWall.scale); Vector3f ipos = scene->camera.position + (cameraDir * intersection); Portal portal; portal.placeOnWall(wall, ipos); if (button == 1) { portal.texture = TextureLoader::getTexture("blueportal.png"); scene->bluePortal = portal; } else { portal.texture = TextureLoader::getTexture("orangeportal.png"); scene->orangePortal = portal; } }
void handleCamera(Camera * camera) { vec3 oldCameraPos = camera->getPosition(); vec3 move(glfwGetKey('D')-glfwGetKey('A'),0,glfwGetKey('S')-glfwGetKey('W')); move *= 0.1f; camera->move(move); vec3 newCameraPos = camera->getPosition(); vec2 lookVec( glfwGetKey(GLFW_KEY_LEFT)-glfwGetKey(GLFW_KEY_RIGHT), glfwGetKey(GLFW_KEY_UP)-glfwGetKey(GLFW_KEY_DOWN)); camera->rotateY(lookVec.x * 2.0); // Handle portaling :) Module * currentModule = camera->getOwnerModule(); std::vector<Portal*> portals = currentModule->getPortals(); for(u32 i=0; i<portals.size(); ++i) { Portal * portal = portals[i]; if( intersectLinePortal(oldCameraPos, newCameraPos, *portal) ) { camera->getOwnerModule()->removeGameObject(camera); portal->getTargetPortal()->getOwnerModule()->addGameObject(camera); camera->setTransform(portal->getInvViewMatrix(camera)); } } }
void Portal::transportBall(Ball &ball, Portal &portal) { int nextX = portal.getXPos(); int nextY = portal.getYPos(); ball.setXPos(nextX); ball.setYPos(nextY); }
// delete a portal instance by pointer void PCZSceneManager::destroyPortal(Portal * p) { // remove the portal from it's target portal Portal * targetPortal = p->getTargetPortal(); if (targetPortal) { targetPortal->setTargetPortal(0); // the targetPortal will still have targetZone value, but targetPortal will be invalid } // remove the Portal from it's home zone PCZone * homeZone = p->getCurrentHomeZone(); if (homeZone) { // inform zone of portal change. Do here since PCZone is abstract homeZone->setPortalsUpdated(true); homeZone->_removePortal(p); } // remove the portal from the master portal list PortalList::iterator it = std::find( mPortals.begin(), mPortals.end(), p ); if (it != mPortals.end()) { mPortals.erase(it); } // delete the portal instance OGRE_DELETE p; }
// Create a portal instance Portal* PCZSceneManager::createPortal(const String& name, PortalBase::PORTAL_TYPE type) { Portal* newPortal = OGRE_NEW Portal(name, type); newPortal->_notifyCreator(Root::getSingleton().getMovableObjectFactory("Portal")); newPortal->_notifyManager(this); mPortals.push_front(newPortal); return newPortal; }
//--------------------------------------------------------------------------------------- void Portal::Split(Plane& plane, Portal& a, Portal& b) { a.CopyProps(*this); b.CopyProps(*this); if((_n == plane._n && _c == plane._c) || (_n == -plane._n && _c == -plane._c) ) { #ifdef WINDOWS # pragma message("see this") #endif a._vxes = _vxes; b._vxes = _vxes; return; } v3d_t iv; v3d_t itxB = *_vxes.begin(); v3d_t itxA = _vxes.back(); f32_t fB; f32_t fA = plane.DistTo(itxA); FOREACH(vvector<v3d_t>, _vxes, vxI) { itxB = *vxI; fB = plane.DistTo(itxB); if(fB > GEpsilon) { if(fA < -GEpsilon) { f32_t t = -fA /(fB - fA); iv.interpolate(itxA,itxB,t); a._vxes << iv; b._vxes << iv; } a._vxes<<itxB; } else if(fB < -GEpsilon) { if(fA > GEpsilon) { f32_t t = -fA /(fB - fA); // t of segment iv.interpolate(itxA,itxB,t); a._vxes <<iv; b._vxes <<iv; } b._vxes<<itxB; } else { a._vxes << itxB; b._vxes << itxB; } itxA = itxB; fA = fB; }
Portal* Portal::create(Stage* _stage) { Portal* ret = new (std::nothrow) Portal(); if (ret &&ret->init(_stage)) { ret->autorelease(); return ret; } CC_SAFE_DELETE(ret); return nullptr; }
void Sector::render(Portal *portal) { if(frame == Engine::frame) return; frame = Engine::frame; this->portal = portal; Bsp::visible_sectors[Bsp::num_visible_sectors++] = this; num_visible_objects = 0; root->render(); for(int i = 0; i < num_objects; i++) { Object *o = objects[i]; if(o->frame == Engine::frame) continue; if(Engine::frustum->inside(o->pos + o->getCenter(),o->getRadius())) { Engine::num_triangles += o->render(Object::RENDER_OPACITY); visible_objects[num_visible_objects++] = o; } } for(int i = 0; i < num_portals; i++) { Portal *p = &Bsp::portals[portals[i]]; if(p->frame == Engine::frame) continue; p->frame = Engine::frame; if(Engine::frustum->inside(p->center,p->radius)) { float dist = (Engine::camera - p->center).length(); if(Engine::have_occlusion && dist > p->radius) { if(Material::old_material) Material::old_material->disable(); glDisable(GL_CULL_FACE); glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE); glDepthMask(GL_FALSE); glBeginQueryARB(GL_SAMPLES_PASSED_ARB,Engine::query_id); p->render(); glEndQueryARB(GL_SAMPLES_PASSED_ARB); glDepthMask(GL_TRUE); glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE); glEnable(GL_CULL_FACE); GLuint samples; glGetQueryObjectuivARB(Engine::query_id,GL_QUERY_RESULT_ARB,&samples); if(samples == 0) continue; } if(dist > p->radius) Engine::frustum->addPortal(Engine::camera,p->points); for(int j = 0; j < p->num_sectors; j++) { Bsp::sectors[p->sectors[j]].render(dist > p->radius ? p : NULL); } if(dist > p->radius) Engine::frustum->removePortal(); } } }
/* The following function checks if a node has left it's current home zone. * This is done by checking each portal in the zone. If the node has crossed * the portal, then the current zone is no longer the home zone of the node. The * function then recurses into the connected zones. Once a zone is found where * the node does NOT cross out through a portal, that zone is the new home zone. NOTE: For this function to work, the node must start out in the proper zone to begin with! */ PCZone* DefaultZone::updateNodeHomeZone( PCZSceneNode * pczsn, bool allowBackTouches ) { // default to newHomeZone being the current home zone PCZone * newHomeZone = pczsn->getHomeZone(); // Check all portals of the start zone for crossings! Portal* portal; PortalList::iterator pi, piend; piend = mPortals.end(); for (pi = mPortals.begin(); pi != piend; pi++) { portal = *pi; Portal::PortalIntersectResult pir = portal->intersects(pczsn); switch (pir) { default: case Portal::NO_INTERSECT: // node does not intersect portal - do nothing case Portal::INTERSECT_NO_CROSS:// node intersects but does not cross portal - do nothing break; case Portal::INTERSECT_BACK_NO_CROSS:// node intersects but on the back of the portal if (allowBackTouches) { // node is on wrong side of the portal - fix if we're allowing backside touches if (portal->getTargetZone() != this && portal->getTargetZone() != pczsn->getHomeZone()) { // set the home zone of the node to the target zone of the portal pczsn->setHomeZone(portal->getTargetZone()); // continue checking for portal crossings in the new zone newHomeZone = portal->getTargetZone()->updateNodeHomeZone(pczsn, false); } } break; case Portal::INTERSECT_CROSS: // node intersects and crosses the portal - recurse into that zone as new home zone if (portal->getTargetZone() != this && portal->getTargetZone() != pczsn->getHomeZone()) { // set the home zone of the node to the target zone of the portal pczsn->setHomeZone(portal->getTargetZone()); // continue checking for portal crossings in the new zone newHomeZone = portal->getTargetZone()->updateNodeHomeZone(pczsn, true); } break; } } // return the new home zone return newHomeZone; }
//================================================================================================= void Location::Save(GameWriter& f, bool) { f << type; f << pos; f << name; f << state; int refid; if(active_quest) { if(active_quest == (Quest_Dungeon*)ACTIVE_QUEST_HOLDER) refid = ACTIVE_QUEST_HOLDER; else refid = active_quest->refid; } else refid = -1; f << refid; f << last_visit; f << st; f << outside; f << reset; f << spawn; f << dont_clean; f << seed; f << image; // portals Portal* p = portal; while(p) { f.Write1(); p->Save(f); p = p->next_portal; } f.Write0(); // events f << events.size(); for(Event& e : events) { f << e.type; f << e.quest->refid; } }
long Portal::dist(Portal &p) const { //Om de är i samma grupp if (p.group->id == this->group->id) { //Om du ska hitta avtåndet i en cykel if (group->type == 1) { if (p.i() < i()) return group->high - i() + 1 + p.i() - group->low; else return p.i() - i(); } //Avståndet i en gren if (group->type == 2) { if (p.in(group) && p.i() > i()) return p.i() - i(); else return -1; } } else { //Om det finns en väg mellan de två nodernas grupper if (group->merge.find(p.group->id) != group->merge.end()) { //Om noden har en index högre än där grenen ansluter till dens grupp if (portals[group->merge[p.group->id].first].i() <= p.i()) { return group->high - i() + 1 + group->merge[p.group->id].second + p.i() - portals[group->merge[p.group->id].first].i(); } else if (p.group->type == 1) { return group->high - i() + 1 + group->merge[p.group->id].second + p.group->high - portals[group->merge[p.group->id].first].i() + p.i() - p.group->low + 1; } } else return -1; } return -1; }
void SoundEvent::visitRoom(Room *room, double strength) { strength *= room->eventMultiplier(GameEventType::Sound); if (strength >= 0.1) { for (const GameObjectPtr &characterPtr : room->characters()) { if (excludedCharacters().contains(characterPtr)) { continue; } Character *character = characterPtr.cast<Character *>(); QString message = descriptionForStrengthAndCharacterInRoom(strength, character, room); if (character->isPlayer()) { character->send(message); } else { character->invokeTrigger("onsound", message); } addAffectedCharacter(characterPtr); } for (const GameObjectPtr &portalPtr : room->portals()) { Portal *portal = portalPtr.cast<Portal *>(); Room *room1 = portal->room().unsafeCast<Room *>(); Room *room2 = portal->room2().unsafeCast<Room *>(); Room *oppositeRoom = (room == room1 ? room2 : room1); if (hasBeenVisited(oppositeRoom) || !portal->canHearThrough()) { continue; } double propagatedStrength = strength * portal->eventMultiplier(GameEventType::Sound); if (propagatedStrength >= 0.1) { addVisit(oppositeRoom, propagatedStrength); } } } }
/* Attempt to automatically connect unconnected portals to proper target zones * by looking for matching portals in other zones which are at the same location */ void PCZSceneManager::connectPortalsToTargetZonesByLocation(void) { // go through every zone to find portals ZoneMap::iterator i, iend; PCZone* zone; iend = mZones.end(); bool foundMatch; for (i = mZones.begin(); i != iend; i++) { zone = i->second; // go through all the portals in the zone Portal* portal; PortalList::iterator pi, piend; piend = zone->mPortals.end(); for (pi = zone->mPortals.begin(); pi != piend; pi++) { portal = *pi; //portal->updateDerivedValues(); if (portal->getTargetZone() == 0) { // this is a portal without a connected zone - look for // a matching portal in another zone PCZone* zone2; ZoneMap::iterator j= mZones.begin(); foundMatch = false; while (!foundMatch && j != mZones.end()) { zone2 = j->second; if (zone2 != zone) // make sure we don't look in the same zone { Portal * portal2 = zone2->findMatchingPortal(portal); if (portal2) { // found a match! Ogre::LogManager::getSingletonPtr()->logMessage("Connecting portal "+portal->getName()+" to portal "+portal2->getName()); foundMatch = true; portal->setTargetZone(zone2); portal->setTargetPortal(portal2); portal2->setTargetZone(zone); portal2->setTargetPortal(portal); } } j++; } if (foundMatch == false) { // error, didn't find a matching portal! OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Could not find matching portal for portal " + portal->getName(), "PCZSceneManager::connectPortalsToTargetZonesByLocation"); } } } } }
// delete a portal instance by pointer void PCZSceneManager::destroyPortal(const String & portalName) { // find the portal from the master portal list Portal * p; Portal * thePortal = 0; PortalList::iterator it = mPortals.begin(); while (it != mPortals.end()) { p = *it; if (p->getName() == portalName) { thePortal = p; // erase entry in the master list mPortals.erase(it); break; } it++; } if (thePortal) { // remove the portal from it's target portal Portal * targetPortal = thePortal->getTargetPortal(); if (targetPortal) { targetPortal->setTargetPortal(0); // the targetPortal will still have targetZone value, but targetPortal will be invalid } // remove the Portal from it's home zone PCZone * homeZone = thePortal->getCurrentHomeZone(); if (homeZone) { // inform zone of portal change homeZone->setPortalsUpdated(true); homeZone->_removePortal(thePortal); } // delete the portal instance OGRE_DELETE thePortal; } }
//Skapa den nya datastrukturen med grupper //Varje nod besöks 1 gång O(N) //a = noden som skall besökas, low = lägsta noden (ny index) som besökts (början på en gren) inline Group * rec(long a, const long & low) { Portal * p = &portals[a]; //Om noden inte har fått en ny index if (p->i() == 0) { //Ge en ny index p->new_index = first++; Group * g = rec(p->exit, low); //Om vi ansluter till en cykel if (g->type == 1) { //Om den nuvarande noden finns i cykeln if (p->in(g)) { //sätt nodens grupp till cykelns return p->group = g; } else { //Annars skapa en gren p->group->type = 2; p->group->merge[portals[p->exit].group->id] = make_pair(p->exit, 0); p->group->low = low; p->group->high = p->new_index; return p->group; } } else { //Om numret inte finns i den nuvarande grenen if (!p->in(g)) { //_(Optimering)_ //Om du ansluter en nod i början av grenen if (portals[p->exit].i() == g->low) { //Flytta upp noderna i grenens index så att de nu är över den nuvarande nodens index g->add += (p->i() - g->low) + 1; g->high += (p->i() - g->low) + 1; first = g->high + 1; p->new_index -= g->add; g->low = low; }else { //Om den nya noden ansluter mitt på grenen skapa en ny gren. p->group->type = 2; //Hämta avtånde och anslutningsinformation från överliggadne gren for (auto item : g->merge) p->group->merge[item.first] = make_pair(item.second.first, item.second.second + g->high - portals[p->exit].i() + 1); p->group->merge[g->id] = make_pair(p->exit, 0); p->group->low = low; p->group->high = p->new_index; return p->group; } } else { //Om noden finns på grenen justera dens index p->new_index -= g->add; } return p->group = g; } } else { //Om noden är besökt men inte har en grupp if (p->group->type == 0) { //Skapa en cykel p->group->type = 1; p->group->low = p->i(); p->group->high = first - 1; return p->group; } else { return p->group; } } }
void DefaultZone::_findNodes( const Ray &t, PCZSceneNodeList &list, PortalList &visitedPortals, bool includeVisitors, bool recurseThruPortals, PCZSceneNode *exclude ) { // if this zone has an enclosure, check against the enclosure AABB first if (mEnclosureNode) { std::pair<bool, Real> nsect = t.intersects(mEnclosureNode->_getWorldAABB()); if (!nsect.first) { // AABB of zone does not intersect t, just return. return; } } // check nodes at home in this zone PCZSceneNodeList::iterator it = mHomeNodeList.begin(); while ( it != mHomeNodeList.end() ) { PCZSceneNode * pczsn = *it; if ( pczsn != exclude ) { // make sure node is not already in the list (might have been added in another // zone it was visiting) PCZSceneNodeList::iterator it2 = list.find(pczsn); if (it2 == list.end()) { std::pair<bool, Real> nsect = t.intersects( pczsn -> _getWorldAABB() ); if ( nsect.first ) { list.insert( pczsn ); } } } ++it; } if (includeVisitors) { // check visitor nodes PCZSceneNodeList::iterator iter = mVisitorNodeList.begin(); while ( iter != mVisitorNodeList.end() ) { PCZSceneNode * pczsn = *iter; if ( pczsn != exclude ) { // make sure node is not already in the list (might have been added in another // zone it was visiting) PCZSceneNodeList::iterator it2 = list.find(pczsn); if (it2 == list.end()) { std::pair<bool, Real> nsect = t.intersects( pczsn -> _getWorldAABB() ); if ( nsect.first ) { list.insert( pczsn ); } } } ++iter; } } // if asked to, recurse through portals if (recurseThruPortals) { PortalList::iterator pit = mPortals.begin(); while ( pit != mPortals.end() ) { Portal * portal = *pit; // check portal versus bounding box if (portal->intersects(t)) { // make sure portal hasn't already been recursed through PortalList::iterator pit2 = std::find(visitedPortals.begin(), visitedPortals.end(), portal); if (pit2 == visitedPortals.end()) { // save portal to the visitedPortals list visitedPortals.push_front(portal); // recurse into the connected zone portal->getTargetZone()->_findNodes(t, list, visitedPortals, includeVisitors, recurseThruPortals, exclude); } } pit++; } } }
/* // Recursively walk the zones, adding all visible SceneNodes to the list of visible nodes. */ void DefaultZone::findVisibleNodes(PCZCamera *camera, NodeList & visibleNodeList, RenderQueue * queue, VisibleObjectsBoundsInfo* visibleBounds, bool onlyShadowCasters, bool displayNodes, bool showBoundingBoxes) { //return immediately if nothing is in the zone. if (mHomeNodeList.size() == 0 && mVisitorNodeList.size() == 0 && mPortals.size() == 0) return ; // Else, the zone is automatically assumed to be visible since either // it is the camera the zone is in, or it was reached because // a connecting portal was deemed visible to the camera. // enable sky if called to do so for this zone if (mHasSky) { // enable sky mPCZSM->enableSky(true); } // find visible nodes at home in the zone bool vis; PCZSceneNodeList::iterator it = mHomeNodeList.begin(); while ( it != mHomeNodeList.end() ) { PCZSceneNode * pczsn = *it; // if the scene node is already visible, then we can skip it if (pczsn->getLastVisibleFrame() != mLastVisibleFrame || pczsn->getLastVisibleFromCamera() != camera) { // for a scene node, check visibility using AABB vis = camera ->isVisible( pczsn -> _getWorldAABB() ); if ( vis ) { // add it to the list of visible nodes visibleNodeList.push_back( pczsn ); // add the node to the render queue pczsn -> _addToRenderQueue(camera, queue, onlyShadowCasters, visibleBounds ); // if we are displaying nodes, add the node renderable to the queue if ( displayNodes ) { queue -> addRenderable( pczsn->getDebugRenderable() ); } // if the scene manager or the node wants the bounding box shown, add it to the queue if (pczsn->getShowBoundingBox() || showBoundingBoxes) { pczsn->_addBoundingBoxToQueue(queue); } // flag the node as being visible this frame pczsn->setLastVisibleFrame(mLastVisibleFrame); pczsn->setLastVisibleFromCamera(camera); } } ++it; } // find visible visitor nodes it = mVisitorNodeList.begin(); while ( it != mVisitorNodeList.end() ) { PCZSceneNode * pczsn = *it; // if the scene node is already visible, then we can skip it if (pczsn->getLastVisibleFrame() != mLastVisibleFrame || pczsn->getLastVisibleFromCamera() != camera) { // for a scene node, check visibility using AABB vis = camera ->isVisible( pczsn -> _getWorldAABB() ); if ( vis ) { // add it to the list of visible nodes visibleNodeList.push_back( pczsn ); // add the node to the render queue pczsn->_addToRenderQueue(camera, queue, onlyShadowCasters, visibleBounds ); // if we are displaying nodes, add the node renderable to the queue if ( displayNodes ) { queue -> addRenderable( pczsn->getDebugRenderable() ); } // if the scene manager or the node wants the bounding box shown, add it to the queue if (pczsn->getShowBoundingBox() || showBoundingBoxes) { pczsn->_addBoundingBoxToQueue(queue); } // flag the node as being visible this frame pczsn->setLastVisibleFrame(mLastVisibleFrame); pczsn->setLastVisibleFromCamera(camera); } } ++it; } // Here we merge both portal and antiportal visible to the camera into one list. // Then we sort them in the order from nearest to furthest from camera. PortalBaseList sortedPortalList; for (AntiPortalList::iterator iter = mAntiPortals.begin(); iter != mAntiPortals.end(); ++iter) { AntiPortal* portal = *iter; if (camera->isVisible(portal)) { sortedPortalList.push_back(portal); } } for (PortalList::iterator iter = mPortals.begin(); iter != mPortals.end(); ++iter) { Portal* portal = *iter; if (camera->isVisible(portal)) { sortedPortalList.push_back(portal); } } const Vector3& cameraOrigin(camera->getDerivedPosition()); std::sort(sortedPortalList.begin(), sortedPortalList.end(), PortalSortDistance(cameraOrigin)); // create a standalone frustum for anti portal use. // we're doing this instead of using camera because we don't need // to do camera frustum check again. PCZFrustum antiPortalFrustum; antiPortalFrustum.setOrigin(cameraOrigin); antiPortalFrustum.setProjectionType(camera->getProjectionType()); // now we do culling check and remove hidden portals. // whenever we get a portal in the main loop, we can be sure that it is not // occluded by AntiPortal. So we do traversal right there and then. // This is because the portal list has been sorted. size_t sortedPortalListCount = sortedPortalList.size(); for (size_t i = 0; i < sortedPortalListCount; ++i) { PortalBase* portalBase = sortedPortalList[i]; if (!portalBase) continue; // skip removed portal. if (portalBase->getTypeFlags() == PortalFactory::FACTORY_TYPE_FLAG) { Portal* portal = static_cast<Portal*>(portalBase); // portal is visible. Add the portal as extra culling planes to camera int planes_added = camera->addPortalCullingPlanes(portal); // tell target zone it's visible this frame portal->getTargetZone()->setLastVisibleFrame(mLastVisibleFrame); portal->getTargetZone()->setLastVisibleFromCamera(camera); // recurse into the connected zone portal->getTargetZone()->findVisibleNodes(camera, visibleNodeList, queue, visibleBounds, onlyShadowCasters, displayNodes, showBoundingBoxes); if (planes_added > 0) { // Then remove the extra culling planes added before going to the next portal in the list. camera->removePortalCullingPlanes(portal); } } else if (i < sortedPortalListCount) // skip antiportal test if it is the last item in the list. { // this is an anti portal. So we use it to test preceding portals in the list. AntiPortal* antiPortal = static_cast<AntiPortal*>(portalBase); int planes_added = antiPortalFrustum.addPortalCullingPlanes(antiPortal); for (size_t j = i + 1; j < sortedPortalListCount; ++j) { PortalBase* otherPortal = sortedPortalList[j]; // Since this is an antiportal, we are doing the inverse of the test. // Here if the portal is fully visible in the anti portal fustrum, it means it's hidden. if (otherPortal && antiPortalFrustum.isFullyVisible(otherPortal)) sortedPortalList[j] = NULL; } if (planes_added > 0) { // Then remove the extra culling planes added before going to the next portal in the list. antiPortalFrustum.removePortalCullingPlanes(antiPortal); } } } }
bool Portal::_setBackSidePassable( void* object, const char* index, const char* data ) { Portal* portal = reinterpret_cast< Portal* >( object ); portal->setSidePassable( Portal::BackSide, EngineUnmarshallData< bool >()( data ) ); return false; }
void FunctionalPortal::createEnvironmentMap(const std::vector<Portal *> *portals){ Portal *destPortal = (*portals)[iDestPortal]; Vec3 portalPos = destPortal->getPos(); Vec3 eyePos; vecAdd(&destPos_pcoord, &portalPos, &eyePos); bool oldHide = isHidden(); setHide(true); GL_CHECK(glMatrixMode(GL_MODELVIEW)); GL_CHECK(glPushMatrix()); GL_CHECK(glMatrixMode(GL_PROJECTION)); GL_CHECK(glPushMatrix()); GL_CHECK(glPushAttrib(GL_VIEWPORT_BIT)); //GL_CHECK(glBindTexture(GL_TEXTURE_2D, 0)); tgr->bind(); //GL_CHECK(glBindTexture(GL_TEXTURE_2D, dstDepthmap)); //GL_CHECK(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, //GL_TEXTURE_2D, dstDepthmap, 0)); /*GLuint id = renderTgr->genColorTexutre(); glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, id, 0); struct MAZErectangle viewport; viewport.left = 0; viewport.bottom = 0; viewport.width = width; viewport.height = height; struct Vec3 centerPos = vec2vecAdd(&eyePos, 0, 0, -10); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(eyePos.x, eyePos.y, eyePos.z, centerPos.x, centerPos.y, centerPos.z, 0, 1, 0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); struct MAZEmat projviewMat; struct MAZEmat viewportMat; getWindowProjMat(viewport, projviewMat, viewportMat); hash_set<int *> visitedEdgeSet; destPortal->cullDraw(&projviewMat, &viewportMat, viewport, portals, visitedEdgeSet); glBindTexture(GL_TEXTURE_2D, id); //debug sf::Uint8 *pixelArray = new sf::Uint8[width*height*4]; glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelArray); // to read from texture instead sf::Image temp(width, height, pixelArray); std::string filename = "envmap"; //char a[2] = {'a'+i, '\0'}; //filename.append(a); filename.append(".jpg"); temp.SaveToFile(filename); return;*/ glMatrixMode(GL_PROJECTION); GLfloat aspectRatio = 1.; GLfloat nearClip = 0.1f; GLfloat farClip = 400.0f; GLfloat fieldOfView = 90.0f; // Degrees glLoadIdentity(); gluPerspective(fieldOfView, aspectRatio, nearClip, farClip); glViewport(0, 0, width, height); float lookVectors[24] = { 1, 0, 0, 1, -1, 0, 0, 1, 0, 1, 0, 1, 0, -1, 0, 1, 0, 0, 1, 1, 0, 0, -1, 1 }; float up[24] = { 0, -1, 0, 1, 0, -1, 0, 1, 0, 0, 1, 1, 0, 0, -1, 1, 0, -1, 0, 1, 0, -1, 0, 1 }; struct MAZErectangle viewport; viewport.left = 0; viewport.bottom = 0; viewport.width = width; viewport.height = height; GL_CHECK(glBindTexture(GL_TEXTURE_CUBE_MAP, dstCubemap)); struct Vec3 centerPos = vec2vecAdd(&eyePos, lookVectors[direction*4], lookVectors[direction*4+1], lookVectors[direction*4+2]); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); GL_CHECK(gluLookAt(eyePos.x, eyePos.y, eyePos.z, centerPos.x, centerPos.y, centerPos.z, up[direction*4], up[direction*4+1], up[direction*4+2])); GL_CHECK(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_CUBE_MAP_POSITIVE_X+src_lookDirection, dstCubemap, 0)); /*if(GL_FRAMEBUFFER_COMPLETE_EXT != glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)){ cerr << "Invalid framebuffer configuration: ERROR CODE " << glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); exit(-1); }*/ GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); struct MAZEmat projviewMat; struct MAZEmat viewportMat; getWindowProjMat(viewport, projviewMat, viewportMat); set<int *> visitedEdgeSet; cout << "here1" <<endl; destPortal->cullDraw(&projviewMat, &viewportMat, viewport, portals, visitedEdgeSet); //GL_CHECK(glBindTexture(GL_TEXTURE_CUBE_MAP, dstCubemap)); /* //debug sf::Uint8 *pixelArray = new sf::Uint8[width*height*4]; glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X+src_lookDirection, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelArray); // to read from texture instead sf::Image temp(width, height, pixelArray); std::string filename = "envmap"; char a[2] = {'a'+src_lookDirection, '\0'}; filename.append(a); filename.append(".jpg"); temp.SaveToFile(filename); delete pixelArray;*/ glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); tgr->unbind(); setHide(oldHide); }
bool Portal::cullDraw(struct MAZEmat *projviewMat, struct MAZEmat *viewportMat, struct MAZErectangle &rec, const std::vector<Portal *> *portals, set<int *> &visitedEdgeSet){ MAZEmat finalProjViewMat; multMat(projviewMat, &transformation, &finalProjViewMat); //TODO: implement BV for objects glMatrixMode(GL_MODELVIEW); glPushMatrix(); //glMultMatrixf(transformation.mat); if(!portalObj->isHidden()) portalObj->draw(portals); for(int i=0; i<objs.size(); i++) if(!objs[i]->isHidden()) objs[i]->draw(portals); glMatrixMode(GL_MODELVIEW); glPopMatrix(); //What this portal looks like in its neighbors eye... int posMap[4] = {1, 0, 3, 2}; for(int i=0; i<4; i++){ if(neighbors[i] < 0) continue; //Have we visited this undirected edge? //I know the following code seems a little hack //but I can't find any better way... Portal *port = (*portals)[neighbors[i]]; if(visitedEdgeSet.count(port->getNeighbors()+posMap[i]) > 0 || visitedEdgeSet.count(neighbors+i)) continue; //int size1 = visitedEdgeSet.size(); visitedEdgeSet.insert(neighbors+i); //int size2 = visitedEdgeSet.size(); /*if(size2 == size1){ cout << "not right" << endl; }*/ //assert(visitedEdgeSet.size()<4*(*portals).size()); //cout<<"visitedEdge " << visitedEdgeSet.size() << endl; struct Vec3 p[4]; float left = MY_FLT_MAX, right = MY_FLT_MIN, top = MY_FLT_MIN, bottom = MY_FLT_MAX; float nearC = MY_FLT_MAX, farC = MY_FLT_MIN; for(int j=0; j<4; j++){ struct Vec3 tmp; matMultVec3_normalize(&finalProjViewMat, &doorPoints[i][j], &tmp); matMultVec3_normalize(viewportMat, &tmp, p+j); if(p[j].x < left) left = p[j].x; if(p[j].x > right) right = p[j].x; if(p[j].y > top) top = p[j].y; if(p[j].y < bottom) bottom = p[j].y; if(p[j].z < nearC) nearC = p[j].z; if(p[j].z > farC) farC = p[j].z; } if(farC < 0 || nearC > 1) continue; left = left > rec.left ? left : rec.left; right = right < (rec.left+rec.width) ? right : rec.left+rec.width; bottom = bottom > rec.bottom ? bottom : rec.bottom; top = top < (rec.bottom + rec.height) ? top : rec.bottom+rec.height; MAZErectangle neighborRect; neighborRect.left = left; neighborRect.bottom = bottom; neighborRect.height = top-bottom; neighborRect.width = right-left; //This is necessary for edge condition if(neighborRect.height <= -1e-5 || neighborRect.width <= -1e-5) continue; //Door status switched. If it is open from this cell to its //neighbor, we might visit that neighbor. When we are visiting //the neighbor, we will close the door and would not visit this //cell. Is it still possible that we might loop back to visited portal? //If the door is open, visit it. //NOTE: Theorectically it's possible that a single object in a cell //can be rendered several times from different doors. TODO: I might add some //mask to handle this problem in the future. But, for this maze game, //this scenario seems unlikely. So ignore it for now. port->cullDraw(projviewMat, viewportMat, neighborRect, portals, visitedEdgeSet); } return true; }
void Hero::update() { if (mySpawnPortal) { mySpawnPortalFrameCounter++; if (mySpawnPortalFrameCounter == 1) { Portal* portal = new Portal(); portal->setPosition(getPosition()); getRoom()->addEntity(portal); return; } else if (mySpawnPortalFrameCounter >= 60 * 5) { mySpawnPortal = false; } else { return; } } if (myIsDead) return; Entity::update(); mFramesSinceLandPlayed++; if (mGravityHitTimer <= 0){ mGravityDirection=1; } else { mGravityHitTimer--; } if (touchesDangerousTile()) { die(); } //checkEnemies(); if (mSpawnPoint.x < -100 && mSpawnPoint.y < -100) { mSpawnPoint = getPosition(); } float acceleration = mOnGround ? GROUND_ACCELERATION : AIR_ACCELERATION; if (Input::isHeld(Button_Left)) { mVelocity.x -= acceleration; mFacingDirection = Direction_Left; } if (Input::isHeld(Button_Right)) { mVelocity.x += acceleration; mFacingDirection = Direction_Right; } if(Input::isPressed(Button_Fire) && GameState::getInt(GameState::POWERUP_GRENADE) != 0){ mWeaponSelected = Weapon_Gravity_Grenade; fireWeapon(); } if(Input::isPressed(Button_ToggleWeapon) && GameState::getInt(GameState::POWERUP_GUN) != 0){ mWeaponSelected = Weapon_Gun; fireWeapon(); } mVelocity.x = clamp(mVelocity.x, -MAX_X_VELOCITY, MAX_X_VELOCITY); if (Input::isPressed(Button_Jump)) { mJumpPrepressed = true; } if (mOnGround && mJumpPrepressed) { Sound::playSample("data/sounds/jump.wav"); mVelocity.y = GameState::getInt(GameState::POWERUP_HIJUMP) ? -HI_JUMP_VELOCITY : -JUMP_VELOCITY; mJumpHeld = true; mJumpPrepressed = false; } if (Input::isReleased(Button_Jump)) { if (mJumpHeld && mVelocity.y < 0) { mVelocity.y *= 0.5f; } mJumpHeld = false; mJumpPrepressed = false; } if (mVelocity.y >= 0) { mJumpHeld = false; } mMovementState = MovementState_Still; if (mOnGround) { if (abs(mVelocity.x) > GROUND_STOP_VELOCITY) { mMovementState = MovementState_Run; } } else { if (mVelocity.y < 0) { mMovementState = MovementState_Jump; } else { mMovementState = MovementState_Fall; } } if (mMovementState == MovementState_Still) { mVelocity.x = 0; } bool ground = moveOutOfSolidEntities(); float2 usedVelocity(mVelocity.x, clamp(mVelocity.y, -MAX_Y_VELOCITY, MAX_Y_VELOCITY)); unsigned int bumps = moveWithCollision(usedVelocity / Time::TicksPerSecond); if ((bumps & (Direction_Left | Direction_Right)) != 0) { mVelocity.x = 0; } if ((bumps & (Direction_Up | Direction_Down)) != 0) { mVelocity.y = 0; } float gravity = mJumpHeld ? JUMP_GRAVITY : GRAVITY; mVelocity.y += gravity * getGravityDirection(); ground |= ((bumps & Direction_Down) != 0); if (ground && !mOnGround) { if (mFramesSinceLandPlayed > 6) { Sound::playSample("data/sounds/land.wav"); } mFramesSinceLandPlayed = 0; } mOnGround = ground; float drag = mOnGround ? GROUND_DRAG : AIR_DRAG; mVelocity *= drag; mFrame ++; if (mBlinkingTicksLeft) { mBlinkingTicksLeft --; } }
void Camera::Update() { //float dt = TheTimer::Instance()->GetDt(); Vec3f pos; if (m_target) { pos = m_target->GetPos(); // yRotAuto = 0; #ifdef AUTO_ROTATE // Swing behind target float dir = m_target->GetDir() + 180.0f; float angleDiff = yRotAuto - dir; // Rotate to face m_dir, taking the shortest route (CW or CCW) if (fabs(angleDiff) < 0.1f) // TODO CONFIG { yRotAuto = dir; } else { float ROT_SPEED = 1.0f; // TODO CONFIG if (yRotAuto > dir) { yRotAuto -= ROT_SPEED * dt * fabs(angleDiff); } else if (yRotAuto < dir) { yRotAuto += ROT_SPEED * dt * fabs(angleDiff); } } #endif // AUTO_ROTATE #ifdef PORTAL_ROTATE // TODO Get closest portal static PGameObject lastportal = 0; // We want to get the closest portal to the target, even if they have never intersected it. int pid = m_target->GetIgnorePortalId(); if (pid > -1) { lastportal = TheGame::Instance()->GetGameObject(pid); } else { // Look for portals in this room, find closest. // TODO Optimise // just check periodically ? Portals portals = GetPortals(); float bestSqDist = 999999.9f; for (Portals::iterator it = portals.begin(); it != portals.end(); ++it) { Portal* p = *it; float sqDist = (p->GetPos() - pos).SqLen(); if (sqDist < bestSqDist) { bestSqDist = sqDist; lastportal = p; } } } if (lastportal) { float pdist = (pos - lastportal->GetPos()).SqLen(); // sq dist from portal to player static const float MAX_DIST = ROConfig()->GetFloat("portal-max-dist", 200.0f); static const float MAX_SQ_DIST = MAX_DIST * MAX_DIST; if (pdist < MAX_SQ_DIST) { yRotAuto = atan2(-pos.x, pos.z) * (1.0f - pdist / MAX_SQ_DIST); //std::cout << "SQ Dist from portal: " << pdist << " pos.z=" << pos.z << " pos.x=" << pos.x << " yRotAuto degs=" << RadToDeg(yRotAuto) << "\n"; } } #endif // PORTAL_ROTATE } else { pos = posNoTarget; } pos += posOffset; float y = DegToRad(yRotAuto + yRotUser); SetEyePos(Vec3f( pos.x + sin(y) * cos(xRot) * zDist, pos.y + sin(xRot) * zDist, pos.z + cos(y) * cos(xRot) * zDist)); SetLookAtPos(pos); }
void CommandInterpreter::execute(Character *character, const QString &_command) { static QRegExp whitespace("\\s+"); try { QString command = _command.trimmed(); LogUtil::logCommand(character->name(), command); QStringList words = command.split(whitespace); QString commandName = words[0].toLower(); if (commandName.isEmpty()) { return; } if (Util::isDirectionAbbreviation(commandName)) { words[0] = Util::direction(commandName); commandName = words[0]; } if (Util::isDirection(commandName)) { words.prepend("go"); m_registry->command("go")->execute(character, words.join(" ")); return; } else { Room *currentRoom = character->currentRoom().cast<Room *>(); bool matchedPortal = false; for (const GameObjectPtr &portalPtr : currentRoom->portals()) { Portal *portal = portalPtr.cast<Portal *>(); QString portalName = portal->nameFromRoom(character->currentRoom()); if (portalName == commandName) { matchedPortal = true; } else { for (const QString &portalNamePart : portalName.split(' ')) { if (portalNamePart == commandName) { matchedPortal = true; } } } } if (matchedPortal) { words.prepend("go"); m_registry->command("go")->execute(character, words.join(" ")); return; } } QStringList commands; if (m_registry->contains(commandName)) { m_registry->command(commandName)->execute(character, command); return; } else { for (const QString &name : m_registry->commandNames()) { if (name.startsWith(commandName)) { commands.append(name); } } } if (character->isPlayer() && qobject_cast<Player *>(character)->isAdmin()) { if (commandName.startsWith("api-")) { if (m_registry->apiCommandsContains(commandName)) { m_registry->apiCommand(commandName)->execute(character, command); return; } } else { if (m_registry->adminCommandsContains(commandName)) { m_registry->adminCommand(commandName)->execute(character, command); return; } else { for (const QString &name : m_registry->adminCommandNames()) { if (name.startsWith(commandName)) { commands.append(name); } } } } } if (commands.length() == 1) { commandName = commands[0]; if (m_registry->contains(commandName)) { m_registry->command(commandName)->execute(character, command); } else if (m_registry->adminCommandsContains(commandName)) { m_registry->adminCommand(commandName)->execute(character, command); } } else if (commands.length() > 1) { character->send("Command is not unique."); } else { character->send(QString("Command \"%1\" does not exist.").arg(words[0])); } } catch (GameException &exception) { if (character->isPlayer()) { Player *player = qobject_cast<Player *>(character); player->send(QString("Executing the command gave an exception: ") + exception.what()); if (!player->isAdmin()) { player->send("This is not good. You may want to contact a game admin about this."); } } } catch (...) { if (character->isPlayer()) { Player *player = qobject_cast<Player *>(character); player->send("Executing the command gave an unknown exception."); if (!player->isAdmin()) { player->send("This is not good. You may want to contact a game admin about this."); } } } }
Node* EditorSceneImportPlugin::_fix_node(Node *p_node,Node *p_root,Map<Ref<Mesh>,Ref<Shape> > &collision_map,uint32_t p_flags,Set<Ref<ImageTexture> >& image_map) { // children first.. for(int i=0;i<p_node->get_child_count();i++) { Node *r = _fix_node(p_node->get_child(i),p_root,collision_map,p_flags,image_map); if (!r) { print_line("was erased.."); i--; //was erased } } String name = p_node->get_name(); bool isroot = p_node==p_root; if (!isroot && p_flags&SCENE_FLAG_REMOVE_NOIMP && _teststr(name,"noimp")) { memdelete(p_node); return NULL; } { List<PropertyInfo> pl; p_node->get_property_list(&pl); for(List<PropertyInfo>::Element *E=pl.front();E;E=E->next()) { if (E->get().type==Variant::OBJECT || E->get().type==Variant::ARRAY || E->get().type==Variant::DICTIONARY) { _find_resources(p_node->get(E->get().name),image_map); } } } if (p_flags&SCENE_FLAG_CREATE_BILLBOARDS && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); bool bb=false; if ((_teststr(name,"bb"))) { bb=true; } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"bb"))) { bb=true; } if (bb) { mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true); if (mi->get_mesh().is_valid()) { Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { Ref<FixedMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { fm->set_flag(Material::FLAG_UNSHADED,true); fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true); fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); } } } } } if (p_flags&SCENE_FLAG_REMOVE_NOIMP && p_node->cast_to<AnimationPlayer>()) { //remove animations referencing non-importable nodes AnimationPlayer *ap = p_node->cast_to<AnimationPlayer>(); List<StringName> anims; ap->get_animation_list(&anims); for(List<StringName>::Element *E=anims.front();E;E=E->next()) { Ref<Animation> anim=ap->get_animation(E->get()); ERR_CONTINUE(anim.is_null()); for(int i=0;i<anim->get_track_count();i++) { NodePath path = anim->track_get_path(i); for(int j=0;j<path.get_name_count();j++) { String node = path.get_name(j); if (_teststr(node,"noimp")) { anim->remove_track(i); i--; break; } } } } } if (p_flags&SCENE_FLAG_CREATE_IMPOSTORS && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); String str; if ((_teststr(name,"imp"))) { str=name; } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"imp"))) { str=mi->get_mesh()->get_name(); } if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>(); String d=str.substr(str.find("imp")+3,str.length()); if (d!="") { if ((d[0]<'0' || d[0]>'9')) d=d.substr(1,d.length()); if (d.length() && d[0]>='0' && d[0]<='9') { float dist = d.to_double(); mi->set_flag(GeometryInstance::FLAG_BILLBOARD,true); mi->set_flag(GeometryInstance::FLAG_BILLBOARD_FIX_Y,true); mi->set_draw_range_begin(dist); mi->set_draw_range_end(100000); mip->set_draw_range_begin(0); mip->set_draw_range_end(dist); if (mi->get_mesh().is_valid()) { Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { Ref<FixedMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { fm->set_flag(Material::FLAG_UNSHADED,true); fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true); fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); } } } } } } } if (p_flags&SCENE_FLAG_CREATE_LODS && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); String str; if ((_teststr(name,"lod"))) { str=name; } else if (mi->get_mesh().is_valid() && (_teststr(mi->get_mesh()->get_name(),"lod"))) { str=mi->get_mesh()->get_name(); } if (p_node->get_parent() && p_node->get_parent()->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); MeshInstance *mip = p_node->get_parent()->cast_to<MeshInstance>(); String d=str.substr(str.find("lod")+3,str.length()); if (d!="") { if ((d[0]<'0' || d[0]>'9')) d=d.substr(1,d.length()); if (d.length() && d[0]>='0' && d[0]<='9') { float dist = d.to_double(); mi->set_draw_range_begin(dist); mi->set_draw_range_end(100000); mip->set_draw_range_begin(0); mip->set_draw_range_end(dist); /*if (mi->get_mesh().is_valid()) { Ref<Mesh> m = mi->get_mesh(); for(int i=0;i<m->get_surface_count();i++) { Ref<FixedMaterial> fm = m->surface_get_material(i); if (fm.is_valid()) { fm->set_flag(Material::FLAG_UNSHADED,true); fm->set_flag(Material::FLAG_DOUBLE_SIDED,true); fm->set_hint(Material::HINT_NO_DEPTH_DRAW,true); fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); } } }*/ } } } } if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(name,"colonly") && p_node->cast_to<MeshInstance>()) { if (isroot) return p_node; MeshInstance *mi = p_node->cast_to<MeshInstance>(); Node * col = mi->create_trimesh_collision_node(); ERR_FAIL_COND_V(!col,NULL); col->set_name(_fixstr(name,"colonly")); col->cast_to<Spatial>()->set_transform(mi->get_transform()); p_node->replace_by(col); memdelete(p_node); p_node=col; } else if (p_flags&SCENE_FLAG_CREATE_COLLISIONS &&_teststr(name,"col") && p_node->cast_to<MeshInstance>()) { MeshInstance *mi = p_node->cast_to<MeshInstance>(); mi->set_name(_fixstr(name,"col")); mi->create_trimesh_collision(); } else if (p_flags&SCENE_FLAG_CREATE_ROOMS && _teststr(name,"room") && p_node->cast_to<MeshInstance>()) { if (isroot) return p_node; MeshInstance *mi = p_node->cast_to<MeshInstance>(); DVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID); BSP_Tree bsptree(faces); Ref<RoomBounds> area = memnew( RoomBounds ); area->set_bounds(faces); area->set_geometry_hint(faces); Room * room = memnew( Room ); room->set_name(_fixstr(name,"room")); room->set_transform(mi->get_transform()); room->set_room(area); p_node->replace_by(room); memdelete(p_node); p_node=room; } else if (p_flags&SCENE_FLAG_CREATE_ROOMS &&_teststr(name,"room")) { if (isroot) return p_node; Spatial *dummy = p_node->cast_to<Spatial>(); ERR_FAIL_COND_V(!dummy,NULL); Room * room = memnew( Room ); room->set_name(_fixstr(name,"room")); room->set_transform(dummy->get_transform()); p_node->replace_by(room); memdelete(p_node); p_node=room; room->compute_room_from_subtree(); } else if (p_flags&SCENE_FLAG_CREATE_PORTALS &&_teststr(name,"portal") && p_node->cast_to<MeshInstance>()) { if (isroot) return p_node; MeshInstance *mi = p_node->cast_to<MeshInstance>(); DVector<Face3> faces = mi->get_faces(VisualInstance::FACES_SOLID); ERR_FAIL_COND_V(faces.size()==0,NULL); //step 1 compute the plane Set<Vector3> points; Plane plane; Vector3 center; for(int i=0;i<faces.size();i++) { Face3 f = faces.get(i); Plane p = f.get_plane(); plane.normal+=p.normal; plane.d+=p.d; for(int i=0;i<3;i++) { Vector3 v = f.vertex[i].snapped(0.01); if (!points.has(v)) { points.insert(v); center+=v; } } } plane.normal.normalize(); plane.d/=faces.size(); center/=points.size(); //step 2, create points Transform t; t.basis.from_z(plane.normal); t.basis.transpose(); t.origin=center; Vector<Point2> portal_points; for(Set<Vector3>::Element *E=points.front();E;E=E->next()) { Vector3 local = t.xform_inv(E->get()); portal_points.push_back(Point2(local.x,local.y)); } // step 3 bubbly sort points int swaps=0; do { swaps=0; for(int i=0;i<portal_points.size()-1;i++) { float a = portal_points[i].atan2(); float b = portal_points[i+1].atan2(); if (a>b) { SWAP( portal_points[i], portal_points[i+1] ); swaps++; } } } while(swaps); Portal *portal = memnew( Portal ); portal->set_shape(portal_points); portal->set_transform( mi->get_transform() * t); p_node->replace_by(portal); memdelete(p_node); p_node=portal; } else if (p_node->cast_to<MeshInstance>()) { //last attempt, maybe collision insde the mesh data MeshInstance *mi = p_node->cast_to<MeshInstance>(); Ref<Mesh> mesh = mi->get_mesh(); if (!mesh.is_null()) { if (p_flags&SCENE_FLAG_CREATE_COLLISIONS && _teststr(mesh->get_name(),"col")) { mesh->set_name( _fixstr(mesh->get_name(),"col") ); Ref<Shape> shape; if (collision_map.has(mesh)) { shape = collision_map[mesh]; } else { shape = mesh->create_trimesh_shape(); if (!shape.is_null()) collision_map[mesh]=shape; } if (!shape.is_null()) { #if 0 StaticBody* static_body = memnew( StaticBody ); ERR_FAIL_COND_V(!static_body,NULL); static_body->set_name( String(mesh->get_name()) + "_col" ); shape->set_name(static_body->get_name()); static_body->add_shape(shape); mi->add_child(static_body); if (mi->get_owner()) static_body->set_owner( mi->get_owner() ); #endif } } for(int i=0;i<mesh->get_surface_count();i++) { Ref<FixedMaterial> fm = mesh->surface_get_material(i); if (fm.is_valid()) { String name = fm->get_name(); if (_teststr(name,"alpha")) { fm->set_fixed_flag(FixedMaterial::FLAG_USE_ALPHA,true); name=_fixstr(name,"alpha"); } if (_teststr(name,"vcol")) { fm->set_fixed_flag(FixedMaterial::FLAG_USE_COLOR_ARRAY,true); name=_fixstr(name,"vcol"); } fm->set_name(name); } } } } return p_node; }
void physics(Game *g) { g->mouseThrustOn=false; //ball collision if(gameStarted){ ball.setYVel(ball.getYVel()); ball.setXVel(ball.getXVel()); obstacle->setYVel(obstacle->getYVel()); bool is_ball_hit_edge = ball.checkCollision(xres, yres); if (is_ball_hit_edge){ lastPaddleHit = 'N'; } } //paddle collision bool isLeftHit = paddle1.checkCollision(yres, ball); if (isLeftHit){ lastPaddleHit = 'L'; } bool isRightHit = paddle2.checkCollision(yres, ball); if (isRightHit){ lastPaddleHit = 'R'; } if(level == 2){ obstacle->checkCollision(xres, yres, ball, p1); } //paddle1 movement paddle1.setYVel(paddle1YVel); //paddle2 movement paddle2.setYVel(paddle2YVel); if (level == 1 && hud->isPaused()==false){ //SET BOMBS POSITION: bomb_theta = bomb_theta + speed_theta; if (fabs(bomb_theta) >= 2*PI){ bomb_theta=0; speed_theta *= -1; } bomb_posx=(int)(xres/2 + bomb_radius*cos(bomb_theta - PI/2) - bomb_width/2); bomb_posy=(int)(yres/2 + bomb_radius*sin(bomb_theta - PI/2) - bomb_height/2); //CHECK LEFT COLLISION WITH BOMB: if ((beginSmallLeftPaddle + smallLeftPaddleTime) < time(NULL)){ paddle1.setHeight(100.0f); bool isBallBetweenX = (ball.getXPos() > bomb_posx) && (ball.getXPos() < (bomb_posx + bomb_width)); bool isBallBetweenY = (ball.getYPos() > bomb_posy) && (ball.getYPos() < (bomb_posy + bomb_height)); if (lastPaddleHit == 'L' && (isBallBetweenX && isBallBetweenY)){ bombBegin = time(NULL); createSound(8); createSound(9); //set to half normal height: paddle1.setHeight(60.0f); if (hud->getPlayer1Health()>0){ hud->setPlayer1Health(hud->getPlayer1Health()-10*(1+random(8))); //GAMEOVER: if (hud->getPlayer1Health() <= 0){ createSound(5); is_gameover = true; ball.setXVel(0.0f); ball.setYVel(0.0f); stopGame(); } } beginSmallLeftPaddle = time(NULL); } } //CHECK RIGHT COLLISION WITH BOMB: if ((beginSmallRightPaddle + smallRightPaddleTime) < time(NULL)){ paddle2.setHeight(100.0f); //is_bomb_visible = true; bool isBallBetweenX = (ball.getXPos() > bomb_posx) && (ball.getXPos() < (bomb_posx + bomb_width)); bool isBallBetweenY = (ball.getYPos() > bomb_posy) && (ball.getYPos() < (bomb_posy + bomb_height)); if (lastPaddleHit == 'R' && (isBallBetweenX && isBallBetweenY)){ bombBegin = time(NULL); createSound(8); createSound(9); //is_bomb_visible = false; //set to half normal height: paddle2.setHeight(60.0f); if (hud->getPlayer2Health()>0){ hud->setPlayer2Health(hud->getPlayer2Health()- 10*(1+random(8))); //GAMEOVER: if (hud->getPlayer2Health() <= 0){ createSound(5); is_gameover = true; ball.setXVel(0.0f); ball.setYVel(0.0f); stopGame(); } } beginSmallRightPaddle = time(NULL); } } if(ball.getXPos() >= (xres/2)){ portal1.checkCollision(ball, portal0); } else { portal0.checkCollision(ball, portal1); } }//end if level 1 and not paused }
void init(Game *g) { portal0.setPortalType(0); portal1.setPortalType(1); g->mouseThrustOn=false; }
/** (recursive) check the given light against all portals in the zone * NOTE: This is the default implementation, which doesn't take advantage * of any zone-specific optimizations for checking portal visibility */ void DefaultZone::_checkLightAgainstPortals(PCZLight *light, unsigned long frameCount, PCZFrustum *portalFrustum, Portal * ignorePortal) { for ( PortalList::iterator it = mPortals.begin(); it != mPortals.end(); ++it ) { Portal * p = *it; if (p != ignorePortal) { // calculate the direction vector from light to portal Vector3 lightToPortal = p->getDerivedCP() - light->getDerivedPosition(); if (portalFrustum->isVisible(p)) { // portal is facing the light, but some light types need to // check illumination radius too. PCZone * targetZone = p->getTargetZone(); switch(light->getType()) { case Light::LT_POINT: // point lights - just check if within illumination range if (lightToPortal.length() <= light->getAttenuationRange()) { // if portal is quad portal it must be pointing towards the light if ((p->getType() == Portal::PORTAL_TYPE_QUAD && lightToPortal.dotProduct(p->getDerivedDirection()) < 0.0) || (p->getType() != Portal::PORTAL_TYPE_QUAD)) { if (!light->affectsZone(targetZone)) { light->addZoneToAffectedZonesList(targetZone); if (targetZone->getLastVisibleFrame() == frameCount) { light->setAffectsVisibleZone(true); } // set culling frustum from the portal portalFrustum->addPortalCullingPlanes(p); // recurse into the target zone of the portal p->getTargetZone()->_checkLightAgainstPortals(light, frameCount, portalFrustum, p->getTargetPortal()); // remove the planes added by this portal portalFrustum->removePortalCullingPlanes(p); } } } break; case Light::LT_DIRECTIONAL: // directionals have infinite range, so just make sure // the direction is facing the portal if (lightToPortal.dotProduct(light->getDerivedDirection()) >= 0.0) { // if portal is quad portal it must be pointing towards the light if ((p->getType() == Portal::PORTAL_TYPE_QUAD && lightToPortal.dotProduct(p->getDerivedDirection()) < 0.0) || (p->getType() != Portal::PORTAL_TYPE_QUAD)) { if (!light->affectsZone(targetZone)) { light->addZoneToAffectedZonesList(targetZone); if (targetZone->getLastVisibleFrame() == frameCount) { light->setAffectsVisibleZone(true); } // set culling frustum from the portal portalFrustum->addPortalCullingPlanes(p); // recurse into the target zone of the portal p->getTargetZone()->_checkLightAgainstPortals(light, frameCount, portalFrustum, p->getTargetPortal()); // remove the planes added by this portal portalFrustum->removePortalCullingPlanes(p); } } } break; case Light::LT_SPOTLIGHT: // spotlights - just check if within illumination range // Technically, we should check if the portal is within // the cone of illumination, but for now, we'll leave that // as a future optimisation. if (lightToPortal.length() <= light->getAttenuationRange()) { // if portal is quad portal it must be pointing towards the light if ((p->getType() == Portal::PORTAL_TYPE_QUAD && lightToPortal.dotProduct(p->getDerivedDirection()) < 0.0) || (p->getType() != Portal::PORTAL_TYPE_QUAD)) { if (!light->affectsZone(targetZone)) { light->addZoneToAffectedZonesList(targetZone); if (targetZone->getLastVisibleFrame() == frameCount) { light->setAffectsVisibleZone(true); } // set culling frustum from the portal portalFrustum->addPortalCullingPlanes(p); // recurse into the target zone of the portal p->getTargetZone()->_checkLightAgainstPortals(light, frameCount, portalFrustum, p->getTargetPortal()); // remove the planes added by this portal portalFrustum->removePortalCullingPlanes(p); } } } break; } } } } }
void render(Game *g) { g->mouseThrustOn=false; glClear(GL_COLOR_BUFFER_BIT); if(intro < 1) { char screen; if (selected_screen == LEFT){ screen = 'L'; } else{ screen = 'R'; } if (hud->isShowWelcome() == true){ hud->showIntro(screen,introTexture, bgTexture1, bgTexture2); if (hud->getAI() == true){ hud->selectAI(); } else{ hud->selectHuman(); } return; } else if (hud->isShowHelpMenu() == true){ hud->showHelpMenu(helpMenuTexture); return; } return; } else{ renderTexture(bgTexture, xres, yres); } if (is_gameover){ renderTexture(gameOverTexture, xres, yres); high_score = setHighScore(ball.getPlayer1Score(), ball.getPlayer2Score()); //cout << "Final Score : " << high_score << "\n"; hud->showGameOver(high_score,ball.getPlayer1Score(), ball.getPlayer2Score()); return; } hud->showScore(ball.getPlayer1Score(), ball.getPlayer2Score()); hud->showHealth(hud->getPlayer1Health(), hud->getPlayer2Health()); hud->showCourtYard(); //DRAW BOMB: if (level == 1){ GLuint which_bomb_texture = bombTexture; if ((bombBegin + 2) > time(NULL)){ which_bomb_texture = explodeTexture; } else{ which_bomb_texture = bombTexture; } portal0.render(portalTexture0); portal1.render(portalTexture1); hud->renderBomb(which_bomb_texture,bomb_posx,bomb_posy,bomb_width,bomb_height); } //Draw the paddle glColor3f(0.0, 0.5, 0.5); paddle1.render(); glColor3f(0.7, 0.5, 0.0); paddle2.render(); glEnd(); //Draw the ball ball.render(); //If option 2 is selected i.e. ninja_robot.ppm is the background //Level 2 selected //Draw some obstacles to showcase a difference between level 1 and level2 if(level == 2) { obstacle->render(); } hud->showTimer(getTimer()); if (hud->isPaused()){ hud->showPaused(pausedTexture); } }
/** Update the zone data for the portals in the zone * NOTE: All portal spatial data must be up-to-date before calling this routine. */ void DefaultZone::updatePortalsZoneData(void) { PortalList transferPortalList; AntiPortalList transferAntiPortalList; // check each portal to see if it's intersecting another portal of smaller size for ( PortalList::iterator it = mPortals.begin(); it != mPortals.end(); ++it ) { Portal * p = *it; bool portalNeedUpdate = p->needUpdate(); Real pRadius = p->getRadius(); // First we check against portals in the SAME zone (and only if they have a // target zone different from the home zone) // Here we check only against portals that moved and of smaller size. // We do not need to check portal againts previous portals // since it would have been already checked. // Hence we start with the next portal after the current portal. PortalList::iterator it2 = it; for ( ++it2; it2 != mPortals.end(); ++it2 ) { Portal * p2 = (*it2); // Skip portal if it doesn't need updating. // If both portals are not moving, then there's no need to check between them. if (!portalNeedUpdate && !p2->needUpdate()) continue; // Skip portal if it's not pointing to another zone. if (p2->getTargetZone() == this) continue; // Skip portal if it's pointing to the same target zone as this portal points to if (p2->getTargetZone() == p->getTargetZone()) continue; if (pRadius > p2->getRadius()) { // Portal#1 is bigger than Portal#2, check for crossing if (p2->getCurrentHomeZone() != p->getTargetZone() && p2->crossedPortal(p)) { // portal#2 crossed portal#1 - flag portal#2 to be moved to portal#1's target zone p2->setNewHomeZone(p->getTargetZone()); transferPortalList.push_back(p2); } } else if (pRadius < p2->getRadius()) { // Portal #2 is bigger than Portal #1, check for crossing if (p->getCurrentHomeZone() != p2->getTargetZone() && p->crossedPortal(p2)) { // portal#1 crossed portal#2 - flag portal#1 to be moved to portal#2's target zone p->setNewHomeZone(p2->getTargetZone()); transferPortalList.push_back(p); continue; } } } // Secondly we check againts the antiportals of this zone. for (AntiPortalList::iterator ait = mAntiPortals.begin(); ait != mAntiPortals.end(); ++ait) { AntiPortal* ap = (*ait); // Skip portal if it doesn't need updating. // If both portals are not moving, then there's no need to check between them. if (!portalNeedUpdate && !ap->needUpdate()) continue; // only check for crossing if AntiPortal smaller than portal. if (pRadius > ap->getRadius()) { // Portal#1 is bigger than AntiPortal, check for crossing if (ap->crossedPortal(p)) { // AntiPortal crossed Portal#1 - flag AntiPortal to be moved to Portal#1's target zone ap->setNewHomeZone(p->getTargetZone()); transferAntiPortalList.push_back(ap); } } } // Skip portal if it doesn't need updating. if (!portalNeedUpdate) continue; // Thirdly we check against portals in the target zone (and only if that target // zone is different from the home zone) PCZone * tzone = p->getTargetZone(); if (tzone != this) { for ( PortalList::iterator it3 = tzone->mPortals.begin(); it3 != tzone->mPortals.end(); ++it3 ) { Portal * p3 = (*it3); // only check against bigger regular portals if (pRadius < p3->getRadius()) { // Portal#3 is bigger than Portal#1, check for crossing if (p->getCurrentHomeZone() != p3->getTargetZone() && p->crossedPortal(p3)) { // Portal#1 crossed Portal#3 - switch target zones for Portal#1 p->setTargetZone(p3->getTargetZone()); break; } } } } } // transfer any portals to new zones that have been flagged for ( PortalList::iterator it = transferPortalList.begin(); it != transferPortalList.end(); ++it ) { Portal * p = *it; if (p->getNewHomeZone() != 0) { _removePortal(p); p->getNewHomeZone()->_addPortal(p); p->setNewHomeZone(0); } } // transfer any anti portals to new zones that have been flagged for (AntiPortalList::iterator it = transferAntiPortalList.begin(); it != transferAntiPortalList.end(); ++it) { AntiPortal* p = *it; if (p->getNewHomeZone() != 0) { _removeAntiPortal(p); p->getNewHomeZone()->_addAntiPortal(p); p->setNewHomeZone(0); } } }