/// get the triangle selector for this scene node, creating it if needed
 ITriangleSelector_IPtr SceneObject::GetTriangleSelector()
 {
     ITriangleSelector_IPtr tri_selector = mSceneNode->getTriangleSelector();
     if (tri_selector) {
         return tri_selector;
     } else {
         // create triangle selector
         if (mTerrSceneNode)
         {
             tri_selector = GetSceneManager()->createTerrainTriangleSelector(mTerrSceneNode.get());
             AssertMsg(tri_selector, "Could not create a collision object for id: " << GetId());
             mTerrSceneNode->setTriangleSelector(tri_selector.get());
             LOG_F_DEBUG("collision", "created terrain triangle selector for id: " << GetId());
         }
         else if (mAniSceneNode)
         {
             IMesh* mesh = mAniSceneNode->getMesh();
             tri_selector = GetSceneManager()->createTriangleSelector(mesh, mAniSceneNode.get());
             AssertMsg(tri_selector, "Could not create a collision object for id: " << GetId());
             mAniSceneNode->setTriangleSelector(tri_selector.get());
             LOG_F_DEBUG("collision", "creating mesh triangle selector for id: " << GetId());
         }
         else
         {
             tri_selector = GetSceneManager()->createTriangleSelectorFromBoundingBox(mSceneNode.get());
             AssertMsg(tri_selector, "Could not create a collision object for id: " << GetId());
             mSceneNode->setTriangleSelector(tri_selector.get());
             LOG_F_DEBUG("collision", "creating bounding box triangle selector for id: " << GetId());
         }
         return tri_selector;
     }
 }
    /**
     * Add an entity to the simulation and assign it the required id. If we cannot assign
     * that id (ie: it is already taken) we should fail.
     * @param ent entity to add
     * @return true if add was successful and ids didnt not conflict
    */
    void Simulation::AddSimEntity( SimEntityPtr ent )
    {
        AssertMsg( ent, "Adding a null entity to the simulation!" );
        AssertMsg( !Find( ent->GetSimId() ), "Entity with id " << ent->GetSimId() << " already exists in the simulation" );
        mSimIdHashedEntities[ ent->GetSimId() ] = ent;
        mEntities.insert(ent);
        mEntitiesAdded.push_back(ent);
        uint32_t ent_type = ent->GetType();
        for (size_t i = 0; i < sizeof(uint32_t); ++i) {
            uint32_t t = 1 << i;
            if (t > ent_type) break; // shortcut
            if (ent_type & t) {
                mEntityTypes[t].insert(ent);
            }
        }

        { // also make sure to add the triangle selector for this object to 
          // all relevant meta selectors
            hash_map<uint32_t, IMetaTriangleSelector_IPtr>::iterator iter;
            for (iter = mCollisionSelectors.begin(); iter != mCollisionSelectors.end(); ++iter) {
                // if the entity type matches the stored mask
                if (iter->first & ent_type) {
                    // add the triangles to that selector
                    ITriangleSelector_IPtr tri_selector = ent->GetSceneObject()->GetTriangleSelector();
                    iter->second->addTriangleSelector(tri_selector.get());
                    LOG_F_DEBUG("collision", "added " << tri_selector->getTriangleCount() << " triangles for a total of " << iter->second->getTriangleCount() << " triangles that collide with type " << iter->first);
                }
            }
        }
        
        GetCollisionTriangleSelector(ent_type);
        AssertMsg( Find(ent->GetSimId()) == ent, "The entity with id " << ent->GetSimId() << " could not be properly added" );
    }
 /// get a triangle selector for all the objects matching the types mask
 IMetaTriangleSelector_IPtr Simulation::GetCollisionTriangleSelector( size_t types )
 {
     IMetaTriangleSelector_IPtr meta_selector;
     
     // first, lookup the type mask in our table
     hash_map<uint32_t, IMetaTriangleSelector_IPtr>::const_iterator needle;
     needle = mCollisionSelectors.find(types);
     
     if (needle != mCollisionSelectors.end()) {
         // if found, return the selector
         meta_selector = needle->second;
     } else {
         // if not found, create the selector
         meta_selector = mIrr.getSceneManager()->createMetaTriangleSelector();
         SimEntitySet ents = GetEntities(types);
         // iterate over all entities of that type and add them to the selector
         for (SimEntitySet::const_iterator iter = ents.begin(); iter != ents.end(); ++iter)
         {
             SimEntityPtr ent = *iter;
             ITriangleSelector_IPtr tri_selector = ent->GetSceneObject()->GetTriangleSelector();
             meta_selector->addTriangleSelector(tri_selector.get());
         }
         // remember for future reuse
         mCollisionSelectors[types] = meta_selector;
         LOG_F_DEBUG("collision", "created triangle selector for mask " 
             << types << " with: " << meta_selector->getTriangleCount() << " triangles");        
     }
     
     return meta_selector;
 }
 /// make sure that the new position assigned to this object
 /// actually gets assigned (disregard collisions for one step)
 void SceneObject::DisregardCollisions()
 {
     if (mCollider) {
         SetPosition(mSharedData->GetPosition());
         mCollider->setTargetNode(mSceneNode.get());
         LOG_F_DEBUG("collision", "teleport object id: " << GetId());
     }
 }
 /// @param x screen x-coordinate for active camera
 /// @param y screen y-coordinate for active camera
 /// @return Approximate 3d position of the click
 Vector3f SimContext::GetClickedPosition(const int32_t& x, const int32_t& y)
 {
     Pos2i pos(x,y);
     ISceneCollisionManager* collider = mIrr.getSceneManager()->getSceneCollisionManager();
     // get ray
     Line3f ray = collider->getRayFromScreenCoordinates(pos);
     LOG_F_DEBUG("collision", "screen coordinates: " << pos << ", ray: " << ray.start << " - " << ray.end << ", length: " << ray.getLength());
     Vector3f collision_point;
     Triangle3f collision_triangle;
     ISceneNode* collision = collider->getSceneNodeAndCollisionPointFromRay(ray, collision_point, collision_triangle);
     if (collision) {
         SimEntityPtr ent = mpSimulation->FindBySceneObjectId(collision->getID());
         LOG_F_DEBUG("collision", "screen coordinates: " << pos << " colliding with: " << ent << " at: " << collision_point);
         return ConvertIrrlichtToNeroPosition(collision_point);
     } else {
         LOG_F_WARNING("collision", "screen coordinates: " << pos << " did not collide with any geometry!");
         return ConvertIrrlichtToNeroPosition(ray.end);
     }
 }
Exemple #6
0
 void Camera::snapshot(const std::string& filename)
 {        
     LOG_F_DEBUG("render", "Taking snapshot!");
     IImage* img = mIrr.mpVideoDriver->createScreenShot();
     if(!img)
         LOG_F_ERROR("render", "Snapshot mage is null!");
     else {
         if (!mIrr.mpVideoDriver->writeImageToFile(img, filename.c_str()))
             LOG_F_ERROR("render", "Could not write snapshot image!");
         img->drop();
     }
 }
 void AIManager::Log(SimId id, 
                     size_t episode, 
                     size_t step, 
                     Reward reward, 
                     Reward fitness)
 {
     //stringstream ss;
     //GetStaticTimer().stamp(ss);
     //ss << " (M) [ai.tick] " << id <<
     //    "\t" << episode <<
     //    "\t" << step <<
     //    "\t" << reward <<
     //    "\t" << fitness << endl;
     //ScriptingEngine::instance().NetworkWrite(ss.str());
     LOG_F_DEBUG("ai.tick", id <<
         "\t" << episode <<
         "\t" << step <<
         "\t" << reward <<
         "\t" << fitness);
 }
    /**
     * Load this object from a template
     * @param objTemplate template to load from
     * @return true if success
     */
    bool SceneObject::LoadFromTemplate( ObjectTemplatePtr objTemplate, const SimEntityData& data )
    {
        if( !objTemplate )
            return false;

        Assert( objTemplate->mpSimFactory );

        // cast to object template to the type we expect
        mSceneObjectTemplate = static_pointer_cast< SceneObjectTemplate, ObjectTemplate>( objTemplate );

        IrrFactory& irrFactory = mSceneObjectTemplate->mpSimFactory->getIrrFactory();

        // are we an animated mesh?
        if( mSceneObjectTemplate->mAniMesh )
        {
            mAniSceneNode = irrFactory.addAnimatedMeshSceneNode( mSceneObjectTemplate->mAniMesh.get() );
            if (mSceneObjectTemplate->mCastsShadow)
            {
                mAniSceneNode->addShadowVolumeSceneNode();
            }
            mFPSCamera = mSceneObjectTemplate->mFPSCamera; // reminder to attach camera later

			mAniSceneNode->setAnimationSpeed(0);
            mStartFrame = mAniSceneNode->getStartFrame();
            mEndFrame = mAniSceneNode->getEndFrame();
            mAniSceneNode->setFrameLoop(0,0);
            mAniSceneNode->setCurrentFrame(0);

			mSceneNode = mAniSceneNode;
        }

        // are we a terrain?
        else if( mSceneObjectTemplate->mHeightmap != "" )
        {
            mTerrSceneNode = irrFactory.addTerrainSceneNode( mSceneObjectTemplate->mHeightmap.c_str() );
            mSceneNode     = mTerrSceneNode;
            mTerrSceneNode->scaleTexture( mSceneObjectTemplate->mScaleTexture.X, mSceneObjectTemplate->mScaleTexture.Y );
        }

        // are we a particle system?
        else if( mSceneObjectTemplate->mParticleSystem != "" )
        {
            mParticleSystemNode = irrFactory.addParticleSystemNode( mSceneObjectTemplate->mParticleSystem );
            mSceneNode          = mParticleSystemNode;
            // don't add a triangle selector for a particle node
        }

        if( mSceneNode )
        {
            // assign the textures
            for( uint32_t i = 0; i < (uint32_t)mSceneObjectTemplate->mTextures.size(); ++i )
                mSceneNode->setMaterialTexture( i, mSceneObjectTemplate->mTextures[i].get() );

            // set the material flags
            std::vector<IrrMaterialFlag>::const_iterator flagItr = mSceneObjectTemplate->mMaterialFlags.begin();
            std::vector<IrrMaterialFlag>::const_iterator flagEnd = mSceneObjectTemplate->mMaterialFlags.end();
            for( ; flagItr != flagEnd; ++flagItr )
                mSceneNode->setMaterialFlag( flagItr->mFlag, flagItr->mValue );

            // set the material type
            mSceneNode->setMaterialType( mSceneObjectTemplate->mMaterialType );

            // set the node scale
            Vector3f scale = mSceneObjectTemplate->mScale;
            /// we can optionally multiply by a custom scale
            scale.X = scale.X * data.GetScale().X;
            scale.Y = scale.Y * data.GetScale().Y;
            scale.Z = scale.Z * data.GetScale().Z;
            mSceneNode->setScale( ConvertNeroToIrrlichtPosition(scale) );

            // make the id of the scene node the same as the SimId of our object
            mSceneNode->setID(ConvertSimIdToSceneId(data.GetId(), data.GetType()));

            // set the position of the object
            SetPosition( data.GetPosition() );

            // set the rotation of the object
            SetRotation( data.GetRotation() );

            // set up the triangle selector for this object
            //if (data.GetType() > 0) {
            {
                ITriangleSelector_IPtr tri_selector = GetTriangleSelector();
                if (!tri_selector) {
                    LOG_F_WARNING("collision", "could not create triangle selector for collisions with object " << GetId());
                }
            }
            //}

            // additionally, add a collision response animator
            if (canCollide()) {
                // the world will return the triangles that match the type mask
                ITriangleSelector* world = new CollideByTypeTriangleSelector(mSceneObjectTemplate->mCollisionMask);
                // get the axis-aligned bounding box for the node
                BBoxf box = mSceneNode->getBoundingBox();
                // use the aabbox to make the ellipsoid for the collision response animator
                Vector3f ellipsoid_radius = box.MaxEdge - box.getCenter();
                // TODO: might add gravity here
                Vector3f gravity(0,0,0);
                // ellipsoid translation relative to object coordinates
                Vector3f ellipsoid_translation(0,0,0);
                mCollider = GetSceneManager()->createCollisionResponseAnimator(
                    world, mSceneNode.get(), ellipsoid_radius, gravity, ellipsoid_translation);
                if (!mCollider) {
                    LOG_F_ERROR("collision", "could not create Collision Response Animator for object id: " << data.GetId());
                } else {
                    SafeIrrDrop(world); // we don't need the handle
                    mSceneNode->addAnimator(mCollider.get());
                    LOG_F_DEBUG("collision",
                        "added collision response animator for object id: "
                        << data.GetId() << " of type: " << data.GetType()
                        << " for collision with mask: " << mSceneObjectTemplate->mCollisionMask
                        << " with bounding ellipsoid: " << ellipsoid_radius);
                }
            }

#if SCENEOBJECT_ENABLE_STATS
            // debug information
            if( mTerrSceneNode )
            {
                const aabbox3df& bbox = mTerrSceneNode->getBoundingBox();

                vector3df  dim  = bbox.MaxEdge - bbox.MinEdge;

                float32_t vol = dim.X * dim.Y * dim.Z;
                vol = (vol<0) ? -vol : vol;

                LOG_F_MSG( "render", "Added terrain with heightmap: " << mSceneObjectTemplate->mHeightmap );
                LOG_F_MSG( "render", "   Dim: (" << dim.X << ", " << dim.Y << ", " << dim.Z << ")" );
                LOG_F_MSG( "render", "   Volume: " << vol );
            }
#endif // end SCENEOBJECT_ENABLE_STATS
        }

        return true;
    }
    /// constructor
    SceneObjectTemplate::SceneObjectTemplate( SimFactoryPtr factory, const PropertyMap& propMap ) :
    ObjectTemplate( factory, propMap ),
    mScaleTexture(1,1),
    mTextures(),
    mMaterialFlags(),
    mMaterialType( EMT_SOLID ),
    mHeightmap(),
    mParticleSystem(),
    mAniMesh(NULL),
    mCastsShadow(false),
    mDrawBoundingBox(false),
    mDrawLabel(false),
    mFPSCamera(),
    mAnimationSpeed(25.0f),
    mCollisionMask(0)
    {
        AssertMsg( factory, "Invalid sim factory" );

        std::string val, aniMeshFile;
        IrrFactory& irrFac = factory->getIrrFactory();

        // get the mesh (possibly)
        if( propMap.getValue( aniMeshFile, "Template.Render.AniMesh" ) )
        {
            mAniMesh = irrFac.LoadAniMesh( aniMeshFile.c_str() );
        }

        if( propMap.hasSection( "Template.Render.CastsShadow" ) )
        {
            propMap.getValue( mCastsShadow, "Template.Render.CastsShadow" );
        }

        if( propMap.hasSection( "Template.Render.DrawBoundingBox" ) )
        {
            propMap.getValue( mDrawBoundingBox, "Template.Render.DrawBoundingBox" );
        }

        if( propMap.hasSection( "Template.Render.DrawLabel" ) )
        {
            propMap.getValue( mDrawLabel, "Template.Render.DrawLabel" );
        }

        if (propMap.hasSection( "Template.Render.FPSCamera" ) )
        {
			mFPSCamera.reset(new FPSCameraTemplate("Template.Render.FPSCamera", propMap));
            LOG_F_DEBUG( "render", "object uses an FPS camera " << mFPSCamera );
        }

        if (propMap.hasSection( "Template.Render.AnimationSpeed" ) )
        {
            propMap.getValue( mAnimationSpeed, "Template.Render.AnimationSpeed" );
            LOG_F_DEBUG( "render", "object animation speed: " << mAnimationSpeed );
        }

		if (propMap.hasSection( "Template.Render.Collision" ))
		{
			propMap.getValue( mCollisionMask, "Template.Render.Collision" );
		}

        // get the heightmap (possibly)
        propMap.getValue( mHeightmap, "Template.Render.Terrain" );

        // get the particle system (possibly)
        propMap.getValue( mParticleSystem, "Template.Render.ParticleSystem" );

        PropertyMap::ChildPropVector renderProps;
        propMap.getPropChildren( renderProps, "Template.Render" );

        PropertyMap::ChildPropVector::const_iterator itr = renderProps.begin();
        PropertyMap::ChildPropVector::const_iterator end = renderProps.end();

        // get all the properties of Render
        for( ; itr != end; ++itr )
        {
            // if it starts with the word "Texture" in it (ex: Texture0, Texture1, ...)
            if( itr->first.find("Texture") == 0 )
            {
                ITexture* tex = irrFac.LoadTexture( itr->second );
                if( tex )
                {
                    mTextures.push_back( ITexture_IPtr(tex) );
                }
            }

            // if it contains the word "MaterialFlag" in it( ex: MaterialFlagLighting, ... )
            if( itr->first.find("MaterialFlag") != std::string::npos )
            {
                IrrMaterialFlag flag;

                IrrMaterialFlagConverter c( itr->first.substr(12) );
                c( flag, itr->second );

                if( flag.mFlag != (E_MATERIAL_FLAG)-1 )
                    mMaterialFlags.push_back( flag );
            }
        }

        // get the material type
        propMap.getValue( mMaterialType, "Template.Render.MaterialType", IrrMaterialTypeConverter(factory) );

        // get the scale and texture scale
        propMap.getValue( mScale,           "Template.Render.Scale" );
        propMap.getValue( mScaleTexture,    "Template.Render.ScaleTexture" );

#if SCENEOBJECT_ENABLE_STATS
        // display debug scene object info
        if( mAniMesh )
        {
            const aabbox3df& bbox = mAniMesh->getBoundingBox();
            vector3df  dim  = bbox.MaxEdge - bbox.MinEdge;
            dim.X *= mScale.X;
            dim.Y *= mScale.Y;
            dim.Z *= mScale.Z;

            float32_t vol = dim.X * dim.Y * dim.Z;
            vol = (vol<0) ? -vol : vol;

            LOG_F_MSG( "render", "Loaded animated mesh " << aniMeshFile << " with custom scale (" << mScale << ")" );
            LOG_F_MSG( "render", "   Dim: (" << dim.X << ", " << dim.Y << ", " << dim.Z << ")" );
            LOG_F_MSG( "render", "   Volume: " << vol );
        }
#endif // SCENEOBJECT_ENABLE_STATS
    }