Esempio n. 1
0
void TerrainConvex::getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf)
{
   U32 i;
   cf->material = 0;
   cf->object = mObject;

   // Plane is normal n + support point
   PlaneF plane;
   plane.set(support(n),n);
   S32 vertexCount = cf->mVertexList.size();

   // Emit vertices on the plane
   S32* vertexListPointer;
   if (halfA)
      vertexListPointer = square ? sVertexList[(split45 << 1) | 1]: sVertexList[4];
   else
      vertexListPointer = square ? sVertexList[(split45 << 1)]    : sVertexList[4];

   S32 pm = 0;
   S32 numVerts = *vertexListPointer;
   vertexListPointer += 1;
   for (i = 0; i < numVerts; i++)
   {
      Point3F& cp = point[vertexListPointer[i]];
      cf->mVertexList.increment();
      mat.mulP(cp,&cf->mVertexList.last());
      pm |= 1 << vertexListPointer[i];
   }

   // Emit Edges
   S32* ep = (square && halfA)?
      (split45 ? sEdgeList45A[pm]: sEdgeList135A[pm]):
      (split45 ? sEdgeList45[pm]: sEdgeList135[pm]);

   S32 numEdges = *ep;
   S32 edgeListStart = cf->mEdgeList.size();
   cf->mEdgeList.increment(numEdges);
   ep += 1;
   for (i = 0; i < numEdges; i++)
   {
      cf->mEdgeList[edgeListStart + i].vertex[0] = vertexCount + ep[i * 2 + 0];
      cf->mEdgeList[edgeListStart + i].vertex[1] = vertexCount + ep[i * 2 + 1];
   }

   // Emit faces
   S32* fp = split45 ? sFaceList45[pm]: sFaceList135[pm];
   S32 numFaces = *fp;
   fp += 1;
   S32 faceListStart = cf->mFaceList.size();
   cf->mFaceList.increment(numFaces);
   for (i = 0; i < numFaces; i++)
   {
      cf->mFaceList[faceListStart + i].normal    = normal[fp[i * 4 + 0]];
      cf->mFaceList[faceListStart + i].vertex[0] = vertexCount + fp[i * 4 + 1];
      cf->mFaceList[faceListStart + i].vertex[1] = vertexCount + fp[i * 4 + 2];
      cf->mFaceList[faceListStart + i].vertex[2] = vertexCount + fp[i * 4 + 3];
   }
}
Esempio n. 2
0
inline SceneZoneCullingState::CullingTestResult SceneCullingState::_test( const T& bounds, Iter zoneIter,
                                                                          const PlaneF& nearPlane, const PlaneF& farPlane ) const
{
   // Defer test of near and far plane until we've hit a zone
   // which actually has visible space.  This prevents us from
   // doing near/far tests on objects that were included in the
   // potential render list but aren't actually in any visible
   // zone.
   bool haveTestedNearAndFar = false;

   // Test the culling states of all zones that the object
   // is assigned to.

   for( ; zoneIter.isValid(); ++ zoneIter )
   {
      const SceneZoneCullingState& zoneState = getZoneState( *zoneIter );

      // Skip zone if there are no positive culling volumes.

      if( !zoneState.hasIncluders() )
         continue;

      // If we haven't tested the near and far plane yet, do so
      // now.

      if( !haveTestedNearAndFar )
      {
         // Test near plane.

         PlaneF::Side nearSide = nearPlane.whichSide( bounds );
         if( nearSide == PlaneF::Back )
            return SceneZoneCullingState::CullingTestNegative;

         // Test far plane.

         PlaneF::Side farSide = farPlane.whichSide( bounds );
         if( farSide == PlaneF::Back )
            return SceneZoneCullingState::CullingTestNegative;

         haveTestedNearAndFar = true;
      }

      // If the object's world bounds overlaps any of the volumes
      // for this zone, it's rendered.

      SceneZoneCullingState::CullingTestResult result = zoneState.testVolumes( bounds );

      if( result == SceneZoneCullingState::CullingTestPositiveByInclusion )
         return result;
      else if( result == SceneZoneCullingState::CullingTestPositiveByOcclusion )
         return result;
   }

   return SceneZoneCullingState::CullingTestNegative;
}
ShadowVolumeBSP::SVNode::Side ShadowVolumeBSP::whichSide(SVPoly * poly, const PlaneF & plane) const
{
    bool front = false;
    bool back = false;

    for(U32 i = 0; i < poly->mWindingCount; i++)
    {
        switch(plane.whichSide(poly->mWinding[i]))
        {
        case PlaneF::Front:
            if(back)
                return(SVNode::Split);
            front = true;
            break;

        case PlaneF::Back:
            if(front)
                return(SVNode::Split);
            back = true;
            break;

        default:
            break;
        }
    }

    AssertFatal(!(front && back), "ShadowVolumeBSP::whichSide - failed to classify poly");

    if(!front && !back)
        return(SVNode::On);

    return(front ? SVNode::Front : SVNode::Back);
}
Esempio n. 4
0
void BoxConvex::getFeatures(const MatrixF& mat,const VectorF& n, ConvexFeature* cf)
{
   cf->material = 0;
   cf->object = mObject;

   S32 v = 0;
   v += (n.x >= 0)? 1: 0;
   v += (n.y >= 0)? 2: 0;
   v += (n.z >= 0)? 4: 0;

   PlaneF plane;
   plane.set(getVertex(v),n);

   // Emit vertex and edge
   S32 mask = 0;
   Corner& corner = sCorner[v];
   mask |= isOnPlane(getVertex(corner.a),plane)? 1: 0;
   mask |= isOnPlane(getVertex(corner.b),plane)? 2: 0;
   mask |= isOnPlane(getVertex(corner.c),plane)? 4: 0;

   switch(mask) {
      case 0: {
         cf->mVertexList.increment();
         mat.mulP(getVertex(v),&cf->mVertexList.last());
         break;
      }
      case 1:
         emitEdge(v,corner.a,mat,cf);
         break;
      case 2:
         emitEdge(v,corner.b,mat,cf);
         break;
      case 4:
         emitEdge(v,corner.c,mat,cf);
         break;
      case 1 | 2:
         emitFace(corner.ab,mat,cf);
         break;
      case 2 | 4:
         emitFace(corner.bc,mat,cf);
         break;
      case 1 | 4:
         emitFace(corner.ac,mat,cf);
         break;
   }
}
Esempio n. 5
0
bool TerrainBlock::castRayBlock(const Point3F &pStart, const Point3F &pEnd, const Point2I &aBlockPos, U32 aLevel, F32 invDeltaX, F32 invDeltaY, F32 aStartT, F32 aEndT, RayInfo *info, bool collideEmpty)
{
   F32 invBlockSize = 1 / F32(BlockSquareWidth);

   static TerrLOSStackNode stack[BlockShift * 3 + 1];
   U32 stackSize = 1;

   stack[0].startT = aStartT;
   stack[0].endT = aEndT;
   stack[0].blockPos = aBlockPos;
   stack[0].level = aLevel;
   
   if(!mTile && !aBlockPos.isZero())
      return false;

   while(stackSize--)
   {
      TerrLOSStackNode *sn = stack + stackSize;
      U32 level  = sn->level;
      F32 startT = sn->startT;
      F32 endT   = sn->endT;
      Point2I blockPos = sn->blockPos;

      GridSquare *sq = findSquare(level, Point2I(blockPos.x & BlockMask, blockPos.y & BlockMask));

      F32 startZ = startT * (pEnd.z - pStart.z) + pStart.z;
      F32 endZ = endT * (pEnd.z - pStart.z) + pStart.z;

      F32 minHeight = fixedToFloat(sq->minHeight);
      if(startZ <= minHeight && endZ <= minHeight)
      {
         //drawLineTest(startT, sn->endT, false);
         continue;
      }
      F32 maxHeight = fixedToFloat(sq->maxHeight);
      if(startZ >= maxHeight && endZ >= maxHeight)
      {
         //drawLineTest(startT, endT, false);
         continue;
      }
      if (!collideEmpty && (sq->flags & GridSquare::Empty) &&
      	  blockPos.x == (blockPos.x & BlockMask) && blockPos.y == (blockPos.y & BlockMask))
      {
         //drawLineTest(startT, endT, false);
         continue;
      }
      if(level == 0)
      {
         F32 xs = blockPos.x * invBlockSize;
         F32 ys = blockPos.y * invBlockSize;

         F32 zBottomLeft = fixedToFloat(getHeight(blockPos.x, blockPos.y));
         F32 zBottomRight= fixedToFloat(getHeight(blockPos.x + 1, blockPos.y));
         F32 zTopLeft =    fixedToFloat(getHeight(blockPos.x, blockPos.y + 1));
         F32 zTopRight =   fixedToFloat(getHeight(blockPos.x + 1, blockPos.y + 1));

         PlaneF p1, p2;
         PlaneF divider;
         Point3F planePoint;

         if(sq->flags & GridSquare::Split45)
         {
            p1.set(zBottomLeft - zBottomRight, zBottomRight - zTopRight, invBlockSize);
            p2.set(zTopLeft - zTopRight, zBottomLeft - zTopLeft, invBlockSize);
            planePoint.set(xs, ys, zBottomLeft);
            divider.x = 1;
            divider.y = -1;
            divider.z = 0;
         }
         else
         {
            p1.set(zTopLeft - zTopRight, zBottomRight - zTopRight, invBlockSize);
            p2.set(zBottomLeft - zBottomRight, zBottomLeft - zTopLeft, invBlockSize);
            planePoint.set(xs + invBlockSize, ys, zBottomRight);
            divider.x = 1;
            divider.y = 1;
            divider.z = 0;
         }
         p1.setPoint(planePoint);
         p2.setPoint(planePoint);
         divider.setPoint(planePoint);

         F32 t1 = p1.intersect(pStart, pEnd);
         F32 t2 = p2.intersect(pStart, pEnd);
         F32 td = divider.intersect(pStart, pEnd);

         F32 dStart = divider.distToPlane(pStart);
         F32 dEnd = divider.distToPlane(pEnd);

         // see if the line crosses the divider
         if((dStart >= 0 && dEnd < 0) || (dStart < 0 && dEnd >= 0))
         {
            if(dStart < 0)
            {
               F32 temp = t1;
               t1 = t2;
               t2 = temp;
            }
            if(t1 >= startT && t1 && t1 <= td && t1 <= endT)
            {
               info->t = t1;
               info->normal = p1;
               return true;
            }
            if(t2 >= td && t2 >= startT && t2 <= endT)
            {
               info->t = t2;
               info->normal = p2;
               return true;
            }
         }
         else
         {
            F32 t;
            if(dStart >= 0) {
               t = t1;
               info->normal = p1;
            }
            else {
               t = t2;
               info->normal = p2;
            }
            if(t >= startT && t <= endT)
            {
               info->t = t;
               return true;
            }
         }
         continue;
      }
      int subSqWidth = 1 << (level - 1);
      F32 xIntercept = (blockPos.x + subSqWidth) * invBlockSize;
      F32 xInt = calcInterceptX(pStart.x, invDeltaX, xIntercept);
      F32 yIntercept = (blockPos.y + subSqWidth) * invBlockSize;
      F32 yInt = calcInterceptY(pStart.y, invDeltaY, yIntercept);

      F32 startX = startT * (pEnd.x - pStart.x) + pStart.x;
      F32 startY = startT * (pEnd.y - pStart.y) + pStart.y;

      if(xInt < startT)
         xInt = MAX_FLOAT;
      if(yInt < startT)
         yInt = MAX_FLOAT;

      U32 x0 = (startX > xIntercept) * subSqWidth;
      U32 y0 = (startY > yIntercept) * subSqWidth;
      U32 x1 = subSqWidth - x0;
      U32 y1 = subSqWidth - y0;
      U32 nextLevel = level - 1;

      // push the items on the stack in reverse order of processing
      if(xInt > endT && yInt > endT)
      {
         // only test the square the point started in:
         stack[stackSize].blockPos.set(blockPos.x + x0, blockPos.y + y0);
         stack[stackSize].level = nextLevel;
         stackSize++;
      }
      else if(xInt < yInt)
      {
         F32 nextIntersect = endT;
         if(yInt <= endT)
         {
            stack[stackSize].blockPos.set(blockPos.x + x1, blockPos.y + y1);
            stack[stackSize].startT = yInt;
            stack[stackSize].endT = endT;
            stack[stackSize].level = nextLevel;
            nextIntersect = yInt;
            stackSize++;
         }
         stack[stackSize].blockPos.set(blockPos.x + x1, blockPos.y + y0);
         stack[stackSize].startT = xInt;
         stack[stackSize].endT = nextIntersect;
         stack[stackSize].level = nextLevel;

         stack[stackSize+1].blockPos.set(blockPos.x + x0, blockPos.y + y0);
         stack[stackSize+1].startT = startT;
         stack[stackSize+1].endT = xInt;
         stack[stackSize+1].level = nextLevel;
         stackSize += 2;
      }
      else if(yInt < xInt)
      {
         F32 nextIntersect = endT;
         if(xInt <= endT)
         {
            stack[stackSize].blockPos.set(blockPos.x + x1, blockPos.y + y1);
            stack[stackSize].startT = xInt;
            stack[stackSize].endT = endT;
            stack[stackSize].level = nextLevel;
            nextIntersect = xInt;
            stackSize++;
         }
         stack[stackSize].blockPos.set(blockPos.x + x0, blockPos.y + y1);
         stack[stackSize].startT = yInt;
         stack[stackSize].endT = nextIntersect;
         stack[stackSize].level = nextLevel;

         stack[stackSize+1].blockPos.set(blockPos.x + x0, blockPos.y + y0);
         stack[stackSize+1].startT = startT;
         stack[stackSize+1].endT = yInt;
         stack[stackSize+1].level = nextLevel;
         stackSize += 2;
      }
      else
      {
         stack[stackSize].blockPos.set(blockPos.x + x1, blockPos.y + y1);
         stack[stackSize].startT = xInt;
         stack[stackSize].endT = endT;
         stack[stackSize].level = nextLevel;

         stack[stackSize+1].blockPos.set(blockPos.x + x0, blockPos.y + y0);
         stack[stackSize+1].startT = startT;
         stack[stackSize+1].endT = xInt;
         stack[stackSize+1].level = nextLevel;
         stackSize += 2;
      }
   }
   return false;
}
void ShadowVolumeBSP::splitPoly(SVPoly * poly, const PlaneF & plane, SVPoly ** front, SVPoly ** back)
{
    PlaneF::Side sides[SVPoly::MaxWinding];

    U32 i;
    for(i = 0; i < poly->mWindingCount; i++)
        sides[i] = plane.whichSide(poly->mWinding[i]);

    // create the polys
    (*front) = createPoly();
    (*back) = createPoly();

    // copy the info
    (*front)->mWindingCount = (*back)->mWindingCount = 0;
    (*front)->mPlane = (*back)->mPlane = poly->mPlane;
    (*front)->mTarget = (*back)->mTarget = poly->mTarget;
    (*front)->mSurfaceInfo = (*back)->mSurfaceInfo = poly->mSurfaceInfo;
    (*front)->mShadowVolume = (*back)->mShadowVolume = poly->mShadowVolume;

    //
    for(i = 0; i < poly->mWindingCount; i++)
    {
        U32 j = (i+1) % poly->mWindingCount;

        if(sides[i] == PlaneF::On)
        {
            (*front)->mWinding[(*front)->mWindingCount++] = poly->mWinding[i];
            (*back)->mWinding[(*back)->mWindingCount++] = poly->mWinding[i];
        }
        else if(sides[i] == PlaneF::Front)
        {
            (*front)->mWinding[(*front)->mWindingCount++] = poly->mWinding[i];

            if(sides[j] == PlaneF::Back)
            {
                const Point3F & a = poly->mWinding[i];
                const Point3F & b = poly->mWinding[j];

                F32 t = plane.intersect(a, b);
                AssertFatal(t >=0 && t <= 1, "ShadowVolumeBSP::splitPoly - bad plane intersection");

                Point3F pos;
                pos.interpolate(a, b, t);

                //
                (*front)->mWinding[(*front)->mWindingCount++] =
                    (*back)->mWinding[(*back)->mWindingCount++] = pos;
            }
        }
        else if(sides[i] == PlaneF::Back)
        {
            (*back)->mWinding[(*back)->mWindingCount++] = poly->mWinding[i];

            if(sides[j] == PlaneF::Front)
            {
                const Point3F & a = poly->mWinding[i];
                const Point3F & b = poly->mWinding[j];

                F32 t = plane.intersect(a, b);
                AssertFatal(t >=0 && t <= 1, "ShadowVolumeBSP::splitPoly - bad plane intersection");

                Point3F pos;
                pos.interpolate(a, b, t);

                (*front)->mWinding[(*front)->mWindingCount++] =
                    (*back)->mWinding[(*back)->mWindingCount++] = pos;
            }
        }
    }

    AssertFatal((*front)->mWindingCount && (*back)->mWindingCount, "ShadowVolume::split - invalid split");
}
Esempio n. 7
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. 8
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);
}
Esempio n. 9
0
void WaterPlane::_getWaterPlane( const Point3F &camPos, PlaneF &outPlane, Point3F &outPos )
{
   outPos = getPosition();   
   outPlane.set( outPos, Point3F(0,0,1) );   
}