//------------------------------------------------------------------------------ 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]], ¤tStore, 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); }
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; }
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); } } }
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; }