bool MWMechanics::AiPackage::isReachableRotatingOnTheRun(const MWWorld::Ptr& actor, const ESM::Pathgrid::Point& dest) { // get actor's shortest radius for moving in circle float speed = actor.getClass().getSpeed(actor); speed += speed * 0.1f; // 10% real speed inaccuracy float radius = speed / MAX_VEL_ANGULAR_RADIANS; // get radius direction to the center const float* rot = actor.getRefData().getPosition().rot; osg::Quat quatRot(rot[0], -osg::X_AXIS, rot[1], -osg::Y_AXIS, rot[2], -osg::Z_AXIS); osg::Vec3f dir = quatRot * osg::Y_AXIS; // actor's orientation direction is a tangent to circle osg::Vec3f radiusDir = dir ^ osg::Z_AXIS; // radius is perpendicular to a tangent radiusDir.normalize(); radiusDir *= radius; // pick up the nearest center candidate osg::Vec3f dest_ = PathFinder::MakeOsgVec3(dest); osg::Vec3f pos = actor.getRefData().getPosition().asVec3(); osg::Vec3f center1 = pos - radiusDir; osg::Vec3f center2 = pos + radiusDir; osg::Vec3f center = (center1 - dest_).length2() < (center2 - dest_).length2() ? center1 : center2; float distToDest = (center - dest_).length(); // if pathpoint is reachable for the actor rotating on the run: // no points of actor's circle should be farther from the center than destination point return (radius <= distToDest); }
//! renders the node. void CSkyDomeSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); scene::ICameraSceneNode* camera = SceneManager->getActiveCamera(); if (!camera || !driver) return; if ( !camera->isOrthogonal() ) { core::matrix4 mat(AbsoluteTransformation); mat.setTranslation(camera->getAbsolutePosition()); driver->setTransform(video::ETS_WORLD, mat); driver->setMaterial(Buffer->Material); driver->drawMeshBuffer(Buffer); } // for debug purposes only: if ( DebugDataVisible ) { video::SMaterial m; m.Lighting = false; driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_NORMALS ) { IAnimatedMesh * arrow = SceneManager->addArrowMesh ( "__debugnormal2", 0xFFECEC00, 0xFF999900, 4, 8, 1.f * 40.f, 0.6f * 40.f, 0.05f * 40.f, 0.3f * 40.f); if ( 0 == arrow ) { arrow = SceneManager->getMesh ( "__debugnormal2" ); } IMesh *mesh = arrow->getMesh(0); // find a good scaling factor core::matrix4 m2; // draw normals const scene::IMeshBuffer* mb = Buffer; const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); for ( u32 i=0; i != mb->getVertexCount(); ++i ) { // align to v->Normal core::quaternion quatRot(v->Normal.X, 0.f, -v->Normal.X, 1+v->Normal.Y); quatRot.normalize(); quatRot.getMatrix(m2, v->Pos); m2 = AbsoluteTransformation * m2; driver->setTransform(video::ETS_WORLD, m2); for (u32 a = 0; a != mesh->getMeshBufferCount(); ++a) driver->drawMeshBuffer(mesh->getMeshBuffer(a)); v = (const video::S3DVertex*) ( (u8*) v + vSize ); } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); } // show mesh if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) { m.Wireframe = true; driver->setMaterial(m); driver->drawMeshBuffer(Buffer); } } }
//! renders the node. void CMeshSceneNode::render() { video::IVideoDriver* driver = SceneManager->getVideoDriver(); if (!Mesh || !driver) return; bool isTransparentPass = SceneManager->getSceneNodeRenderPass() == scene::ESNRP_TRANSPARENT; ++PassCount; driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); Box = Mesh->getBoundingBox(); // for debug purposes only: bool renderMeshes = true; video::SMaterial mat; if (DebugDataVisible && PassCount==1) { // overwrite half transparency if ( DebugDataVisible & scene::EDS_HALF_TRANSPARENCY ) { for (u32 g=0; g<Mesh->getMeshBufferCount(); ++g) { mat = Materials[g]; mat.MaterialType = video::EMT_TRANSPARENT_ADD_COLOR; driver->setMaterial(mat); driver->drawMeshBuffer(Mesh->getMeshBuffer(g)); } renderMeshes = false; } } // render original meshes if ( renderMeshes ) { for (u32 i=0; i<Mesh->getMeshBufferCount(); ++i) { scene::IMeshBuffer* mb = Mesh->getMeshBuffer(i); if (mb) { const video::SMaterial& material = ReadOnlyMaterials ? mb->getMaterial() : Materials[i]; video::IMaterialRenderer* rnd = driver->getMaterialRenderer(material.MaterialType); bool transparent = (rnd && rnd->isTransparent()); // only render transparent buffer if this is the transparent render pass // and solid only in solid pass if (transparent == isTransparentPass) { driver->setMaterial(material); driver->drawMeshBuffer(mb); } } } } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); // for debug purposes only: if ( DebugDataVisible && PassCount==1) { video::SMaterial m; m.Lighting = false; driver->setMaterial(m); if ( DebugDataVisible & scene::EDS_BBOX ) { driver->draw3DBox(Box, video::SColor(255,255,255,255)); } if ( DebugDataVisible & scene::EDS_BBOX_BUFFERS ) { for (u32 g=0; g<Mesh->getMeshBufferCount(); ++g) { driver->draw3DBox( Mesh->getMeshBuffer(g)->getBoundingBox(), video::SColor(255,190,128,128)); } } if ( DebugDataVisible & scene::EDS_NORMALS ) { IAnimatedMesh * arrow = SceneManager->addArrowMesh ( "__debugnormal", 0xFFECEC00, 0xFF999900, 4, 8, 1.f, 0.6f, 0.05f, 0.3f); if ( 0 == arrow ) { arrow = SceneManager->getMesh ( "__debugnormal" ); } IMesh *mesh = arrow->getMesh(0); // find a good scaling factor core::matrix4 m2; // draw normals for (u32 g=0; g<Mesh->getMeshBufferCount(); ++g) { const scene::IMeshBuffer* mb = Mesh->getMeshBuffer(g); const u32 vSize = video::getVertexPitchFromType(mb->getVertexType()); const video::S3DVertex* v = ( const video::S3DVertex*)mb->getVertices(); for ( u32 i=0; i != mb->getVertexCount(); ++i ) { // align to v->Normal core::quaternion quatRot(v->Normal.X, 0.f, -v->Normal.X, 1+v->Normal.Y); quatRot.normalize(); quatRot.getMatrix(m2); m2.setTranslation(v->Pos); m2*=AbsoluteTransformation; driver->setTransform(video::ETS_WORLD, m2); for (u32 a = 0; a != mesh->getMeshBufferCount(); ++a) driver->drawMeshBuffer(mesh->getMeshBuffer(a)); v = (const video::S3DVertex*) ( (u8*) v + vSize ); } } driver->setTransform(video::ETS_WORLD, AbsoluteTransformation); } // show mesh if ( DebugDataVisible & scene::EDS_MESH_WIRE_OVERLAY ) { m.Wireframe = true; driver->setMaterial(m); for (u32 g=0; g<Mesh->getMeshBufferCount(); ++g) { driver->drawMeshBuffer( Mesh->getMeshBuffer(g) ); } } } }
/* angle = dotproduct ( v(0,1,0), up ) axis = crossproduct ( v(0,1,0), up ) */ inline void AlignToUpVector(irr::core::matrix4 &m, const irr::core::vector3df &up ) { core::quaternion quatRot( up.Z, 0.f, -up.X, 1 + up.Y ); quatRot.normalize(); quatRot.getMatrix ( m ); }