void BillboardSet::UpdateBatches(const FrameInfo& frame)
{
    // If beginning a new frame, assume no sorting first
    if (frame.frameNumber_ != sortFrameNumber_)
    {
        sortThisFrame_ = false;
        sortFrameNumber_ = frame.frameNumber_;
    }
    
    Vector3 worldPos = node_->GetWorldPosition();
    Vector3 offset = (worldPos - frame.camera_->GetNode()->GetWorldPosition());
    // Sort if position relative to camera has changed
    if (offset != previousOffset_ & sorted_)
        sortThisFrame_ = true;
    
    distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());

    // Calculate scaled distance for animation LOD
    float scale = GetWorldBoundingBox().Size().DotProduct(DOT_SCALE);
    // If there are no billboards, the size becomes zero, and LOD'ed updates no longer happen. Disable LOD in that case
    if (scale > M_EPSILON)
        lodDistance_ = frame.camera_->GetLodDistance(distance_, scale, lodBias_);
    else
        lodDistance_ = 0.0f;

    batches_[0].distance_ = distance_;
    batches_[0].numWorldTransforms_ = 2;
    // Billboard positioning
    transforms_[0] = relative_ ? node_->GetWorldTransform() : Matrix3x4::IDENTITY;
    // Billboard rotation
    transforms_[1] = Matrix3x4(Vector3::ZERO, faceCameraMode_ != FC_NONE ? frame.camera_->GetFaceCameraRotation(
        node_->GetWorldPosition(), node_->GetWorldRotation(), faceCameraMode_) : node_->GetWorldRotation(), Vector3::ONE);
}
Beispiel #2
0
void BillboardSet::UpdateBatches(const FrameInfo& frame)
{
    // Check if position relative to camera has changed, and re-sort in that case
    const Matrix3x4& worldTransform = node_->GetWorldTransform();
    Vector3 worldPos = worldTransform.Translation();
    Vector3 offset = (worldPos - frame.camera_->GetNode()->GetWorldPosition());
    if (offset != previousOffset_)
    {
        previousOffset_ = offset;
        if (sorted_)
        {
            // Sort billboards only once per frame. This means that secondary views will get
            // the same sorting as the main view
            if (frame.frameNumber_ != sortFrameNumber_)
            {
                sortFrameNumber_ = frame.frameNumber_;
                bufferDirty_ = true;
            }
        }
    }
    
    distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());
    
    // Calculate scaled distance for animation LOD
    float scale = GetWorldBoundingBox().Size().DotProduct(DOT_SCALE);
    // If there are no billboards, the size becomes zero, and LOD'ed updates no longer happen. Disable LOD in that case
    if (scale > M_EPSILON)
        lodDistance_ = frame.camera_->GetLodDistance(distance_, scale, lodBias_);
    else
        lodDistance_ = 0.0f;
    
    batches_[0].distance_ = distance_;
    batches_[0].worldTransform_ = relative_ ? &node_->GetWorldTransform() : &Matrix3x4::IDENTITY;
}
Beispiel #3
0
csScreenBoxResult csMeshWrapper::GetScreenBoundingBox (iCamera *camera)
{
  csScreenBoxResult rc;

  // Calculate camera space bbox.
  csReversibleTransform tr_o2c = camera->GetTransform ();
  if (!movable.IsFullTransformIdentity ())
    tr_o2c /= movable.GetFullTransform ();
  
  rc.cbox = GetTransformedBoundingBox (tr_o2c);

  // Calculate screen space bbox.
  float minz, maxz;
  const csBox3& wbox = GetWorldBoundingBox();
  if(!wbox.ProjectBox(camera->GetTransform(), camera->GetProjectionMatrix(),
      rc.sbox, minz, maxz, engine->G3D->GetWidth(),
      engine->G3D->GetHeight()))
  {
      rc.distance = -1;
  }
  else
  {
      rc.distance = rc.cbox.MaxZ ();
  }

  return rc;
}
Beispiel #4
0
		Air::U1 MeshEntity::RayCast( const Ray& ray ,float*	pOutDistance)
		{
#if 1
			if(!GetWorldBoundingBox().RayCast(ray.GetOrigin(),ray.GetDirection())){//.Intersect(GetWorldBoundingBox())){
				return	false;
			}
#endif

			Matrix	matWorld	=	*GetWorldMatrix();
			Matrix	matWorldInv	=	matWorld;
			matWorldInv.Inverse();
			Float3	vStart	=	ray.m_vStart;
			Float3	vLookAt	=	vStart	+	ray.m_vDirection;
			vStart			=	matWorldInv*vStart;
			vLookAt			=	matWorldInv*vLookAt;
			Float3	vDir	=	(vLookAt	-	vStart);
			vDir.Normalize();

			Ray	objSpaceRay(vStart,vDir);

			float	fDistance	=	999999.0f;

			U1	bHit	=	m_pMesh->RayCast(objSpaceRay,&fDistance);
			if(bHit	&&	pOutDistance!=NULL){
				Float3	vObjSpaceHitPostion		=	vStart	+	vDir*fDistance;
				Float3	vWorldSpaceHiPosition	=	matWorld*vObjSpaceHitPostion;
				*pOutDistance	=	(vWorldSpaceHiPosition	-	ray.m_vStart).Length();
			}
			return	bHit;
		}
Beispiel #5
0
void Text3D::UpdateBatches(const FrameInfo& frame)
{
    distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());

    if (faceCameraMode_ != FC_NONE)
    {
        Vector3 worldPosition = node_->GetWorldPosition();
        customWorldTransform_ = Matrix3x4(worldPosition, frame.camera_->GetFaceCameraRotation(
            worldPosition, node_->GetWorldRotation(), faceCameraMode_), node_->GetWorldScale());
        worldBoundingBoxDirty_ = true;
    }

    for (unsigned i = 0; i < batches_.Size(); ++i)
    {
        batches_[i].distance_ = distance_;
        batches_[i].worldTransform_ = faceCameraMode_ != FC_NONE ? &customWorldTransform_ : &node_->GetWorldTransform();
    }

    for (unsigned i = 0; i < uiBatches_.Size(); ++i)
    {
        if (uiBatches_[i].texture_ && uiBatches_[i].texture_->IsDataLost())
        {
            fontDataLost_ = true;
            break;
        }
    }
}
void StaticModelGroup::UpdateBatches(const FrameInfo& frame)
{
    // Getting the world bounding box ensures the transforms are updated
    const BoundingBox& worldBoundingBox = GetWorldBoundingBox();
    const Matrix3x4& worldTransform = node_->GetWorldTransform();
    distance_ = frame.camera_->GetDistance(worldBoundingBox.Center());
    
    if (batches_.Size() > 1)
    {
        for (unsigned i = 0; i < batches_.Size(); ++i)
        {
            batches_[i].distance_ = frame.camera_->GetDistance(worldTransform * geometryData_[i].center_);
            batches_[i].worldTransform_ = numWorldTransforms_ ? &worldTransforms_[0] : &Matrix3x4::IDENTITY;
            batches_[i].numWorldTransforms_ = numWorldTransforms_;
        }
    }
    else if (batches_.Size() == 1)
    {
        batches_[0].distance_ = distance_;
        batches_[0].worldTransform_ = numWorldTransforms_ ? &worldTransforms_[0] : &Matrix3x4::IDENTITY;
        batches_[0].numWorldTransforms_ = numWorldTransforms_;
    }
    
    float scale = worldBoundingBox.Size().DotProduct(DOT_SCALE);
    float newLodDistance = frame.camera_->GetLodDistance(distance_, scale, lodBias_);
    
    if (newLodDistance != lodDistance_)
    {
        lodDistance_ = newLodDistance;
        CalculateLodLevels();
    }
}
Beispiel #7
0
void Zone::ClearDrawablesZone()
{
    if (octant_ && lastWorldBoundingBox_.defined_)
    {
        PODVector<Drawable*> result;
        BoxOctreeQuery query(result, lastWorldBoundingBox_, DRAWABLE_GEOMETRY | DRAWABLE_ZONE);
        octant_->GetRoot()->GetDrawables(query);

        for (PODVector<Drawable*>::Iterator i = result.Begin(); i != result.End(); ++i)
        {
            Drawable* drawable = *i;
            unsigned drawableFlags = drawable->GetDrawableFlags();
            if (drawableFlags & DRAWABLE_GEOMETRY)
                drawable->SetZone(0);
            else if (drawableFlags & DRAWABLE_ZONE)
            {
                Zone* zone = static_cast<Zone*>(drawable);
                zone->lastAmbientStartZone_.Reset();
                zone->lastAmbientEndZone_.Reset();
            }
        }
    }

    lastWorldBoundingBox_ = GetWorldBoundingBox();
    lastAmbientStartZone_.Reset();
    lastAmbientEndZone_.Reset();
}
void StaticModel::UpdateBatches(const FrameInfo& frame)
{
    const BoundingBox& worldBoundingBox = GetWorldBoundingBox();
    distance_ = frame.camera_->GetDistance(worldBoundingBox.Center());

    if (batches_.Size() == 1)
        batches_[0].distance_ = distance_;
    else
    {
        const Matrix3x4& worldTransform = node_->GetWorldTransform();
        for (unsigned i = 0; i < batches_.Size(); ++i)
            batches_[i].distance_ = frame.camera_->GetDistance(worldTransform * geometryData_[i].center_);
    }

    float scale = worldBoundingBox.Size().DotProduct(DOT_SCALE);
    float newLodDistance = frame.camera_->GetLodDistance(distance_, scale, lodBias_);

    if (newLodDistance != lodDistance_)
    {
        lodDistance_ = newLodDistance;
        CalculateLodLevels();
    }

    // ATOMIC BEGIN
    if (geometryDisabled_)
        UpdateBatchesHideGeometry();
    // ATOMIC END

}
Beispiel #9
0
void Drawable2D::UpdateBatches(const FrameInfo& frame)
{
    const Matrix3x4& worldTransform = node_->GetWorldTransform();
    distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());

    batches_[0].distance_ = distance_;
    batches_[0].worldTransform_ = &worldTransform;
}
void StaticModelGroup::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results)
{
    // If no bones or no bone-level testing, use the Drawable test
    RayQueryLevel level = query.level_;
    if (level < RAY_AABB)
    {
        Drawable::ProcessRayQuery(query, results);
        return;
    }

    // Check ray hit distance to AABB before proceeding with more accurate tests
    // GetWorldBoundingBox() updates the world transforms
    if (query.ray_.HitDistance(GetWorldBoundingBox()) >= query.maxDistance_)
        return;
    
    for (unsigned i = 0; i < numWorldTransforms_; ++i)
    {
        // Initial test using AABB
        float distance = query.ray_.HitDistance(boundingBox_.Transformed(worldTransforms_[i]));
        
        // Then proceed to OBB and triangle-level tests if necessary
        if (level >= RAY_OBB && distance < query.maxDistance_)
        {
            Matrix3x4 inverse = worldTransforms_[i].Inverse();
            Ray localRay = query.ray_.Transformed(inverse);
            distance = localRay.HitDistance(boundingBox_);
            
            if (level == RAY_TRIANGLE && distance < query.maxDistance_)
            {
                distance = M_INFINITY;
                
                for (unsigned j = 0; j < batches_.Size(); ++j)
                {
                    Geometry* geometry = batches_[j].geometry_;
                    if (geometry)
                    {
                        float geometryDistance = geometry->GetHitDistance(localRay);
                        if (geometryDistance < query.maxDistance_ && geometryDistance < distance)
                            distance = geometryDistance;
                    }
                }
            }
        }
        
        if (distance < query.maxDistance_)
        {
            RayQueryResult result;
            result.drawable_ = this;
            result.node_ = node_;
            result.distance_ = distance;
            result.subObject_ = i;
            results.Push(result);
        }
    }
}
Beispiel #11
0
void SceneNode::OnUpdateRenderQueues( const Camera& camera, RenderOrder order, uint32_t buckterFilter, uint32_t filterIgnore )
{
	const BoundingBoxf& worldBound = GetWorldBoundingBox();

	if (!camera.Visible(GetWorldBoundingBox()))
		return;

	RenderQueue& renderQueue = mScene->GetRenderQueue();
	for (SceneObject* pSceneObject : mAttachedObjects)
	{
		if (pSceneObject->IsActive() && pSceneObject->Renderable())
			pSceneObject->OnUpdateRenderQueue(&renderQueue, camera, order, buckterFilter, filterIgnore);
	}

	// recursively call children
	for (Node* node : mChildren)
	{
		SceneNode* child = static_cast<SceneNode*>(node);
		child->OnUpdateRenderQueues(camera, order, buckterFilter, filterIgnore);
	}
}
void Light::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results)
{
    // Do not record a raycast result for a directional light, as it would block all other results
    if (lightType_ == LIGHT_DIRECTIONAL)
        return;

    float distance = query.maxDistance_;
    switch (query.level_)
    {
    case RAY_AABB:
        Drawable::ProcessRayQuery(query, results);
        return;

    case RAY_OBB:
        {
            Matrix3x4 inverse(node_->GetWorldTransform().Inverse());
            Ray localRay = query.ray_.Transformed(inverse);
            distance = localRay.HitDistance(GetWorldBoundingBox().Transformed(inverse));
            if (distance >= query.maxDistance_)
                return;
        }
        break;

    case RAY_TRIANGLE:
        if (lightType_ == LIGHT_SPOT)
        {
            distance = query.ray_.HitDistance(GetFrustum());
            if (distance >= query.maxDistance_)
                return;
        }
        else
        {
            distance = query.ray_.HitDistance(Sphere(node_->GetWorldPosition(), range_));
            if (distance >= query.maxDistance_)
                return;
        }
        break;

    case RAY_TRIANGLE_UV:
        LOGWARNING("RAY_TRIANGLE_UV query level is not supported for Light component");
        return;
    }

    // If the code reaches here then we have a hit
    RayQueryResult result;
    result.position_ = query.ray_.origin_ + distance * query.ray_.direction_;
    result.normal_ = -query.ray_.direction_;
    result.distance_ = distance;
    result.drawable_ = this;
    result.node_ = node_;
    result.subObject_ = M_MAX_UNSIGNED;
    results.Push(result);
}
void Drawable::LimitLights()
{
    // Maximum lights value 0 means unlimited
    if (!maxLights_ || lights_.Size() <= maxLights_)
        return;

    // If more lights than allowed, move to vertex lights and cut the list
    const BoundingBox& box = GetWorldBoundingBox();
    for (unsigned i = 0; i < lights_.Size(); ++i)
        lights_[i]->SetIntensitySortValue(box);

    Sort(lights_.Begin(), lights_.End(), CompareDrawables);
    vertexLights_.Insert(vertexLights_.End(), lights_.Begin() + maxLights_, lights_.End());
    lights_.Resize(maxLights_);
}
void Drawable::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results)
{
    float distance = query.ray_.HitDistance(GetWorldBoundingBox());
    if (distance < query.maxDistance_)
    {
        RayQueryResult result;
        result.position_ = query.ray_.origin_ + distance * query.ray_.direction_;
        result.normal_ = -query.ray_.direction_;
        result.distance_ = distance;
        result.drawable_ = this;
        result.node_ = GetNode();
        result.subObject_ = M_MAX_UNSIGNED;
        results.Push(result);
    }
}
Beispiel #15
0
void Text3D::UpdateBatches(const FrameInfo& frame)
{
    const Matrix3x4& worldTransform = node_->GetWorldTransform();
    distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());
    
    if (faceCamera_)
    {
        customWorldTransform_ = Matrix3x4(node_->GetWorldPosition(), frame.camera_->GetNode()->GetWorldRotation(), node_->GetWorldScale());
        worldBoundingBoxDirty_ = true;
    }
    
    for (unsigned i = 0; i < batches_.Size(); ++i)
    {
        batches_[i].distance_ = distance_;
        batches_[i].worldTransform_ = faceCamera_ ? &customWorldTransform_ : &worldTransform;
    }
}
bool StaticModelGroup::DrawOcclusion(OcclusionBuffer* buffer)
{
    // Make sure instance transforms are up-to-date
    GetWorldBoundingBox();
    
    for (unsigned i = 0; i < numWorldTransforms_; ++i)
    {
        for (unsigned j = 0; j < batches_.Size(); ++j)
        {
            Geometry* geometry = GetLodGeometry(j, occlusionLodLevel_);
            if (!geometry)
                continue;
            
            // Check that the material is suitable for occlusion (default material always is) and set culling mode
            Material* material = batches_[j].material_;
            if (material)
            {
                if (!material->GetOcclusion())
                    continue;
                buffer->SetCullMode(material->GetCullMode());
            }
            else
                buffer->SetCullMode(CULL_CCW);
            
            const unsigned char* vertexData;
            unsigned vertexSize;
            const unsigned char* indexData;
            unsigned indexSize;
            unsigned elementMask;
            
            geometry->GetRawData(vertexData, vertexSize, indexData, indexSize, elementMask);
            // Check for valid geometry data
            if (!vertexData || !indexData)
                continue;
            
            unsigned indexStart = geometry->GetIndexStart();
            unsigned indexCount = geometry->GetIndexCount();
            
            // Draw and check for running out of triangles
            if (!buffer->Draw(worldTransforms_[i], vertexData, vertexSize, indexData, indexSize, indexStart, indexCount))
                return false;
        }
    }
    
    return true;
}
void Drawable::UpdateBatches(const FrameInfo& frame)
{
    const BoundingBox& worldBoundingBox = GetWorldBoundingBox();
    const Matrix3x4& worldTransform = node_->GetWorldTransform();
    distance_ = frame.camera_->GetDistance(worldBoundingBox.Center());

    for (unsigned i = 0; i < batches_.Size(); ++i)
    {
        batches_[i].distance_ = distance_;
        batches_[i].worldTransform_ = &worldTransform;
    }

    float scale = worldBoundingBox.Size().DotProduct(DOT_SCALE);
    float newLodDistance = frame.camera_->GetLodDistance(distance_, scale, lodBias_);

    if (newLodDistance != lodDistance_)
        lodDistance_ = newLodDistance;
}
Beispiel #18
0
void BillboardSet::ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results)
{
    // If no billboard-level testing, use the Drawable test
    if (query.level_ < RAY_TRIANGLE)
    {
        Drawable::ProcessRayQuery(query, results);
        return;
    }

    // Check ray hit distance to AABB before proceeding with billboard-level tests
    if (query.ray_.HitDistance(GetWorldBoundingBox()) >= query.maxDistance_)
        return;

    const Matrix3x4& worldTransform = node_->GetWorldTransform();
    Matrix3x4 billboardTransform = relative_ ? worldTransform : Matrix3x4::IDENTITY;
    Vector3 billboardScale = scaled_ ? worldTransform.Scale() : Vector3::ONE;

    for (unsigned i = 0; i < billboards_.Size(); ++i)
    {
        if (!billboards_[i].enabled_)
            continue;

        // Approximate the billboards as spheres for raycasting
        float size = INV_SQRT_TWO * (billboards_[i].size_.x_ * billboardScale.x_ + billboards_[i].size_.y_ * billboardScale.y_);
        if (fixedScreenSize_)
            size *= billboards_[i].screenScaleFactor_;
        Vector3 center = billboardTransform * billboards_[i].position_;
        Sphere billboardSphere(center, size);

        float distance = query.ray_.HitDistance(billboardSphere);
        if (distance < query.maxDistance_)
        {
            // If the code reaches here then we have a hit
            RayQueryResult result;
            result.position_ = query.ray_.origin_ + distance * query.ray_.direction_;
            result.normal_ = -query.ray_.direction_;
            result.distance_ = distance;
            result.drawable_ = this;
            result.node_ = node_;
            result.subObject_ = i;
            results.Push(result);
        }
    }
}
Beispiel #19
0
    /// Gets the center world position of the tree's trunk.
    /// @return The center world position of the tree's trunk.
    MATH::Vector2f Tree::GetTrunkCenterWorldPosition() const
    {
        // GET THE BOUNDING BOX OF THE TREE.
        MATH::FloatRectangle world_bounding_box = GetWorldBoundingBox();

        // CALCULATE THE CENTER OF THE TREE'S TRUNK.
        // The center will be set so that it works for all current tree sizes.
        // It is vertically placed halfway up the pixel grid for the smallest
        // tree size, which also works well for other tree sizes.
        const float OFFSET_FROM_TREE_BOTTOM_TO_TRUNK_CENTER_IN_PIXELS = 8.0f;
        float tree_bottom_world_y_position = world_bounding_box.GetBottomYPosition();
        // Y gets smaller going up.
        float trunk_center_y_position = tree_bottom_world_y_position - OFFSET_FROM_TREE_BOTTOM_TO_TRUNK_CENTER_IN_PIXELS;
        float trunk_center_x_position = world_bounding_box.GetCenterXPosition();
        MATH::Vector2f trunk_center_world_position(
            trunk_center_x_position,
            trunk_center_y_position);
        return trunk_center_world_position;
    }
Beispiel #20
0
void Zone::OnMarkedDirty(Node* node)
{
    // Due to the octree query and weak pointer manipulation, is not safe from worker threads
    Scene* scene = GetScene();
    if (scene && scene->IsThreadedUpdate())
    {
        scene->DelayedMarkedDirty(this);
        return;
    }

    Drawable::OnMarkedDirty(node);

    // When marked dirty, clear the cached zone from all drawables inside the zone bounding box,
    // and mark gradient dirty in all neighbor zones
    if (octant_ && lastWorldBoundingBox_.defined_)
    {
        PODVector<Drawable*> result;
        BoxOctreeQuery query(result, lastWorldBoundingBox_, DRAWABLE_GEOMETRY | DRAWABLE_ZONE);
        octant_->GetRoot()->GetDrawables(query);

        for (PODVector<Drawable*>::Iterator i = result.Begin(); i != result.End(); ++i)
        {
            Drawable* drawable = *i;
            unsigned drawableFlags = drawable->GetDrawableFlags();
            if (drawableFlags & DRAWABLE_GEOMETRY)
            {
                if (drawable->GetZone() == this)
                    drawable->SetZone(0);
            }
            else if (drawableFlags & DRAWABLE_ZONE)
            {
                Zone* zone = static_cast<Zone*>(drawable);
                zone->lastAmbientStartZone_.Reset();
                zone->lastAmbientEndZone_.Reset();
            }
        }
    }

    lastWorldBoundingBox_ = GetWorldBoundingBox();
    lastAmbientStartZone_.Reset();
    lastAmbientEndZone_.Reset();
    inverseWorldDirty_ = true;
}
void Drawable::LimitVertexLights(bool removeConvertedLights)
{
    if (removeConvertedLights)
    {
        for (unsigned i = vertexLights_.Size() - 1; i < vertexLights_.Size(); --i)
        {
            if (!vertexLights_[i]->GetPerVertex())
                vertexLights_.Erase(i);
        }
    }

    if (vertexLights_.Size() <= MAX_VERTEX_LIGHTS)
        return;

    const BoundingBox& box = GetWorldBoundingBox();
    for (unsigned i = 0; i < vertexLights_.Size(); ++i)
        vertexLights_[i]->SetIntensitySortValue(box);

    Sort(vertexLights_.Begin(), vertexLights_.End(), CompareDrawables);
    vertexLights_.Resize(MAX_VERTEX_LIGHTS);
}
Beispiel #22
0
void Text3D::UpdateBatches(const FrameInfo& frame)
{
    distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());

    if (faceCameraMode_ != FC_NONE || fixedScreenSize_)
        CalculateFixedScreenSize(frame);

    for (unsigned i = 0; i < batches_.Size(); ++i)
    {
        batches_[i].distance_ = distance_;
        batches_[i].worldTransform_ = faceCameraMode_ != FC_NONE ? &customWorldTransform_ : &node_->GetWorldTransform();
    }

    for (unsigned i = 0; i < uiBatches_.Size(); ++i)
    {
        if (uiBatches_[i].texture_ && uiBatches_[i].texture_->IsDataLost())
        {
            fontDataLost_ = true;
            break;
        }
    }
}
void TerrainPatch::UpdateBatches(const FrameInfo& frame)
{
    const Matrix3x4& worldTransform = node_->GetWorldTransform();
    distance_ = frame.camera_->GetDistance(GetWorldBoundingBox().Center());
    
    float scale = worldTransform.Scale().DotProduct(DOT_SCALE);
    lodDistance_ = frame.camera_->GetLodDistance(distance_, scale, lodBias_);
    
    batches_[0].distance_ = distance_;
    batches_[0].worldTransform_ = &worldTransform;
    
    unsigned newLodLevel = 0;
    for (unsigned i = 0; i < lodErrors_.Size(); ++i)
    {
        if (lodErrors_[i] / lodDistance_ > LOD_CONSTANT)
            break;
        else
            newLodLevel = i;
    }
    
    lodLevel_ = GetCorrectedLodLevel(newLodLevel);
}
unsigned StaticModelGroup::GetNumOccluderTriangles()
{
    // Make sure instance transforms are up-to-date
    GetWorldBoundingBox();
    
    unsigned triangles = 0;
    
    for (unsigned i = 0; i < batches_.Size(); ++i)
    {
        Geometry* geometry = GetLodGeometry(i, occlusionLodLevel_);
        if (!geometry)
            continue;
        
        // Check that the material is suitable for occlusion (default material always is)
        Material* mat = batches_[i].material_;
        if (mat && !mat->GetOcclusion())
            continue;
        
        triangles += numWorldTransforms_ * geometry->GetIndexCount() / 3;
    }
    
    return triangles;
}
Beispiel #25
0
/// Gets the width of the sprite, in pixels.
/// @return The width of the sprite.
float Sprite::GetWidthInPixels() const
{
    MATH::FloatRectangle bounding_box = GetWorldBoundingBox();
    float width = bounding_box.GetWidth();
    return width;
}
Beispiel #26
0
    /// Updates the entire overworld for the elapsed time.
    /// @param[in]  elapsed_time - The elapsed time for which to update the world.
    /// @param[in,out]  input_controller - The controller supplying player input.
    /// @param[in,out]  camera - The camera defining the viewable region of the overworld.
    /// @param[out] message_for_text_box - The message to display in the main text box,
    ///     if one needs to start being displayed; empty if no new message needs to be displayed.
    void GameplayState::UpdateOverworld(
        const sf::Time& elapsed_time,
        INPUT_CONTROL::KeyboardInputController& input_controller,
        GRAPHICS::Camera& camera,
        std::string& message_for_text_box)
    {
        // INDICATE THAT NO MESSAGE NEEDS TO BE DISPLAYED YET IN THE TEXT BOX.
        message_for_text_box.clear();

        MATH::FloatRectangle camera_bounds = camera.ViewBounds;
        MATH::Vector2f camera_view_center = camera_bounds.GetCenterPosition();

        MAPS::TileMap* current_tile_map = Overworld->GetTileMap(camera_view_center.X, camera_view_center.Y);
        assert(current_tile_map);

        // CHECK IF THE PRIMARY ACTION BUTTON WAS PRESSED.
        if (input_controller.ButtonDown(INPUT_CONTROL::KeyboardInputController::PRIMARY_ACTION_KEY))
        {
            // SWING THE PLAYER'S AXE.
            // A new axe swing may not be created if the player's
            // axe is already being swung.
            std::shared_ptr<EVENTS::AxeSwingEvent> axe_swing = Overworld->NoahPlayer->SwingAxe();
            bool axe_swing_occurred = (nullptr != axe_swing);
            if (axe_swing_occurred)
            {
                // Allow the axe to collide with other objects.
                Overworld->AxeSwings.push_back(axe_swing);
            }
        }

        // CHECK IF THE PLAYER IS ALLOWED TO MOVE.
        // Noah can't move while the axe is swinging.
        // Movement is prevented to have the axe's position remain attached to Noah.
        // We need to keep track if Noah moved this frame so that we can stop any walking animations for him if he didn't move.
        bool noah_moved_this_frame = false;
        bool axe_is_swinging = (nullptr != Overworld->NoahPlayer->Inventory->Axe) && Overworld->NoahPlayer->Inventory->Axe->IsSwinging();
        bool player_movement_allowed = (!axe_is_swinging);
        if (player_movement_allowed)
        {
            // MOVE NOAH IN RESPONSE TO USER INPUT.
            const float PLAYER_POSITION_ADJUSTMENT_FOR_SCROLLING_IN_PIXELS = 8.0f;
            MATH::Vector2f old_noah_position = Overworld->NoahPlayer->GetWorldPosition();
            if (input_controller.ButtonDown(INPUT_CONTROL::KeyboardInputController::UP_KEY))
            {
                // TRACK NOAH AS MOVING THIS FRAME.
                noah_moved_this_frame = true;

                // START NOAH WALKING UP.
                Overworld->NoahPlayer->BeginWalking(CORE::Direction::UP, OBJECTS::Noah::WALK_BACK_ANIMATION_NAME);

                // MOVE NOAH WHILE HANDLING COLLISIONS.
                MATH::Vector2f new_position = COLLISION::CollisionDetectionAlgorithms::MoveObject(
                    Overworld->NoahPlayer->GetWorldBoundingBox(),
                    CORE::Direction::UP,
                    OBJECTS::Noah::MOVE_SPEED_IN_PIXELS_PER_SECOND,
                    elapsed_time,
                    *Overworld);
                Overworld->NoahPlayer->SetWorldPosition(new_position);

                // CHECK IF NOAH MOVED OUT OF THE CAMERA'S VIEW.
                MATH::FloatRectangle noah_world_bounding_box = Overworld->NoahPlayer->GetWorldBoundingBox();
                float camera_top_y_position = camera_bounds.GetTopYPosition();
                bool player_moved_out_of_view = (noah_world_bounding_box.GetTopYPosition() < camera_top_y_position);
                if (player_moved_out_of_view)
                {
                    // CHECK IF A TOP TILE MAP EXISTS FOR NOAH TO MOVE TO.
                    unsigned int top_tile_map_row_index = current_tile_map->OverworldRowIndex - 1;
                    unsigned int top_tile_map_column_index = current_tile_map->OverworldColumnIndex;
                    MAPS::TileMap* top_tile_map = Overworld->GetTileMap(
                        top_tile_map_row_index,
                        top_tile_map_column_index);
                    bool top_tile_map_exists = (nullptr != top_tile_map);
                    if (top_tile_map_exists)
                    {
                        // MOVE NOAH A FEW MORE PIXELS UP SO THAT HE WILL BE MORE VISIBLE ON THE NEW MAP.
                        MATH::Vector2f noah_world_position = Overworld->NoahPlayer->GetWorldPosition();
                        noah_world_position.Y -= PLAYER_POSITION_ADJUSTMENT_FOR_SCROLLING_IN_PIXELS;
                        Overworld->NoahPlayer->SetWorldPosition(noah_world_position);

                        // START SCROLLING TO THE TOP TILE MAP.
                        MATH::Vector2f scroll_start_position = current_tile_map->GetCenterWorldPosition();
                        MATH::Vector2f scroll_end_position = top_tile_map->GetCenterWorldPosition();
                        camera.StartScrolling(scroll_start_position, scroll_end_position);

                        // DISABLE PLAYER MOVEMENT WHILE SCROLLING IS OCCURRING.
                        input_controller.DisableInput();
                    }
                    else
                    {
                        // KEEP NOAH WITHIN THE BOUNDS OF THE CURRENT TILE MAP.
                        // Since there is no top tile map to scroll to, this will keep Noah on-screen.
                        MATH::FloatRectangle tile_map_bounding_box = current_tile_map->GetWorldBoundingBox();
                        float tile_map_top_boundary = tile_map_bounding_box.GetTopYPosition();

                        // To keep Noah completely on screen, his center position should be half
                        // his height below the top tile map boundary.
                        MATH::Vector2f noah_world_position = old_noah_position;
                        float noah_half_height = noah_world_bounding_box.GetHeight() / 2.0f;
                        noah_world_position.Y = tile_map_top_boundary + noah_half_height;

                        Overworld->NoahPlayer->SetWorldPosition(noah_world_position);
                    }
                }
            }
            if (input_controller.ButtonDown(INPUT_CONTROL::KeyboardInputController::DOWN_KEY))
            {
                // TRACK NOAH AS MOVING THIS FRAME.
                noah_moved_this_frame = true;

                // START NOAH WALKING DOWN.
                Overworld->NoahPlayer->BeginWalking(CORE::Direction::DOWN, OBJECTS::Noah::WALK_FRONT_ANIMATION_NAME);

                // MOVE NOAH WHILE HANDLING COLLISIONS.
                MATH::Vector2f new_position = COLLISION::CollisionDetectionAlgorithms::MoveObject(
                    Overworld->NoahPlayer->GetWorldBoundingBox(),
                    CORE::Direction::DOWN,
                    OBJECTS::Noah::MOVE_SPEED_IN_PIXELS_PER_SECOND,
                    elapsed_time,
                    *Overworld);
                Overworld->NoahPlayer->SetWorldPosition(new_position);

                // CHECK IF NOAH MOVED OUT OF THE CAMERA'S VIEW.
                MATH::FloatRectangle noah_world_bounding_box = Overworld->NoahPlayer->GetWorldBoundingBox();
                float camera_bottom_y_position = camera_bounds.GetBottomYPosition();
                bool player_moved_out_of_view = (noah_world_bounding_box.GetBottomYPosition() > camera_bottom_y_position);
                if (player_moved_out_of_view)
                {
                    // CHECK IF A BOTTOM TILE MAP EXISTS FOR NOAH TO MOVE TO.
                    unsigned int bottom_tile_map_row_index = current_tile_map->OverworldRowIndex + 1;
                    unsigned int bottom_tile_map_column_index = current_tile_map->OverworldColumnIndex;
                    MAPS::TileMap* bottom_tile_map = Overworld->GetTileMap(
                        bottom_tile_map_row_index,
                        bottom_tile_map_column_index);
                    bool bottom_tile_map_exists = (nullptr != bottom_tile_map);
                    if (bottom_tile_map_exists)
                    {
                        // MOVE NOAH A FEW MORE PIXELS DOWN SO THAT HE WILL BE MORE VISIBLE ON THE NEW MAP.
                        MATH::Vector2f noah_world_position = Overworld->NoahPlayer->GetWorldPosition();
                        noah_world_position.Y += PLAYER_POSITION_ADJUSTMENT_FOR_SCROLLING_IN_PIXELS;
                        Overworld->NoahPlayer->SetWorldPosition(noah_world_position);

                        // START SCROLLING TO THE BOTTOM TILE MAP.
                        MATH::Vector2f scroll_start_position = current_tile_map->GetCenterWorldPosition();
                        MATH::Vector2f scroll_end_position = bottom_tile_map->GetCenterWorldPosition();
                        camera.StartScrolling(scroll_start_position, scroll_end_position);

                        // DISABLE PLAYER MOVEMENT WHILE SCROLLING IS OCCURRING.
                        input_controller.DisableInput();
                    }
                    else
                    {
                        // KEEP NOAH WITHIN THE BOUNDS OF THE CURRENT TILE MAP.
                        // Since there is no bottom tile map to scroll to, this will keep Noah on-screen.
                        MATH::FloatRectangle tile_map_bounding_box = current_tile_map->GetWorldBoundingBox();
                        float tile_map_bottom_boundary = tile_map_bounding_box.GetBottomYPosition();

                        // To keep Noah completely on screen, his center position should be half
                        // his height above the bottom tile map boundary.
                        MATH::Vector2f noah_world_position = old_noah_position;
                        float noah_half_height = Overworld->NoahPlayer->GetWorldBoundingBox().GetHeight() / 2.0f;
                        noah_world_position.Y = tile_map_bottom_boundary - noah_half_height;

                        Overworld->NoahPlayer->SetWorldPosition(noah_world_position);
                    }
                }
            } 
            if (input_controller.ButtonDown(INPUT_CONTROL::KeyboardInputController::LEFT_KEY))
            {
                // TRACK NOAH AS MOVING THIS FRAME.
                noah_moved_this_frame = true;

                // START NOAH WALKING LEFT.
                Overworld->NoahPlayer->BeginWalking(CORE::Direction::LEFT, OBJECTS::Noah::WALK_LEFT_ANIMATION_NAME);

                // MOVE NOAH WHILE HANDLING COLLISIONS.
                MATH::Vector2f new_position = COLLISION::CollisionDetectionAlgorithms::MoveObject(
                    Overworld->NoahPlayer->GetWorldBoundingBox(),
                    CORE::Direction::LEFT,
                    OBJECTS::Noah::MOVE_SPEED_IN_PIXELS_PER_SECOND,
                    elapsed_time,
                    *Overworld);
                Overworld->NoahPlayer->SetWorldPosition(new_position);

                // CHECK IF NOAH MOVED OUT OF THE CAMERA'S VIEW.
                MATH::FloatRectangle noah_world_bounding_box = Overworld->NoahPlayer->GetWorldBoundingBox();
                float camera_left_x_position = camera_bounds.GetLeftXPosition();
                bool player_moved_out_of_view = (noah_world_bounding_box.GetLeftXPosition() < camera_left_x_position);
                if (player_moved_out_of_view)
                {
                    // CHECK IF A LEFT TILE MAP EXISTS FOR NOAH TO MOVE TO.
                    unsigned int left_tile_map_row_index = current_tile_map->OverworldRowIndex;
                    unsigned int left_tile_map_column_index = current_tile_map->OverworldColumnIndex - 1;
                    MAPS::TileMap* left_tile_map = Overworld->GetTileMap(
                        left_tile_map_row_index,
                        left_tile_map_column_index);
                    bool left_tile_map_exists = (nullptr != left_tile_map);
                    if (left_tile_map_exists)
                    {
                        // MOVE NOAH A FEW MORE PIXELS LEFT SO THAT HE WILL BE MORE VISIBLE ON THE NEW MAP.
                        MATH::Vector2f noah_world_position = Overworld->NoahPlayer->GetWorldPosition();
                        noah_world_position.X -= PLAYER_POSITION_ADJUSTMENT_FOR_SCROLLING_IN_PIXELS;
                        Overworld->NoahPlayer->SetWorldPosition(noah_world_position);

                        // START SCROLLING TO THE LEFT TILE MAP.
                        MATH::Vector2f scroll_start_position = current_tile_map->GetCenterWorldPosition();
                        MATH::Vector2f scroll_end_position = left_tile_map->GetCenterWorldPosition();
                        camera.StartScrolling(scroll_start_position, scroll_end_position);

                        // DISABLE PLAYER MOVEMENT WHILE SCROLLING IS OCCURRING.
                        input_controller.DisableInput();
                    }
                    else
                    {
                        // KEEP NOAH WITHIN THE BOUNDS OF THE CURRENT TILE MAP.
                        // Since there is no left tile map to scroll to, this will keep Noah on-screen.
                        MATH::FloatRectangle tile_map_bounding_box = current_tile_map->GetWorldBoundingBox();
                        float tile_map_left_boundary = tile_map_bounding_box.GetLeftXPosition();

                        // To keep Noah completely on screen, his center position should be half
                        // his width to the right of the left tile map boundary.
                        MATH::Vector2f noah_world_position = old_noah_position;
                        float noah_half_width = Overworld->NoahPlayer->GetWorldBoundingBox().GetWidth() / 2.0f;
                        noah_world_position.X = tile_map_left_boundary + noah_half_width;

                        Overworld->NoahPlayer->SetWorldPosition(noah_world_position);
                    }
                }
            } 
            if (input_controller.ButtonDown(INPUT_CONTROL::KeyboardInputController::RIGHT_KEY))
            {
                // TRACK NOAH AS MOVING THIS FRAME.
                noah_moved_this_frame = true;

                // START NOAH WALKING RIGHT.
                Overworld->NoahPlayer->BeginWalking(CORE::Direction::RIGHT, OBJECTS::Noah::WALK_RIGHT_ANIMATION_NAME);

                // MOVE NOAH WHILE HANDLING COLLISIONS.
                MATH::Vector2f new_position = COLLISION::CollisionDetectionAlgorithms::MoveObject(
                    Overworld->NoahPlayer->GetWorldBoundingBox(),
                    CORE::Direction::RIGHT,
                    OBJECTS::Noah::MOVE_SPEED_IN_PIXELS_PER_SECOND,
                    elapsed_time,
                    *Overworld);
                Overworld->NoahPlayer->SetWorldPosition(new_position);

                // CHECK IF NOAH MOVED OUT OF THE CAMERA'S VIEW.
                MATH::FloatRectangle noah_world_bounding_box = Overworld->NoahPlayer->GetWorldBoundingBox();
                float camera_right_x_position = camera_bounds.GetRightXPosition();
                bool player_moved_out_of_view = (noah_world_bounding_box.GetRightXPosition() > camera_right_x_position);
                if (player_moved_out_of_view)
                {
                    // CHECK IF A RIGHT TILE MAP EXISTS FOR NOAH TO MOVE TO.
                    unsigned int right_tile_map_row_index = current_tile_map->OverworldRowIndex;
                    unsigned int right_tile_map_column_index = current_tile_map->OverworldColumnIndex + 1;
                    MAPS::TileMap* right_tile_map = Overworld->GetTileMap(
                        right_tile_map_row_index,
                        right_tile_map_column_index);
                    bool right_tile_map_exists = (nullptr != right_tile_map);
                    if (right_tile_map_exists)
                    {
                        // MOVE NOAH A FEW MORE PIXELS RIGHT SO THAT HE WILL BE MORE VISIBLE ON THE NEW MAP.
                        MATH::Vector2f noah_world_position = Overworld->NoahPlayer->GetWorldPosition();
                        noah_world_position.X += PLAYER_POSITION_ADJUSTMENT_FOR_SCROLLING_IN_PIXELS;
                        Overworld->NoahPlayer->SetWorldPosition(noah_world_position);

                        // START SCROLLING TO THE RIGHT TILE MAP.
                        MATH::Vector2f scroll_start_position = current_tile_map->GetCenterWorldPosition();
                        MATH::Vector2f scroll_end_position = right_tile_map->GetCenterWorldPosition();
                        camera.StartScrolling(scroll_start_position, scroll_end_position);

                        // DISABLE PLAYER MOVEMENT WHILE SCROLLING IS OCCURRING.
                        input_controller.DisableInput();
                    }
                    else
                    {
                        // KEEP NOAH WITHIN THE BOUNDS OF THE CURRENT TILE MAP.
                        // Since there is no right tile map to scroll to, this will keep Noah on-screen.
                        MATH::FloatRectangle tile_map_bounding_box = current_tile_map->GetWorldBoundingBox();
                        float tile_map_right_boundary = tile_map_bounding_box.GetRightXPosition();

                        // To keep Noah completely on screen, his center position should be half
                        // his width to the left of the right tile map boundary.
                        MATH::Vector2f noah_world_position = old_noah_position;
                        float noah_half_width = Overworld->NoahPlayer->GetWorldBoundingBox().GetWidth() / 2.0f;
                        noah_world_position.X = tile_map_right_boundary - noah_half_width;

                        Overworld->NoahPlayer->SetWorldPosition(noah_world_position);
                    }
                }
            } 
        }

        // CHECK IF NOAH MOVED THIS FRAME.
        if (noah_moved_this_frame)
        {
            // UPDATE NOAH'S ANIMATION.
            Overworld->NoahPlayer->Sprite.Update(elapsed_time);

            // BUILD A PIECE OF THE ARK IF NOAH STEPPED ONTO AN APPROPRIATE SPOT.
            MATH::Vector2f noah_world_position = Overworld->NoahPlayer->GetWorldPosition();
            MAPS::TileMap* tile_map_underneath_noah = Overworld->GetTileMap(noah_world_position.X, noah_world_position.Y);
            assert(tile_map_underneath_noah);
            
            // An ark piece only needs to be built once.
            OBJECTS::ArkPiece* ark_piece = tile_map_underneath_noah->GetArkPieceAtWorldPosition(noah_world_position);
            bool ark_piece_can_be_built = (ark_piece && !ark_piece->Built);
            if (ark_piece_can_be_built)
            {
                /// @todo   Check if Noah has wood.

                // BUILD THE ARK PIECE.
                ark_piece->Built = true;

                // When building an ark piece, a dust cloud should appear.
                std::shared_ptr<GRAPHICS::Texture> dust_cloud_texture = Assets->GetTexture(RESOURCES::DUST_CLOUD_TEXTURE_ID);
                assert(dust_cloud_texture);
                OBJECTS::DustCloud dust_cloud(dust_cloud_texture);

                // The dust cloud should be positioned over the ark piece.
                MATH::Vector2f dust_cloud_center_world_position = ark_piece->Sprite.GetWorldPosition();
                dust_cloud.Sprite.SetWorldPosition(dust_cloud_center_world_position);

                // The dust cloud should start animating immediately.
                dust_cloud.Sprite.Play();

                // The dust cloud needs to be added to the tile map so that it gets updated.
                tile_map_underneath_noah->DustClouds.push_back(dust_cloud);

                /// @todo   Play sound effect when building ark piece.
            }
        }
        else
        {
            // STOP NOAH'S ANIMATION FROM PLAYING SINCE THE PLAYER DIDN'T MOVE THIS FRAME.
            Overworld->NoahPlayer->Sprite.ResetAnimation();
        }

        // UPDATE THE CAMERA BASED ON SCROLLING.
        if (camera.IsScrolling)
        {
            // SCROLL BASED ON THE ELAPSED FRAME TIME.
            camera.Scroll(elapsed_time);

            // CHECK IF SCROLLING HAS FINISHED.
            bool scrolling_finished = !camera.IsScrolling;
            if (scrolling_finished)
            {
                // RE-ENABLE PLAYER INPUT.
                input_controller.EnableInput();
            }
        }
        else
        {
            // POSITION THE CAMERA TO FOCUS ON THE CENTER OF THE CURRENT TILE MAP.
            MATH::Vector2f center_world_position = current_tile_map->GetCenterWorldPosition();
            camera.SetCenter(center_world_position);
        }

        // HANDLE OTHER COLLISIONS.
        COLLISION::CollisionDetectionAlgorithms::HandleAxeSwings(*Overworld, Overworld->AxeSwings, *Assets);
        for (auto wood_logs = current_tile_map->WoodLogs.begin(); wood_logs != current_tile_map->WoodLogs.end();)
        {
            // CHECK IF THE WOOD LOGS INTERSECT WITH NOAH.
            MATH::FloatRectangle wood_log_bounding_box = wood_logs->GetWorldBoundingBox();
            MATH::FloatRectangle noah_bounding_box = Overworld->NoahPlayer->GetWorldBoundingBox();
            bool noah_collided_with_wood_logs = noah_bounding_box.Contains(
                wood_log_bounding_box.GetCenterXPosition(),
                wood_log_bounding_box.GetCenterYPosition());
            if (noah_collided_with_wood_logs)
            {
                // ADD THE WOOD TO NOAH'S INVENTORY.
                // The logs can have a random amount of wood.
                unsigned int MIN_WOOD_COUNT = 1;
                unsigned int MAX_WOOD_COUNT = 3;
                unsigned int random_number_for_wood = RandomNumberGenerator();
                unsigned int random_wood_count = (random_number_for_wood % MAX_WOOD_COUNT) + MIN_WOOD_COUNT;
                Overworld->NoahPlayer->Inventory->AddWood(random_wood_count);

                // REMOVE THE WOOD LOGS SINCE THEY'VE BEEN COLLECTED BY NOAH.
                wood_logs = current_tile_map->WoodLogs.erase(wood_logs);

                // SEE IF A BIBLE VERSE SHOULD BE COLLECTED ALONG WITH THE WOOD.
                // There should be a random chance that a Bible verse can be collected.
                const unsigned int EVENLY_DIVISIBLE = 0;
                const unsigned int BIBLE_VERSE_EXISTS_IF_DIVISIBLE_BY_THIS = 2;
                unsigned int random_number_for_bible_verse = RandomNumberGenerator();
                bool bible_verse_exists_with_wood = ((random_number_for_bible_verse % BIBLE_VERSE_EXISTS_IF_DIVISIBLE_BY_THIS) == EVENLY_DIVISIBLE);
                if (bible_verse_exists_with_wood)
                {
                    // CHECK IF ANY BIBLE VERSES REMAIN.
                    // This check helps protect against a mod by 0 below.
                    bool bible_verses_remain_to_be_found = !BibleVersesLeftToFind.empty();
                    if (bible_verses_remain_to_be_found)
                    {
                        // PLAY THE SOUND EFFECT FOR COLLECTING A BIBLE VERSE.
                        std::shared_ptr<AUDIO::SoundEffect> collected_bible_verse_sound = Assets->GetSound(RESOURCES::COLLECT_BIBLE_VERSE_SOUND_ID);
                        bool collect_bible_verse_sound_loaded = (nullptr != collected_bible_verse_sound);
                        if (collect_bible_verse_sound_loaded)
                        {
                            collected_bible_verse_sound->Play();
                        }

                        // SELECT A RANDOM BIBLE VERSE.
                        unsigned int random_bible_verse_index = RandomNumberGenerator() % BibleVersesLeftToFind.size();
                        auto bible_verse = BibleVersesLeftToFind.begin() + random_bible_verse_index;

                        // ADD THE BIBLE VERSE TO THE PLAYER'S INVENTORY.
                        Overworld->NoahPlayer->Inventory->BibleVerses.insert(*bible_verse);

                        // POPULATE THE MESSAGE TO DISPLAY IN THE MAIN TEXT BOX.
                        message_for_text_box = "You got a Bible verse!\n" + bible_verse->ToString();

                        // REMOVE THE VERSE SINCE IT HAS BEEN FOUND.
                        BibleVersesLeftToFind.erase(bible_verse);
                    }
                }
            }
            else
            {
                // MOVE TO CHECKING COLLISIONS WITH THE NEXT SET OF WOOD LOGS.
                ++wood_logs;
            }
        }
    }
void Drawable::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
{
    if (debug && IsEnabledEffective())
        debug->AddBoundingBox(GetWorldBoundingBox(), Color::GREEN, depthTest);
}
Beispiel #28
0
/// Gets the height of the sprite, in pixels.
/// @return The height of the sprite.
float Sprite::GetHeightInPixels() const
{
    MATH::FloatRectangle bounding_box = GetWorldBoundingBox();
    float height = bounding_box.GetHeight();
    return height;
}