/**
     * @return  @c true if the ray passes @a bspLeaf; otherwise @c false.
     */
    bool crossBspLeaf(BspLeaf const &bspLeaf)
    {
        if(!bspLeaf.hasSubspace())
            return false;

        ConvexSubspace const &subspace = bspLeaf.subspace();

        // Check polyobj lines.
        LoopResult blocked = subspace.forAllPolyobjs([this] (Polyobj &pob)
        {
            for(Line *line : pob.lines())
            {
                if(!crossLine(line->front()))
                    return LoopAbort;
            }
            return LoopContinue;
        });
        if(blocked) return false;

        // Check lines for the edges of the subspace geometry.
        HEdge *base = subspace.poly().hedge();
        HEdge *hedge = base;
        do
        {
            if(hedge->hasMapElement())
            {
                if(!crossLine(hedge->mapElementAs<LineSideSegment>().lineSide()))
                    return false;
            }
        } while((hedge = &hedge->next()) != base);

        // Check lines for the extra meshes.
        blocked = subspace.forAllExtraMeshes([this] (Mesh &mesh)
        {
            for(HEdge *hedge : mesh.hedges())
            {
                // Is this on the back of a one-sided line?
                if(!hedge->hasMapElement())
                    continue;

                if(!crossLine(hedge->mapElementAs<LineSideSegment>().lineSide()))
                    return LoopAbort;
            }
            return LoopContinue;
        });

        return !blocked;
    }
Beispiel #2
0
/**
 * Interpret vlights from glowing planes at the @a origin in the specfified
 * @a bspleaf and add them to the identified list.
 */
static void lightWithPlaneGlows(Vector3d const &origin, BspLeaf &bspLeaf, uint listIdx)
{
    SectorCluster &cluster = bspLeaf.cluster();
    for(int i = 0; i < cluster.sector().planeCount(); ++i)
    {
        Plane &plane     = cluster.visPlane(i);
        Surface &surface = plane.surface();

        // Glowing at this moment?
        Vector3f glowColor;
        float intensity = surface.glow(glowColor);
        if(intensity < .05f)
            continue;

        coord_t glowHeight = Rend_PlaneGlowHeight(intensity);
        if(glowHeight < 2)
            continue; // Not too small!

        // In front of the plane?
        Vector3d pointOnPlane = Vector3d(cluster.center(), plane.heightSmoothed());
        double dist = (origin - pointOnPlane).dot(surface.normal());
        if(dist < 0)
            continue;

        intensity *= 1 - dist / glowHeight;
        if(intensity < .05f)
            continue;

        Vector3f color = Rend_LuminousColor(glowColor, intensity);

        if(color != Vector3f(0, 0, 0))
        {
            ListNode *node = newVLight();
            VectorLight *vlight = &node->vlight;

            vlight->direction  = Vector3f(surface.normal().x, surface.normal().y, -surface.normal().z);
            vlight->color      = color;
            vlight->affectedByAmbient = true;
            vlight->approxDist = dist;
            vlight->lightSide  = 1;
            vlight->darkSide   = 0;
            vlight->offset     = .3f;

            linkNodeInList(node, listIdx);
        }
    }
}
Beispiel #3
0
    void addNeighborIntercepts(coord_t bottom, coord_t top)
    {
        ClockDirection const direction = edge? Clockwise : Anticlockwise;

        HEdge *hedge = wallHEdge;
        while((hedge = &SectorClusterCirculator::findBackNeighbor(*hedge, direction)) != wallHEdge)
        {
            // Stop if there is no back cluster.
            BspLeaf *backLeaf = hedge->hasFace()? &hedge->face().mapElementAs<BspLeaf>() : 0;
            if(!backLeaf || !backLeaf->hasCluster())
                break;

            SectorCluster &cluster = backLeaf->cluster();
            if(cluster.hasWorldVolume())
            {
                for(int i = 0; i < cluster.visPlaneCount(); ++i)
                {
                    Plane const &plane = cluster.visPlane(i);

                    if(plane.heightSmoothed() > bottom && plane.heightSmoothed() < top)
                    {
                        ddouble distance = distanceTo(plane.heightSmoothed());
                        if(!haveEvent(distance))
                        {
                            createEvent(distance);

                            // Have we reached the div limit?
                            if(interceptCount() == WALLEDGE_MAX_INTERCEPTS)
                                return;
                        }
                    }

                    // Clip a range bound to this height?
                    if(plane.isSectorFloor() && plane.heightSmoothed() > bottom)
                        bottom = plane.heightSmoothed();
                    else if(plane.isSectorCeiling() && plane.heightSmoothed() < top)
                        top = plane.heightSmoothed();

                    // All clipped away?
                    if(bottom >= top)
                        return;
                }
            }
            else
            {
                /*
                 * A neighbor with zero volume is a special case -- the potential
                 * division is at the height of the back ceiling. This is because
                 * elsewhere we automatically fix the case of a floor above a
                 * ceiling by lowering the floor.
                 */
                coord_t z = cluster.visCeiling().heightSmoothed();

                if(z > bottom && z < top)
                {
                    ddouble distance = distanceTo(z);
                    if(!haveEvent(distance))
                    {
                        createEvent(distance);
                        // All clipped away.
                        return;
                    }
                }
            }
        }
    }