示例#1
0
/**
 * Given the coordinates of the two opposite corners of a bounding box
 * in object space (x1,y1,z1) and (x2,y2,z2), use the given modelview
 * and projection matrices to transform the coordinates to NDC space.
 * Find the 3D bounding bounding box of those eight coordinates and
 * return the min/max in (x1,y1,x1) and (x2,y2,z2).
 */
void
crProjectBBox(const GLfloat modl[16], const GLfloat proj[16], 
              GLfloat *x1, GLfloat *y1, GLfloat *z1,
              GLfloat *x2, GLfloat *y2, GLfloat *z2) 
{
	CRmatrix m;
	
	/* compute product of modl and proj matrices */
	m.m00  = proj[0] * modl[0]  + proj[4] * modl[1]  + proj[8]  * modl[2]  + proj[12] * modl[3];	
	m.m01  = proj[1] * modl[0]  + proj[5] * modl[1]  + proj[9]  * modl[2]  + proj[13] * modl[3];	
	m.m02  = proj[2] * modl[0]  + proj[6] * modl[1]  + proj[10] * modl[2]  + proj[14] * modl[3];	
	m.m03  = proj[3] * modl[0]  + proj[7] * modl[1]  + proj[11] * modl[2]  + proj[15] * modl[3];	
	m.m10  = proj[0] * modl[4]  + proj[4] * modl[5]  + proj[8]  * modl[6]  + proj[12] * modl[7];	
	m.m11  = proj[1] * modl[4]  + proj[5] * modl[5]  + proj[9]  * modl[6]  + proj[13] * modl[7];	
	m.m12  = proj[2] * modl[4]  + proj[6] * modl[5]  + proj[10] * modl[6]  + proj[14] * modl[7];	
	m.m13  = proj[3] * modl[4]  + proj[7] * modl[5]  + proj[11] * modl[6]  + proj[15] * modl[7];	
	m.m20  = proj[0] * modl[8]  + proj[4] * modl[9]  + proj[8]  * modl[10] + proj[12] * modl[11];	
	m.m21  = proj[1] * modl[8]  + proj[5] * modl[9]  + proj[9]  * modl[10] + proj[13] * modl[11];
	m.m22  = proj[2] * modl[8]  + proj[6] * modl[9]  + proj[10] * modl[10] + proj[14] * modl[11];	
	m.m23  = proj[3] * modl[8]  + proj[7] * modl[9]  + proj[11] * modl[10] + proj[15] * modl[11];	
	m.m30  = proj[0] * modl[12] + proj[4] * modl[13] + proj[8]  * modl[14] + proj[12] * modl[15];	
	m.m31  = proj[1] * modl[12] + proj[5] * modl[13] + proj[9]  * modl[14] + proj[13] * modl[15];	
	m.m32  = proj[2] * modl[12] + proj[6] * modl[13] + proj[10] * modl[14] + proj[14] * modl[15];	
	m.m33  = proj[3] * modl[12] + proj[7] * modl[13] + proj[11] * modl[14] + proj[15] * modl[15]; 
	
    crTransformBBox( *x1, *y1, *z1,
                     *x2, *y2, *z2,
                     &m,
                     x1, y1, z1,
                     x2, y2, z2 );
}
示例#2
0
/**
 * Transform a bounding box from object space to NDC space.
 * This routine is used by most of the bucketing algorithms.
 * \param  winInfo - which window/mural
 * \param      server - which server (usually not needed)
 * \param      objMin, objMax - bounds in object space
 * \param xmin, ymin, zmin, xmax, ymax, zmax - bounds in NDC
 * \param      ibounds - bounds in screen coords
 * \return  GL_TRUE if the resulting screen-space NDC bbox is visible,
 *         GL_FALSE if the resulting screen-space NDC bbox is not visible.
 */
static GLboolean
TransformBBox(const WindowInfo *winInfo, int server,
							const GLvectorf *objMin, const GLvectorf *objMax,
							float *xmin, float *ymin, float *zmin,
							float *xmax, float *ymax, float *zmax,
							CRrecti *ibounds)
{
	GET_THREAD(thread);
	CRContext *g = thread->currentContext->State;
	CRTransformState *t = &(g->transform);

	if (thread->currentContext->providedBBOX == GL_SCREEN_BBOX_CR) {
		/* objMin, objMax are in NDC screen coords already */
		*xmin = objMin->x;
		*ymin = objMin->y;
		*zmin = objMin->z;
		*xmax = objMax->x;
		*ymax = objMax->y;
		*zmax = objMax->z;
	}
	else if (winInfo->matrixSource == MATRIX_SOURCE_SERVERS) {
		/* Use matrices obtained from the servers */
		const ServerWindowInfo *servWinInfo = winInfo->server + server;
		CRmatrix pv, pvm;
		int eye = (thread->currentContext->stereoDestFlags & EYE_RIGHT) ? 1:0;

		/* XXX \todo we could multiply this earlier! */
		/* pv = proj matrix * view matrix */
		crMatrixMultiply(&pv, &servWinInfo->projectionMatrix[eye],
														&servWinInfo->viewMatrix[eye]);
		/* pvm = pv * model matrix */
		crMatrixMultiply(&pvm, &pv, t->modelViewStack.top);

		/* Transform bbox by modelview * projection, and project to screen */
		crTransformBBox( objMin->x, objMin->y, objMin->z,
										 objMax->x, objMax->y, objMax->z, &pvm,
										 xmin, ymin, zmin, xmax, ymax, zmax );
	}
	else if (winInfo->matrixSource == MATRIX_SOURCE_CONFIG &&
					 thread->currentContext->stereoDestFlags != (EYE_LEFT | EYE_RIGHT)) {
		/* use special left or right eye matrices (set via config options) */
		const int curEye = thread->currentContext->stereoDestFlags - 1;
		CRmatrix pv, pvm;

		CRASSERT(curEye == 0 || curEye == 1);

		/* XXX \todo we could multiply this earlier! */
		/* pv = proj matrix * view matrix */
		crMatrixMultiply(&pv, &tilesort_spu.stereoProjMatrices[curEye],
														&tilesort_spu.stereoViewMatrices[curEye]);
		/* pvm = pv * model matrix */
		crMatrixMultiply(&pvm, &pv, t->modelViewStack.top);

		/* Transform bbox by modelview * projection, and project to screen */
		crTransformBBox( objMin->x, objMin->y, objMin->z,
										 objMax->x, objMax->y, objMax->z, &pvm,
										 xmin, ymin, zmin, xmax, ymax, zmax );
	}
	else {
		const CRmatrix *mvp = &(t->modelViewProjection);

		CRASSERT(winInfo->matrixSource == MATRIX_SOURCE_APP ||
				 thread->currentContext->stereoDestFlags == (EYE_LEFT | EYE_RIGHT));

		/* Check to make sure the transform is valid */
		if (!t->modelViewProjectionValid)
		{
			/* I'm pretty sure this is always the case, but I'll leave it. */
			crStateTransformUpdateTransform(t);
		}

		/* Transform bbox by modelview * projection, and project to screen */
		crTransformBBox( objMin->x, objMin->y, objMin->z,
										 objMax->x, objMax->y, objMax->z, mvp,
										 xmin, ymin, zmin, xmax, ymax, zmax );
	}

	/* trivial rejection test */
	if (*xmin > 1.0f || *ymin > 1.0f || *xmax < -1.0f || *ymax < -1.0f) {
		/* bbox doesn't intersect screen */
		return GL_FALSE;
	}

	/* clamp */
	if (*xmin < -1.0f) *xmin = -1.0f;
	if (*ymin < -1.0f) *ymin = -1.0f;
	if (*xmax > 1.0f) *xmax = 1.0f;
	if (*ymax > 1.0f) *ymax = 1.0f;

	if (ibounds) {
		/* return screen pixel coords too */
		ibounds->x1 = (int) (winInfo->halfViewportWidth * *xmin + winInfo->viewportCenterX);
		ibounds->x2 = (int) (winInfo->halfViewportWidth * *xmax + winInfo->viewportCenterX);
		ibounds->y1 = (int) (winInfo->halfViewportHeight * *ymin + winInfo->viewportCenterY);
		ibounds->y2 = (int) (winInfo->halfViewportHeight * *ymax + winInfo->viewportCenterY);
	}
	return GL_TRUE;
}