Esempio n. 1
0
void blInteriorProxy::addToShadowVolume(ShadowVolumeBSP * shadowVolume, LightInfo * light, S32 level)
{
    if(light->getType() != LightInfo::Vector)
        return;

    ColorF ambient = light->getAmbient();

    bool shadowedTree = true;

    InteriorInstance* interior = dynamic_cast<InteriorInstance*>(getObject());
    if (!interior)
        return;
    Resource<InteriorResource> mInteriorRes = interior->getResource();

    // check if just getting shadow detail
    if(level == SceneLighting::SHADOW_DETAIL)
    {
        shadowedTree = false;
        level = mInteriorRes->getNumDetailLevels() - 1;
    }

    Interior * detail = mInteriorRes->getDetailLevel(level);
    bool hasAlarm = detail->hasAlarmState();

    // make sure surfaces do not get processed more than once
    BitVector surfaceProcessed;
    surfaceProcessed.setSize(detail->mSurfaces.size());
    surfaceProcessed.clear();

    ColorI color = light->getAmbient();

    // go through the zones of the interior and grab outside visible surfaces
    for(U32 i = 0; i < detail->getNumZones(); i++)
    {
        Interior::Zone & zone = detail->mZones[i];
        for(U32 j = 0; j < zone.surfaceCount; j++)
        {
            U32 surfaceIndex = detail->mZoneSurfaces[zone.surfaceStart + j];

            // dont reprocess a surface
            if(surfaceProcessed.test(surfaceIndex))
                continue;
            surfaceProcessed.set(surfaceIndex);

            Interior::Surface & surface = detail->mSurfaces[surfaceIndex];

            // outside visible?
            if(!(surface.surfaceFlags & Interior::SurfaceOutsideVisible))
                continue;

            // good surface?
            PlaneF plane = detail->getPlane(surface.planeIndex);
            if(Interior::planeIsFlipped(surface.planeIndex))
                plane.neg();

            // project the plane
            PlaneF projPlane;
            mTransformPlane(interior->getTransform(), interior->getScale(), plane, &projPlane);

            // fill with ambient? (need to do here, because surface will not be
            // added to the SVBSP tree)
            F32 dot = mDot(projPlane, light->getDirection());
            if(dot > -gParellelVectorThresh)// && !(GFX->getPixelShaderVersion() > 0.0) )
            {
                if(shadowedTree)
                {
                    // alarm lighting
                    GFXTexHandle normHandle = gInteriorLMManager.duplicateBaseLightmap(detail->getLMHandle(), interior->getLMHandle(), detail->getNormalLMapIndex(surfaceIndex));
                    GFXTexHandle alarmHandle;

                    GBitmap * normLightmap = normHandle->getBitmap();
                    GBitmap * alarmLightmap = 0;

                    // check if they share the lightmap
                    if(hasAlarm)
                    {
                        if(detail->getNormalLMapIndex(surfaceIndex) != detail->getAlarmLMapIndex(surfaceIndex))
                        {
                            alarmHandle = gInteriorLMManager.duplicateBaseLightmap(detail->getLMHandle(), interior->getLMHandle(), detail->getAlarmLMapIndex(surfaceIndex));
                            alarmLightmap = alarmHandle->getBitmap();
                        }
                    }

                    //
                    // Support for interior light map border sizes.
                    //
                    U32 xlen, ylen, xoff, yoff;
                    U32 lmborder = detail->getLightMapBorderSize();
                    xlen = surface.mapSizeX + (lmborder * 2);
                    ylen = surface.mapSizeY + (lmborder * 2);
                    xoff = surface.mapOffsetX - lmborder;
                    yoff = surface.mapOffsetY - lmborder;

                    // attemp to light normal and alarm lighting
                    for(U32 c = 0; c < 2; c++)
                    {
                        GBitmap * lightmap = (c == 0) ? normLightmap : alarmLightmap;
                        if(!lightmap)
                            continue;

                        // fill it
                        for(U32 y = 0; y < ylen; y++)
                        {
                            for(U32 x = 0; x < xlen; x++)
                            {
                                ColorI outColor(255, 0, 0, 255);

#ifndef SET_COLORS
                                ColorI lmColor(0, 0, 0, 255);
                                lightmap->getColor(xoff + x, yoff + y, lmColor);

                                U32 _r = static_cast<U32>( color.red ) + static_cast<U32>( lmColor.red );
                                U32 _g = static_cast<U32>( color.green ) + static_cast<U32>( lmColor.green );
                                U32 _b = static_cast<U32>( color.blue ) + static_cast<U32>( lmColor.blue );

                                outColor.red   = mClamp(_r, 0, 255);
                                outColor.green = mClamp(_g, 0, 255);
                                outColor.blue  = mClamp(_b, 0, 255);
#endif

                                lightmap->setColor(xoff + x, yoff + y, outColor);
                            }
                        }
                    }
                }
                continue;
            }

            ShadowVolumeBSP::SVPoly * poly = buildInteriorPoly(shadowVolume, detail,
                                             surfaceIndex, light, shadowedTree);

            // insert it into the SVBSP tree
            shadowVolume->insertPoly(poly);
        }
    }
}
Esempio n. 2
0
ShadowVolumeBSP::SVPoly * blInteriorProxy::buildInteriorPoly(ShadowVolumeBSP * shadowVolumeBSP,
        Interior * detail, U32 surfaceIndex, LightInfo * light,
        bool createSurfaceInfo)
{
    InteriorInstance* interior = dynamic_cast<InteriorInstance*>(getObject());
    if (!interior)
        return NULL;

    // transform and add the points...
    const MatrixF & transform = interior->getTransform();
    const VectorF & scale = interior->getScale();

    const Interior::Surface & surface = detail->mSurfaces[surfaceIndex];

    ShadowVolumeBSP::SVPoly * poly = shadowVolumeBSP->createPoly();

    poly->mWindingCount = surface.windingCount;

    // project these points
    for(U32 j = 0; j < poly->mWindingCount; j++)
    {
        Point3F iPnt = detail->mPoints[detail->mWindings[surface.windingStart + j]].point;
        Point3F tPnt;
        iPnt.convolve(scale);
        transform.mulP(iPnt, &tPnt);
        poly->mWinding[j] = tPnt;
    }

    // convert from fan
    U32 tmpIndices[ShadowVolumeBSP::SVPoly::MaxWinding];
    Point3F fanIndices[ShadowVolumeBSP::SVPoly::MaxWinding];

    tmpIndices[0] = 0;

    U32 idx = 1;
    U32 i;
    for(i = 1; i < poly->mWindingCount; i += 2)
        tmpIndices[idx++] = i;
    for(i = ((poly->mWindingCount - 1) & (~0x1)); i > 0; i -= 2)
        tmpIndices[idx++] = i;

    idx = 0;
    for(i = 0; i < poly->mWindingCount; i++)
        if(surface.fanMask & (1 << i))
            fanIndices[idx++] = poly->mWinding[tmpIndices[i]];

    // set the data
    poly->mWindingCount = idx;
    for(i = 0; i < poly->mWindingCount; i++)
        poly->mWinding[i] = fanIndices[i];

    // flip the plane - shadow volumes face inwards
    PlaneF plane = detail->getPlane(surface.planeIndex);
    if(!Interior::planeIsFlipped(surface.planeIndex))
        plane.neg();

    // transform the plane
    mTransformPlane(transform, scale, plane, &poly->mPlane);
    shadowVolumeBSP->buildPolyVolume(poly, light);

    // do surface info?
    if(createSurfaceInfo)
    {
        ShadowVolumeBSP::SurfaceInfo * surfaceInfo = new ShadowVolumeBSP::SurfaceInfo;
        shadowVolumeBSP->mSurfaces.push_back(surfaceInfo);

        // fill it
        surfaceInfo->mSurfaceIndex = surfaceIndex;
        surfaceInfo->mShadowVolume = shadowVolumeBSP->getShadowVolume(poly->mShadowVolume);

        // POLY and POLY node gets it too
        ShadowVolumeBSP::SVNode * traverse = shadowVolumeBSP->getShadowVolume(poly->mShadowVolume);
        while(traverse->mFront)
        {
            traverse->mSurfaceInfo = surfaceInfo;
            traverse = traverse->mFront;
        }

        // get some info from the poly node
        poly->mSurfaceInfo = traverse->mSurfaceInfo = surfaceInfo;
        surfaceInfo->mPlaneIndex = traverse->mPlaneIndex;
    }

    return(poly);
}