/// 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); } }
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 }