예제 #1
0
void Box::GetExtentsAlongAxis(Vector4 const& v, float & a, float & b) const
{
	// The implementation of this function is optimized to the point of opacity.
	// If you're interested in its inner workings, contact me directly.

	// transform v into object space.
	Vector4 ov = TransformPlane(v, GetTransformation().inverseAffine());
	Vector3 ov3(ov.x, ov.y, ov.z);
	// note: ov3 is unit length

	// distance from center of box to plane
	float dc = ov.w;

	// distances along ov from center to each of the positive three faces, abs'ed and summed
	float extDist = GetHalfSize().absDotProduct(ov3);

	a = dc - extDist;
	b = dc + extDist;
}
예제 #2
0
VPlane VMatrix::operator*(const VPlane &thePlane) const
{
	VPlane ret;
	TransformPlane( thePlane, ret );
	return ret;
}
예제 #3
0
파일: plate.cpp 프로젝트: artemeliy/inf4715
int Plate::BuildMaps(TimeValue t, RenderMapsContext &rmc) {
	SubRendParams srp;
	rmc.GetSubRendParams(srp);
  	PlateMap *pmap = FindMap(rmc.NodeRenderID());
	if (pmap&&!DoThisFrame(t,srp.fieldRender,pmap->mapTime))
		return 1;
	ViewParams vp;

	Box2 sbox;

	rmc.GetCurrentViewParams(vp);

	rmc.FindMtlScreenBox(sbox, &vp.affineTM, rmc.SubMtlIndex());

	int xmin,xmax,ymin,ymax;

	BOOL fieldRender = FALSE;
	if (srp.fieldRender) {
		sbox.top *= 2;
		sbox.bottom *= 2;
		fieldRender = TRUE;
		}

		// add a margin around object for refraction
	int ew = srp.devWidth/20;
	int eh = srp.devHeight/20;
	xmax = sbox.right+ew;
	xmin = sbox.left-ew;
	ymax = sbox.bottom+eh;
	ymin = sbox.top-eh;

	if (srp.rendType==RENDTYPE_REGION) {
		ymin = MAX(ymin,srp.ymin-eh);
		ymax = MIN(ymax,srp.ymax+eh);
		xmin = MAX(xmin,srp.xmin-ew);
		xmax = MIN(xmax,srp.xmax+ew);
		}

	srp.xmin = MAX(xmin,-ew);
	srp.xmax = MIN(xmax,srp.devWidth+ew);
	srp.ymin = MAX(ymin,-eh);
	srp.ymax = MIN(ymax,srp.devHeight+eh);

	int xorg = xmin;
	int yorg = ymin;
	int devw = srp.devWidth;
	int devh = srp.devHeight;

	// The renderer is set up to allocate A-buffer for the range
	// 0..devWidth-1,  0..devHeight-1.  If the region of the plate
	// bitmap goes out of this region, it must be extended.
	int d1 = 0, d2 = 0;
	if (srp.xmin<0) d1 = -srp.xmin;
	if (srp.xmax>=srp.devWidth) d2 = srp.xmax-srp.devWidth+1;
	int d = MAX(d1,d2);
	if (d) {
		srp.devWidth += 2*d;
		srp.xmax += d;
		srp.xmin += d;
		// must also correct fov (or zoom) so the renderer computes the
		// same xscale and yscale
		if (vp.projType==PROJ_PERSPECTIVE) {
			vp.fov = 2.0f*(float)atan((float(srp.devWidth)/float(devw))*tan(0.5*vp.fov));
			}
		else {
			vp.zoom *= (float(srp.devWidth)/float(devw));
			}
		srp.blowupCenter.x += d; // DS: 11/6/00
		}	

	d1 = d2 = 0;
	if (srp.ymin<0) d1 = -srp.ymin;
	if (srp.ymax>=srp.devHeight) d2 = srp.ymax-srp.devHeight+1;
	d = MAX(d1,d2);
	if (d) {
//		if (fieldRender)
//			d = ((d+1)>>1)<<1; // make d even, so line doubling (below) works right.
		srp.devHeight += 2*d;
		srp.ymax += d;
		srp.ymin += d;
		srp.blowupCenter.y += d;   // DS: 11/6/00
		}	


	srp.xorg = srp.xmin;
	srp.yorg = srp.ymin;

	srp.doEnvMap = useEnvMap;
	//srp.doingMirror = TRUE;  // DS: 11/6/00: no longer necessary

	int w = srp.xmax-srp.xmin;
	int h = srp.ymax-srp.ymin;


	if (w<=0||h<=0) 
		return 1;
#ifdef DBG
	w = ((w+3)/4)*4;   // For some reason this needs to be a multiple of 4 for bm->Display
#endif

  	if (pmap==NULL) {
	  	pmap = new PlateMap;
		pmap->nodeID = rmc.NodeRenderID();
		pmap->next = maps;
		maps = pmap;
		}
	
	pmap->AllocMap(w, h);
	pmap->org.x = xorg-devw/2;
	pmap->org.y = yorg-devh/2;
	pmap->devW = devw;  // TBD: This should be accessable from the SC
	pmap->mapTime = t;

	
	// Set up clipping planes to clip out stuff between camera and plate.
	Box3 b = rmc.ObjectSpaceBoundingBox();
	Matrix3 tmObToWorld = rmc.ObjectToWorldTM();
	Matrix3 obToCam = tmObToWorld*vp.affineTM;	
	int nplanes=0;
	Point4 pl[6],pc;
	Point4 clip[6];

	pl[0] = Point4( 1.0f, 0.0f, 0.0f, -b.pmax.x);
	pl[1] = Point4(-1.0f, 0.0f, 0.0f,  b.pmin.x);
	pl[2] = Point4( 0.0f, 1.0f, 0.0f, -b.pmax.y);
	pl[3] = Point4( 0.0f,-1.0f, 0.0f,  b.pmin.y);
	pl[4] = Point4( 0.0f, 0.0f, 1.0f, -b.pmax.z);
	pl[5] = Point4( 0.0f, 0.0f,-1.0f,  b.pmin.z);
	if (vp.projType==PROJ_PARALLEL) {
		for (int i=0; i<6; i++) {
			pc = TransformPlane(obToCam,pl[i]);	
			// see if camera = (0,0,0) is in front of plane
			if (pc.z>0.0f)  
				clip[nplanes++] = -pc;
			}
		}
	else {
		for (int i=0; i<6; i++) {
			pc = TransformPlane(obToCam,pl[i]);	
			// see if camera = (0,0,0) is in front of plane
			if (pc.w>0.0f)  
				clip[nplanes++] = -pc;
			}
		}

	srp.fieldRender = FALSE;

//	assert(nplanes<4);
	if (!rmc.Render(pmap->bm, vp, srp, clip, nplanes))
		return 0;

/*
	if (srp.fieldRender) {
		// Double the lines, otherwise the blur wont work right,
		// because the blank lines in between get averaged in and darken it.
		int	evenLines = srp.evenLines; 
		if(srp.ymin&1) 
			evenLines = !evenLines;

		PixelBuf l64(w);
		if (evenLines) {
			for (int i=0; i<h; i+=2) {
				BMM_Color_64 *p64=l64.Ptr();
				if (i+1<h) {
					pmap->bm->GetPixels(0,i,  w, p64); 
					pmap->bm->PutPixels(0,i+1,w, p64);				
					}
				}
			}
		else {
			for (int i=0; i<h; i+=2) {
				BMM_Color_64 *p64=l64.Ptr();
				if (i+1<h) {
					pmap->bm->GetPixels(0,i+1,w, p64); 
					pmap->bm->PutPixels(0,i  ,w, p64);				
					}
				}
			}
		}
*/

#ifdef DBG
	if (devw>200){
		pmap->bm->UnDisplay();
		TSTR buf;
		RenderGlobalContext *gc = rmc.GetGlobalContext();
		RenderInstance* inst = gc->GetRenderInstance(rmc.NodeRenderID());
		INode *node  = inst->GetINode();
		buf.printf(_T("Thinwall: %s"), node->GetName());
		pmap->bm->Display(buf, BMM_UR);
		MessageBox(NULL, _T("hi"), _T(" Plate Test"), MB_OK|MB_ICONEXCLAMATION);
		}
#endif

	if (applyBlur) {
		// I tried pyramids here, but SATs looked much better. 
		//  maybe we should give users a choice?
		pmap->bm->SetFilter(BMM_FILTER_SUM); 
//		pmap->bm->SetFilter(BMM_FILTER_PYRAMID); 
		BitmapFilter *filt = pmap->bm->Filter();
		if (filt)
			filt->MakeDirty();  // so filter gets recomputed for each frame
		}
	else 
		pmap->bm->SetFilter(BMM_FILTER_NONE); 
	return 1;
	}