float3x4 EC_Mesh::LocalToWorld() const { if (!entity_) { LogError("EC_Mesh::LocalToParent failed! No entity exists in this mesh!"); return float3x4::identity; } Ogre::SceneNode *node = entity_->getParentSceneNode(); if (!node) { LogError("EC_Mesh::LocalToParent failed! Ogre::Entity is not attached to a Ogre::SceneNode!"); return float3x4::identity; } return float3x4::FromTRS(node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale()); }
float3x4 EC_Mesh::LocalToWorld() const { if (!entity_) { LogError(QString("EC_Mesh::LocalToWorld failed! No entity exists in mesh \"%1\" (entity: \"%2\")!").arg(meshRef.Get().ref).arg(ParentEntity() ? ParentEntity()->Name() : "(EC_Mesh with no parent entity)")); return float3x4::identity; } Ogre::SceneNode *node = entity_->getParentSceneNode(); if (!node) { LogError(QString("EC_Mesh::LocalToWorld failed! Ogre::Entity is not attached to a Ogre::SceneNode! Mesh \"%1\" (entity: \"%2\")!").arg(meshRef.Get().ref).arg(ParentEntity() ? ParentEntity()->Name() : "(EC_Mesh with no parent entity)")); return float3x4::identity; } assume(!float3(node->_getDerivedScale()).IsZero()); float3x4 tm = float3x4::FromTRS(node->_getDerivedPosition(), node->_getDerivedOrientation(), node->_getDerivedScale()); assume(tm.IsColOrthogonal()); return tm; }
void RenderingManager::update (float duration, bool paused) { if (MWBase::Environment::get().getStateManager()->getState()== MWBase::StateManager::State_NoGame) return; MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayerPtr(); int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude(); MWBase::Environment::get().getWindowManager()->setScreenFactor(std::max(0.f, 1.f-(blind / 100.f))); setAmbientMode(); // player position MWWorld::RefData &data = player.getRefData(); Ogre::Vector3 playerPos(data.getPosition().pos); mCamera->setCameraDistance(); if(!mCamera->isFirstPerson()) { Ogre::Vector3 orig, dest; mCamera->getPosition(orig, dest); btVector3 btOrig(orig.x, orig.y, orig.z); btVector3 btDest(dest.x, dest.y, dest.z); std::pair<bool,float> test = mPhysicsEngine->sphereCast(mRendering.getCamera()->getNearClipDistance()*2.5, btOrig, btDest); if(test.first) mCamera->setCameraDistance(test.second * orig.distance(dest), false, false); } // Sink the camera while sneaking bool isSneaking = player.getClass().getCreatureStats(player).getStance(MWMechanics::CreatureStats::Stance_Sneak); bool isInAir = !world->isOnGround(player); bool isSwimming = world->isSwimming(player); static const int i1stPersonSneakDelta = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>() .find("i1stPersonSneakDelta")->getInt(); if(!paused && isSneaking && !(isSwimming || isInAir)) mCamera->setSneakOffset(i1stPersonSneakDelta); mOcclusionQuery->update(duration); mRendering.update(duration); Ogre::ControllerManager::getSingleton().setTimeFactor(paused ? 0.f : 1.f); Ogre::Vector3 cam = mRendering.getCamera()->getRealPosition(); applyFog(world->isUnderwater(player.getCell(), cam)); mCamera->update(duration, paused); Ogre::SceneNode *node = data.getBaseNode(); Ogre::Quaternion orient = node->_getDerivedOrientation(); mLocalMap->updatePlayer(playerPos, orient); if(paused) return; mEffectManager->update(duration, mRendering.getCamera()); mActors->update (mRendering.getCamera()); mPlayerAnimation->preRender(mRendering.getCamera()); mObjects->update (duration, mRendering.getCamera()); mSkyManager->update(duration); mSkyManager->setGlare(mOcclusionQuery->getSunVisibility()); mWater->updateUnderwater(world->isUnderwater(player.getCell(), cam)); mWater->update(duration, playerPos); }
void RenderingManager::update (float duration, bool paused) { MWBase::World *world = MWBase::Environment::get().getWorld(); MWWorld::Ptr player = world->getPlayer().getPlayer(); int blind = MWWorld::Class::get(player).getCreatureStats(player).getMagicEffects().get(MWMechanics::EffectKey(ESM::MagicEffect::Blind)).mMagnitude; mRendering.getFader()->setFactor(std::max(0.f, 1.f-(blind / 100.f))); setAmbientMode(); // player position MWWorld::RefData &data = player.getRefData(); Ogre::Vector3 playerPos(data.getPosition().pos); mCamera->setCameraDistance(); if(!mCamera->isFirstPerson()) { Ogre::Vector3 orig, dest; mCamera->getPosition(orig, dest); btVector3 btOrig(orig.x, orig.y, orig.z); btVector3 btDest(dest.x, dest.y, dest.z); std::pair<bool,float> test = mPhysicsEngine->sphereCast(mRendering.getCamera()->getNearClipDistance()*2.5, btOrig, btDest); if(test.first) mCamera->setCameraDistance(test.second * orig.distance(dest), false, false); } mOcclusionQuery->update(duration); mVideoPlayer->update (); mRendering.update(duration); Ogre::ControllerManager::getSingleton().setTimeFactor(paused ? 0.f : 1.f); Ogre::Vector3 cam = mRendering.getCamera()->getRealPosition(); applyFog(world->isUnderwater(player.getCell(), cam)); mCamera->update(duration, paused); if(paused) return; mActors.update (duration); mObjects.update (duration); mSkyManager->update(duration); mSkyManager->setGlare(mOcclusionQuery->getSunVisibility()); Ogre::SceneNode *node = data.getBaseNode(); Ogre::Quaternion orient = node->_getDerivedOrientation(); mLocalMap->updatePlayer(playerPos, orient); mWater->updateUnderwater(world->isUnderwater(player.getCell(), cam)); mWater->update(duration, playerPos); }
void Renderer::FindClosestPolygon(Ogre::Entity* entity, float& closestDistance, Ogre::Vector3& position, Ogre::Vector3& normal) { closestDistance = std::numeric_limits<float>::max(); // default value (means // nothing detected) // Get transformation Ogre::SceneNode* parentNode = entity->getParentSceneNode(); Ogre::Vector3 parentPos; Ogre::Quaternion parentOrientation; Ogre::Vector3 parentScale; if (parentNode) { parentPos = parentNode->_getDerivedPosition(); parentOrientation = parentNode->_getDerivedOrientation(); parentScale = parentNode->_getDerivedScale(); } else { parentPos = Ogre::Vector3::ZERO; parentOrientation = Ogre::Quaternion::IDENTITY; parentScale = Ogre::Vector3::UNIT_SCALE; } // Handle animated entities bool isAnimated = entity->hasSkeleton(); if (isAnimated) { entity->addSoftwareAnimationRequest(false); entity->_updateAnimation(); } // Loop through each submesh Ogre::MeshPtr mesh = entity->getMesh(); for (uint i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* subMesh = mesh->getSubMesh(i); // Ignore anything that isn't a triangle List if (subMesh->operationType != Ogre::RenderOperation::OT_TRIANGLE_LIST) continue; // Get the vertex data Ogre::VertexData* vertexData; if (subMesh->useSharedVertices) { if (isAnimated) vertexData = entity->_getSkelAnimVertexData(); else vertexData = mesh->sharedVertexData; } else { if (isAnimated) vertexData = entity->getSubEntity(i)->_getSkelAnimVertexData(); else vertexData = subMesh->vertexData; } // Get the size of one vertex const Ogre::VertexElement* posEl = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vBuff = vertexData->vertexBufferBinding->getBuffer(posEl->getSource()); uint vertexSize = vBuff->getVertexSize(); // Save pointer to first vertex short* pVertex = (short*)vBuff->lock(Ogre::HardwareBuffer::HBL_READ_ONLY); short* pStartVertex = pVertex; // Get the index buffer // If it is null then skip as it must be a point cloud Ogre::HardwareIndexBufferSharedPtr iBuff = subMesh->indexData->indexBuffer; if (iBuff.isNull()) continue; uint* pLong = (uint*)iBuff->lock(Ogre::HardwareBuffer::HBL_READ_ONLY); uint16_t* pShort = (uint16_t*)pLong; // Look through each vertex and check each triangle with the ray Ogre::Vector3 vertexPos; Ogre::Vector3 vertex1; Ogre::Vector3 vertex2; float* pReal; uint index; for (uint k = 0; k < subMesh->indexData->indexCount; k++) { // Read index value if (iBuff->getType() == Ogre::HardwareIndexBuffer::IT_32BIT) // if 32bit indexes { index = (uint)pLong[k]; } else { index = (uint)pShort[k]; } // Read referenced vertex pVertex = pStartVertex + (vertexSize * index); // calculate pointer posEl->baseVertexPointerToElement(pVertex, &pReal); // read vertex vertexPos = Ogre::Vector3(pReal[0], pReal[1], pReal[2]); // read position values // Apply world transformations if (parentNode) vertexPos = (parentOrientation * (vertexPos * parentScale)) + parentPos; // Figure out triangle and calculate the distance if it's the closest switch (k % 3) { case 0: vertex1 = vertexPos; break; case 1: vertex2 = vertexPos; break; case 2: RayToTriangleCheck(vertex1, vertex2, vertexPos, closestDistance, position, normal); break; default: break; } } iBuff->unlock(); vBuff->unlock(); } if (isAnimated) { entity->removeSoftwareAnimationRequest(false); } }
void CsCameraManager::Update() { static clock_t prevTime = clock(); static Ogre::Vector3 lerpPos; static Ogre::Quaternion slerpRot; static float linLerpStep; static float angLerpStep; clock_t curTime = clock(); float timeStep = (curTime - prevTime) / (float) CLOCKS_PER_SEC; Ogre::SceneNode* camNode = mCameraList[mCurrentCamera].second; // the interpolation ---------------------------------------- // the current camera is not actually used, the default camera is used to approximate // the current camera posA = mDefaultCamNode->_getDerivedPosition(); rotA = mDefaultCamNode->_getDerivedOrientation(); posB = camNode->_getDerivedPosition(); rotB = camNode->_getDerivedOrientation(); linLerpStep = 0.5 * timeStep / 0.12; // reaches half i 0.3 seconds angLerpStep = 0.5 * timeStep / 0.12; // for fast moving targets if (mTargetObject) { float linear = mTargetObject->GetLinearVelocity().length(); float angular = mTargetObject->GetAngularVelocity().length(); if (linear > 200.0f) { linLerpStep += (linear - 150) / 300.0f; angLerpStep += (linear - 150) / 300.0f; } if (angular > 3.0f) { linLerpStep += (angular - 2.0f) / 8.0f; angLerpStep += (angular - 2.0f) / 8.0f; } } if (linLerpStep > 1.0f) linLerpStep = 0.90f; if (angLerpStep > 1.0f) angLerpStep = 0.90f; if (linLerpStep < 0.0f) linLerpStep = 0.1f; if (angLerpStep < 0.0f) angLerpStep = 0.1f; lerpPos = (posB - posA) * linLerpStep + posA; slerpRot = Ogre::Quaternion::Slerp(angLerpStep, rotA, rotB, true); mDefaultCamNode->setPosition(lerpPos); mDefaultCamNode->setOrientation(slerpRot); // ---------------------------------------------------------- if (mCameraType[mCurrentCamera] == Chaos::ORBIT_CAMERA) { Orbit(timeStep); } else if (mCameraType[mCurrentCamera] == Chaos::FREE_CAMERA) { if ( mButtonState[Chaos::ARROW_UP]) camNode->translate(0,0,-timeStep * MOVE_SPEED, Ogre::Node::TS_LOCAL); if ( mButtonState[Chaos::ARROW_DOWN]) camNode->translate(0,0,timeStep * MOVE_SPEED, Ogre::Node::TS_LOCAL); if ( mButtonState[Chaos::ARROW_LEFT]) camNode->translate(-timeStep * MOVE_SPEED,0,0, Ogre::Node::TS_LOCAL); if ( mButtonState[Chaos::ARROW_RIGHT]) camNode->translate(timeStep * MOVE_SPEED,0,0, Ogre::Node::TS_LOCAL); if (xrel) camNode->yaw(Ogre::Radian(Ogre::Degree(-LOOK_SPEED * xrel * timeStep)), Ogre::Node::TS_WORLD); if (yrel) camNode->pitch(Ogre::Radian(Ogre::Degree(-LOOK_SPEED * yrel * timeStep)), Ogre::Node::TS_LOCAL); } xrel = yrel = zrel = 0; prevTime = curTime; }
void Objects::insertMesh (const MWWorld::Ptr& ptr, const std::string& mesh) { Ogre::SceneNode* insert = ptr.getRefData().getBaseNode(); assert(insert); Ogre::AxisAlignedBox bounds = Ogre::AxisAlignedBox::BOX_NULL; NifOgre::EntityList entities = NifOgre::NIFLoader::createEntities(insert, NULL, mesh); for(size_t i = 0;i < entities.mEntities.size();i++) { const Ogre::AxisAlignedBox &tmp = entities.mEntities[i]->getBoundingBox(); bounds.merge(Ogre::AxisAlignedBox(insert->_getDerivedPosition() + tmp.getMinimum(), insert->_getDerivedPosition() + tmp.getMaximum()) ); } Ogre::Vector3 extents = bounds.getSize(); extents *= insert->getScale(); float size = std::max(std::max(extents.x, extents.y), extents.z); bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && Settings::Manager::getBool("limit small object distance", "Viewing distance"); // do not fade out doors. that will cause holes and look stupid if (ptr.getTypeName().find("Door") != std::string::npos) small = false; if (mBounds.find(ptr.getCell()) == mBounds.end()) mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; mBounds[ptr.getCell()].merge(bounds); bool transparent = false; for(size_t i = 0;i < entities.mEntities.size();i++) { Ogre::Entity *ent = entities.mEntities[i]; for (unsigned int i=0; i<ent->getNumSubEntities(); ++i) { Ogre::MaterialPtr mat = ent->getSubEntity(i)->getMaterial(); Ogre::Material::TechniqueIterator techIt = mat->getTechniqueIterator(); while (techIt.hasMoreElements()) { Ogre::Technique* tech = techIt.getNext(); Ogre::Technique::PassIterator passIt = tech->getPassIterator(); while (passIt.hasMoreElements()) { Ogre::Pass* pass = passIt.getNext(); if (pass->getDepthWriteEnabled() == false) transparent = true; } } } } if(!mIsStatic || !Settings::Manager::getBool("use static geometry", "Objects") || transparent) { for(size_t i = 0;i < entities.mEntities.size();i++) { Ogre::Entity *ent = entities.mEntities[i]; ent->setRenderingDistance(small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0); ent->setVisibilityFlags(mIsStatic ? (small ? RV_StaticsSmall : RV_Statics) : RV_Misc); ent->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); } } else { Ogre::StaticGeometry* sg = 0; if (small) { if( mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end()) { uniqueID = uniqueID +1; sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); mStaticGeometrySmall[ptr.getCell()] = sg; sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance")); } else sg = mStaticGeometrySmall[ptr.getCell()]; } else { if( mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end()) { uniqueID = uniqueID +1; sg = mRenderer.getScene()->createStaticGeometry( "sg" + Ogre::StringConverter::toString(uniqueID)); mStaticGeometry[ptr.getCell()] = sg; } else sg = mStaticGeometry[ptr.getCell()]; } // This specifies the size of a single batch region. // If it is set too high: // - there will be problems choosing the correct lights // - the culling will be more inefficient // If it is set too low: // - there will be too many batches. sg->setRegionDimensions(Ogre::Vector3(2500,2500,2500)); sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics); sg->setCastShadows(true); sg->setRenderQueueGroup(transparent ? RQG_Alpha : RQG_Main); for(size_t i = 0;i < entities.mEntities.size();i++) { Ogre::Entity *ent = entities.mEntities[i]; insert->detachObject(ent); sg->addEntity(ent,insert->_getDerivedPosition(),insert->_getDerivedOrientation(),insert->_getDerivedScale()); mRenderer.getScene()->destroyEntity(ent); } } }