//------------------------------------------------------------------------------
void ShadowVolumeBSP::clipPoly(SVNode * root, SVPoly ** store, SVPoly * poly)
{
    if(!root)
    {
        recyclePoly(poly);
        return;
    }

    const PlaneF & plane = getPlane(root->mPlaneIndex);

    switch(whichSide(poly, plane))
    {
    case SVNode::On:
    case SVNode::Back:
        if(root->mBack)
            clipPoly(root->mBack, store, poly);
        else
            addToPolyList(store, poly);
        break;

    case SVNode::Front:
        // encountered POLY node?
        if(!root->mFront)
        {
            recyclePoly(poly);
            return;
        }
        else
            clipPoly(root->mFront, store, poly);
        break;

    case SVNode::Split:
    {
        SVPoly * front;
        SVPoly * back;

        splitPoly(poly, plane, &front, &back);
        AssertFatal(front && back, "ShadowVolumeBSP::clipPoly: invalid split");
        recyclePoly(poly);

        // front
        if(!root->mFront)
        {
            recyclePoly(front);
            return;
        }
        else
            clipPoly(root->mFront, store, front);

        // back
        if(root->mBack)
            clipPoly(root->mBack, store, back);
        else
            addToPolyList(store, back);
        break;
    }
    }
}
F32 ShadowVolumeBSP::getLitSurfaceArea(SVPoly * poly, SurfaceInfo * surfaceInfo)
{
    // clip the poly to the shadow volumes
    SVPoly * polyStore = poly;

    for(U32 i = 0; polyStore && (i < surfaceInfo->mShadowed.size()); i++)
    {
        SVPoly * polyList = 0;
        SVPoly * traverse = polyStore;

        while(traverse)
        {
            SVPoly * next = traverse->mNext;
            traverse->mNext = 0;

            SVPoly * currentStore = 0;

            clipPoly(mShadowVolumes[surfaceInfo->mShadowed[i]], &currentStore, traverse);

            if(currentStore)
                movePolyList(&polyList, currentStore);

            traverse = next;
        }
        polyStore = polyList;
    }

    // get the lit area
    F32 area = getPolySurfaceArea(polyStore);
    recyclePoly(polyStore);
    return(area);
}
//------------------------------------------------------------------------------
F32 ShadowVolumeBSP::getClippedSurfaceArea(SVNode * root, SVPoly * poly)
{
    SVPoly * store = 0;
    clipPoly(root, &store, poly);

    F32 area = getPolySurfaceArea(store);
    recyclePoly(store);
    return(area);
}
예제 #4
0
bool FruitCutNinjaScene::slice(PhysicsWorld &world, const PhysicsRayCastInfo& info, void *data)
{
    if (info.shape->getBody()->getTag() != _sliceTag)
    {
        return true;
    }
    
    if (!info.shape->containsPoint(info.start) && !info.shape->containsPoint(info.end))
    {
        Vec2 normal = info.end - info.start;
        normal = normal.getPerp().getNormalized();
        float dist = info.start.dot(normal);
        
        clipPoly(dynamic_cast<PhysicsShapePolygon*>(info.shape), normal, dist);
        clipPoly(dynamic_cast<PhysicsShapePolygon*>(info.shape), -normal, -dist);
        
        Vec2 v2Direct = (info.end - info.start).getNormalized();
        Vec2 v2Tmp = Vec2::ZERO;
        for (int i = 0; i < PARTICLE_COUNT; i++)
        {
            v2Tmp = info.contact + v2Direct * 80 * (i - 1);
            if (!info.shape->containsPoint(v2Tmp))
            {
                continue;
            }
            else
            {
                m_pEmitter[i]->setPosition(v2Tmp);
                m_pEmitter[i]->resetSystem();
            }
        }
        
        info.shape->getBody()->removeFromWorld();
        info.shape->getBody()->getNode()->removeFromParent();
    }
    
    return true;
}
예제 #5
0
static void rasterizeTri(const float* v0, const float* v1, const float* v2,
						 const unsigned char area, rcHeightfield& hf,
						 const float* bmin, const float* bmax,
						 const float cs, const float ics, const float ich,
						 const int flagMergeThr)
{
	const int w = hf.width;
	const int h = hf.height;
	float tmin[3], tmax[3];
	const float by = bmax[1] - bmin[1];
	
	// Calculate the bounding box of the triangle.
	rcVcopy(tmin, v0);
	rcVcopy(tmax, v0);
	rcVmin(tmin, v1);
	rcVmin(tmin, v2);
	rcVmax(tmax, v1);
	rcVmax(tmax, v2);
	
	// If the triangle does not touch the bbox of the heightfield, skip the triagle.
	if (!overlapBounds(bmin, bmax, tmin, tmax))
		return;
	
	// Calculate the footpring of the triangle on the grid.
	int x0 = (int)((tmin[0] - bmin[0])*ics);
	int y0 = (int)((tmin[2] - bmin[2])*ics);
	int x1 = (int)((tmax[0] - bmin[0])*ics);
	int y1 = (int)((tmax[2] - bmin[2])*ics);
	x0 = rcClamp(x0, 0, w-1);
	y0 = rcClamp(y0, 0, h-1);
	x1 = rcClamp(x1, 0, w-1);
	y1 = rcClamp(y1, 0, h-1);
	
	// Clip the triangle into all grid cells it touches.
	float in[7*3], out[7*3], inrow[7*3];
	
	for (int y = y0; y <= y1; ++y)
	{
		// Clip polygon to row.
		rcVcopy(&in[0], v0);
		rcVcopy(&in[1*3], v1);
		rcVcopy(&in[2*3], v2);
		int nvrow = 3;
		const float cz = bmin[2] + y*cs;
		nvrow = clipPoly(in, nvrow, out, 0, 1, -cz);
		if (nvrow < 3) continue;
		nvrow = clipPoly(out, nvrow, inrow, 0, -1, cz+cs);
		if (nvrow < 3) continue;
		
		for (int x = x0; x <= x1; ++x)
		{
			// Clip polygon to column.
			int nv = nvrow;
			const float cx = bmin[0] + x*cs;
			nv = clipPoly(inrow, nv, out, 1, 0, -cx);
			if (nv < 3) continue;
			nv = clipPoly(out, nv, in, -1, 0, cx+cs);
			if (nv < 3) continue;
			
			// Calculate min and max of the span.
			float smin = in[1], smax = in[1];
			for (int i = 1; i < nv; ++i)
			{
				smin = rcMin(smin, in[i*3+1]);
				smax = rcMax(smax, in[i*3+1]);
			}
			smin -= bmin[1];
			smax -= bmin[1];
			// Skip the span if it is outside the heightfield bbox
			if (smax < 0.0f) continue;
			if (smin > by) continue;
			// Clamp the span to the heightfield bbox.
			if (smin < 0.0f) smin = 0;
			if (smax > by) smax = by;
			
			// Snap the span to the heightfield height grid.
			unsigned short ismin = (unsigned short)rcClamp((int)floorf(smin * ich), 0, RC_SPAN_MAX_HEIGHT);
			unsigned short ismax = (unsigned short)rcClamp((int)ceilf(smax * ich), (int)ismin+1, RC_SPAN_MAX_HEIGHT);
			
			addSpan(hf, x, y, ismin, ismax, area, flagMergeThr);
		}
	}
}
예제 #6
0
bool CCutScene::slice(PhysicsWorld &world, const PhysicsRayCastInfo& info, void *data)
{
    log("slice called %f, %f, %lld", info.contact.x, info.contact.y, m_lLastSlice);
    if (!m_bHasFood) return true;
    
    if (info.shape->getBody()->getTag() != _sliceTag)
    {
        return true;
    }
    
    long long llLastSlice = 0;
    PhysicsBody* pBody = info.shape->getBody();
    if (pBody == NULL) return true;
    CFoodCut* pFood = (CFoodCut*)info.shape->getBody()->getNode();
    if (pFood == NULL) return true;
    llLastSlice = pFood->getBirthTime();
    
    if (getCurTime() - llLastSlice <= 200) return true;
    m_v2Delta.normalize();
    Vec2 v2Start = info.contact - m_v2Delta * 100;
    Vec2 v2End = info.contact + m_v2Delta * 500;
    
    if (!info.shape->containsPoint(v2Start) && !info.shape->containsPoint(v2End))
    {
        Vec2 normal = v2End - v2Start;
        normal = normal.getPerp().getNormalized();
        float dist = v2Start.dot(normal);
        
        clipPoly(dynamic_cast<PhysicsShapePolygon*>(info.shape), normal, dist);
        clipPoly(dynamic_cast<PhysicsShapePolygon*>(info.shape), -normal, -dist);
        
        Vec2 v2Direct = (v2End - v2Start).getNormalized();
        Vec2 v2Tmp = Vec2::ZERO;
        for (int i = 0; i < PARTICLE_COUNT; i++)
        {
            v2Tmp = info.contact + v2Direct * 80 * (i - 1);
            if (!info.shape->containsPoint(v2Tmp))
            {
                continue;
            }
            else
            {
                m_pEmitter[i]->setPosition(v2Tmp);
                m_pEmitter[i]->resetSystem();
            }
        }
        
        std::vector<CFoodCut*>::iterator it;
        for (it = m_vCutFoods.begin(); it != m_vCutFoods.end(); it++)
        {
            CFoodCut* pTmp = *it;
            if (pTmp == info.shape->getBody()->getNode())
            {
                m_vCutFoods.erase(it);
                break;
            }
        }
        m_nSliceCount--;
        info.shape->getBody()->removeFromWorld();
        info.shape->getBody()->getNode()->removeFromParent();
        
        checkFoodSliced();
    }
    
    return true;
}