Exemplo n.º 1
0
static int drawCellSubspaces(Blockmap const &bmap, BlockmapCell const &cell, void *)
{
    bmap.forAllInCell(cell, [] (void *object)
    {
        ConvexSubspace *sub = (ConvexSubspace *)object;
        if(sub->validCount() != validCount)
        {
            sub->setValidCount(validCount);
            drawSubspace(*sub);
        }
        return LoopContinue;
    });
    return false; // Continue iteration.
}
Exemplo n.º 2
0
static void drawSubspace(ConvexSubspace const &subspace)
{
    float const scale = de::max(bmapDebugSize, 1.f);
    float const width = (DENG_GAMEVIEW_WIDTH / 16) / scale;

    Face const &poly = subspace.poly();
    HEdge *base = poly.hedge();
    HEdge *hedge = base;
    do
    {
        Vector2d start = hedge->origin();
        Vector2d end   = hedge->twin().origin();

        glBegin(GL_LINES);
            glVertex2f(start.x, start.y);
            glVertex2f(end.x, end.y);
        glEnd();

        ddouble length = (end - start).length();
        if(length > 0)
        {
            Vector2d const unit = (end - start) / length;
            Vector2d const normal(-unit.y, unit.x);

            GL_BindTextureUnmanaged(GL_PrepareLSTexture(LST_DYNAMIC));
            glEnable(GL_TEXTURE_2D);
            GL_BlendMode(BM_ADD);

            glBegin(GL_QUADS);
                glTexCoord2f(0.75f, 0.5f);
                glVertex2f(start.x, start.y);
                glTexCoord2f(0.75f, 0.5f);
                glVertex2f(end.x, end.y);
                glTexCoord2f(0.75f, 1);
                glVertex2f(end.x - normal.x * width, end.y - normal.y * width);
                glTexCoord2f(0.75f, 1);
                glVertex2f(start.x - normal.x * width, start.y - normal.y * width);
            glEnd();

            glDisable(GL_TEXTURE_2D);
            GL_BlendMode(BM_NORMAL);
        }

        // Draw a bounding box for the leaf's face geometry.
        start = Vector2d(poly.aaBox().minX, poly.aaBox().minY);
        end   = Vector2d(poly.aaBox().maxX, poly.aaBox().maxY);

        glBegin(GL_LINES);
            glVertex2f(start.x, start.y);
            glVertex2f(  end.x, start.y);
            glVertex2f(  end.x, start.y);
            glVertex2f(  end.x,   end.y);
            glVertex2f(  end.x,   end.y);
            glVertex2f(start.x,   end.y);
            glVertex2f(start.x,   end.y);
            glVertex2f(start.x, start.y);
        glEnd();

    } while((hedge = &hedge->next()) != base);
}
Exemplo n.º 3
0
    /**
     * @return  @c true if the ray passes @a subspace; otherwise @c false.
     */
    bool crossSubspace(ConvexSubspace const &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;
    }
Exemplo n.º 4
0
    /**
     * Attempt to spread the obj from the given contact from the source subspace
     * and into the (relative) back subsapce.
     *
     * @param subspace  Convex subspace to attempt to spread over to.
     *
     * @return  Always @c true. (This function is also used as an iterator.)
     */
    void spreadInSubspace(ConvexSubspace &subspace)
    {
        HEdge *base = subspace.poly().hedge();
        HEdge *hedge = base;
        do
        {
            maybeSpreadOverEdge(hedge);

        } while((hedge = &hedge->next()) != base);
    }
Exemplo n.º 5
0
static void evaluateLighting(Vector3d const &origin, ConvexSubspace &subspaceAtOrigin,
                             coord_t distToEye, bool fullbright, Vector4f &ambientColor, duint *vLightListIdx)
{
    if(fullbright)
    {
        ambientColor = Vector3f(1, 1, 1);
        *vLightListIdx = 0;
    }
    else
    {
        SectorCluster &cluster = subspaceAtOrigin.cluster();
        Map &map = cluster.sector().map();

        if(useBias && map.hasLightGrid())
        {
            // Evaluate the position in the light grid.
            Vector4f color = map.lightGrid().evaluate(origin);
            // Apply light range compression.
            for(dint i = 0; i < 3; ++i)
            {
                color[i] += Rend_LightAdaptationDelta(color[i]);
            }
            ambientColor = color;
        }
        else
        {
            Vector4f const color = cluster.lightSourceColorfIntensity();

            dfloat lightLevel = color.w;
            /* if(spr->type == VSPR_DECORATION)
            {
                // Wall decorations receive an additional light delta.
                lightLevel += R_WallAngleLightLevelDelta(line, side);
            } */

            // Apply distance attenuation.
            lightLevel = Rend_AttenuateLightLevel(distToEye, lightLevel);

            // Add extra light.
            lightLevel = de::clamp(0.f, lightLevel + Rend_ExtraLightDelta(), 1.f);

            Rend_ApplyLightAdaptation(lightLevel);

            // Determine the final color.
            ambientColor = color * lightLevel;
        }
        Rend_ApplyTorchLight(ambientColor, distToEye);

        *vLightListIdx = Rend_CollectAffectingLights(origin, ambientColor, &subspaceAtOrigin);
    }
}
Exemplo n.º 6
0
void Rend_DrawFlatRadio(ConvexSubspace const &subspace)
{
    // Disabled?
    if(!::rendFakeRadio || ::levelFullBright) return;

    // If no shadow-casting lines are linked we no work to do.
    if(!subspace.shadowLineCount()) return;

    auto const &subsec = subspace.subsector().as<world::ClientSubsector>();

    // Determine the shadow properties.
    dfloat const shadowDark = calcShadowDarkness(subsec.lightSourceIntensity());
    if(shadowDark < MIN_SHADOW_DARKNESS)
        return;

    static DrawList::Indices indices;
    static ShadowEdge shadowEdges[2/*left, right*/];  // Keep these around (needed often).

    // Can skip drawing for Planes that do not face the viewer - find the 2D vector to subspace center.
    auto const eyeToSubspace = Vector2f(Rend_EyeOrigin().xz() - subspace.poly().center());

    // All shadow geometry uses the same texture (i.e., none) - use the same list.
    DrawList &shadowList = ClientApp::renderSystem().drawLists().find(
#if defined (DENG_OPENGL)
        DrawListSpec(renderWireframe? UnlitGeom : ShadowGeom)
#else
        DrawListSpec(ShadowGeom)
#endif
    );

    // Process all LineSides linked to this subspace as potential shadow casters.
    subspace.forAllShadowLines([&subsec, &shadowDark, &eyeToSubspace, &shadowList] (LineSide &side)
    {
        DENG2_ASSERT(side.hasSections() && !side.line().definesPolyobj() && side.leftHEdge());

        // Process each only once per frame (we only want to draw a shadow set once).
        if(side.shadowVisCount() != R_FrameCount())
        {
            side.setShadowVisCount(R_FrameCount());  // Mark processed.

            for (dint pln = 0; pln < subsec.visPlaneCount(); ++pln)
            {
                Plane const &plane = subsec.visPlane(pln);

                // Skip Planes which should not receive FakeRadio shadowing.
                if (!plane.receivesShadow()) continue;

                // Skip Planes facing away from the viewer.
                if (Vector3f(eyeToSubspace, Rend_EyeOrigin().y - plane.heightSmoothed())
                         .dot(plane.surface().normal()) >= 0)
                {
                    HEdge const *hEdges[2/*left, right*/] = { side.leftHEdge(), side.leftHEdge() };

                    if (prepareFlatShadowEdges(shadowEdges, hEdges, pln, shadowDark))
                    {
                        bool const haveFloor = plane.surface().normal()[2] > 0;

                        // Build geometry.
                        Store &buffer = ClientApp::renderSystem().buffer();
                        gl::Primitive primitive;
                        uint vertCount = makeFlatShadowGeometry(indices, buffer, primitive, shadowEdges, shadowDark, haveFloor);

                        // Skip drawing entirely?
                        if (::rendFakeRadio == 2) continue;

                        // Write the geometry.
                        shadowList.write(buffer, indices.constData(), vertCount, primitive);
                    }
                }
            }
        }
        return LoopContinue;
    });
}
Exemplo n.º 7
0
    void updateDecorations(Surface &suf, MaterialAnimator &matAnimator,
        Vector2f const &materialOrigin, Vector3d const &topLeft,
        Vector3d const &bottomRight, Sector *containingSector = nullptr)
    {
        Vector3d delta = bottomRight - topLeft;
        if(de::fequal(delta.length(), 0)) return;

        Material &material = matAnimator.material();
        int const axis = suf.normal().maxAxis();

        Vector2d sufDimensions;
        if(axis == 0 || axis == 1)
        {
            sufDimensions.x = std::sqrt(de::squared(delta.x) + de::squared(delta.y));
            sufDimensions.y = delta.z;
        }
        else
        {
            sufDimensions.x = std::sqrt(de::squared(delta.x));
            sufDimensions.y = delta.y;
        }

        if(sufDimensions.x < 0) sufDimensions.x = -sufDimensions.x;
        if(sufDimensions.y < 0) sufDimensions.y = -sufDimensions.y;

        // Generate a number of decorations.
        int decorIndex = 0;

        material.forAllDecorations([&suf, &matAnimator, &materialOrigin
                                   , &topLeft, &bottomRight, &containingSector
                                   , &delta, &axis, &sufDimensions, &decorIndex]
                                   (MaterialDecoration &decor)
        {
            Vector2i const &matDimensions               = matAnimator.material().dimensions();
            MaterialAnimator::Decoration const &decorSS = matAnimator.decoration(decorIndex);

            // Skip values must be at least one.
            Vector2i skip = Vector2i(decor.patternSkip().x + 1, decor.patternSkip().y + 1)
                                .max(Vector2i(1, 1));

            Vector2f repeat = matDimensions * skip;
            if(repeat == Vector2f(0, 0))
                return LoopAbort;

            Vector3d origin = topLeft + suf.normal() * decorSS.elevation();

            float s = de::wrap(decorSS.origin().x - matDimensions.x * decor.patternOffset().x + materialOrigin.x,
                               0.f, repeat.x);

            // Plot decorations.
            for(; s < sufDimensions.x; s += repeat.x)
            {
                // Determine the topmost point for this row.
                float t = de::wrap(decorSS.origin().y - matDimensions.y * decor.patternOffset().y + materialOrigin.y,
                                   0.f, repeat.y);

                for(; t < sufDimensions.y; t += repeat.y)
                {
                    float const offS = s / sufDimensions.x;
                    float const offT = t / sufDimensions.y;
                    Vector3d patternOffset(offS, axis == VZ? offT : offS, axis == VZ? offS : offT);

                    Vector3d decorOrigin     = origin + delta * patternOffset;
                    ConvexSubspace *subspace = suf.map().bspLeafAt(decorOrigin).subspacePtr();

                    if(!subspace) continue;
                    if(!subspace->contains(decorOrigin)) continue;

                    if(containingSector)
                    {
                        // The point must be in the correct sector.
                        if(containingSector != &subspace->sector())
                            continue;
                    }

                    suf.addDecoration(new LightDecoration(decorSS, decorOrigin));
                }
            }

            decorIndex += 1;
            return LoopContinue;
        });
    }