Пример #1
0
void clipSegmentPlane(plane_struct* pl, polygon_struct** o, polygon_struct* pp1, polygon_struct* pp2)
{
	if(!pl || !o)return;
	const vect3D v1=pp1->v;const vect3D v2=pp2->v;
	int32 val1=evaluatePlanePoint(pl,v1);
	int32 val2=evaluatePlanePoint(pl,v2);
	// const int32 val1=pp1->val;
	// const int32 val2=pp2->val=evaluatePlanePoint(pl,v2);
	if(val1>=0)
	{
		polygon_struct* p=createPolygon(v1);
		if(!p)return;
		p->next=*o;
		*o=p;
		if(val2<0)
		{
			vect3D dir=vectDifference(v2,v1);
			dir=vect(dir.x<<8,dir.y<<8,dir.z<<8); //improves precision, but limits polygon size; so be careful not to use polygons that are too big
			int32 dist=magnitude(dir); //not the actual distance between v1 and v2 but intersectSegmentPlane doesn't need it so...
			dir=divideVect(dir,dist);
			
			vect3D v=intersectSegmentPlane(pl,v1,dir,dist);
			
			p=createPolygon(v);
			if(!p)return;
			p->next=*o;
			*o=p;
		}
	}else{
		if(val2>=0)
		{
			vect3D dir=vectDifference(v2,v1);
			dir=vect(dir.x<<8,dir.y<<8,dir.z<<8); //improves precision, but limits polygon size; so be careful not to use polygons that are too big
			int32 dist=magnitude(dir); //not the actual distance between v1 and v2 but intersectSegmentPlane doesn't need it so...
			dir=divideVect(dir,dist);
			
			vect3D v=intersectSegmentPlane(pl,v1,dir,dist);
			
			polygon_struct* p=createPolygon(v);
			if(!p)return;
			p->next=*o;
			*o=p;
		}
	}
}
Пример #2
0
void ProjectorCamera::loadMatrices()
{
    Camera::loadMatrices();

    // adjust the camera frustum
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    const REAL ratio = m_width / static_cast<REAL>(m_height);
    const REAL scale = settings.dv_scale;
    gluPerspective(m_fovy * scale, ratio, m_near, m_far-1.0);
    GLdouble p[16];
    glGetDoublev(GL_PROJECTION_MATRIX, p);
    Matrix4x4 perspective = Matrix4x4((REAL *)p).getTranspose();
    glPopMatrix();

    Matrix4x4 viewproj = perspective * m_modelview;
    Matrix4x4 inv_viewproj = viewproj.getInverse();

    Vector4 *corners = new Vector4[8];
    // Near plane (at z = 0)
    corners[0].x = -1, corners[0].y = -1, corners[0].z = 0, corners[0].w = 1;
    corners[1].x =  1, corners[1].y = -1, corners[1].z = 0, corners[1].w = 1;
    corners[2].x = -1, corners[2].y =  1, corners[2].z = 0, corners[2].w = 1;
    corners[3].x =  1, corners[3].y =  1, corners[3].z = 0, corners[3].w = 1;
    // Far plane (should be at z = 1)
    corners[4].x = -1, corners[4].y = -1, corners[4].z = 1, corners[4].w = 1;
    corners[5].x =  1, corners[5].y = -1, corners[5].z = 1, corners[5].w = 1;
    corners[6].x = -1, corners[6].y =  1, corners[6].z = 1, corners[6].w = 1;
    corners[7].x =  1, corners[7].y =  1, corners[7].z = 1, corners[7].w = 1;

    // transform to world space
    Vector4 v;
    for (int i = 0; i < 8; i++) {
        v = corners[i];
        corners[i] = inv_viewproj * v;
        corners[i].homogenize();
    }

    // get intersection points between the edges of
    // the camera frustum and the displacable volume
    std::list<Vector4> intersections;
    // delta denotes absolute distance of the bounding planes of the displaceable volume from the y=0 plane.
    // the value is set to 0 as I'm never going to use the displaceable volume idea.
    const REAL delta = 0.0;
    for (int i = 0; i < 4; i++) {
        if (intersectSegmentPlane(corners[i], corners[i+4], delta, v)) {
            v.y = 0; // project the point onto S_base
            intersections.push_front(v);
        }
        // don't intersect twice if delta is 0
        if (delta > DBL_EPSILON && intersectSegmentPlane(corners[i], corners[i+4], -delta, v)) {
            v.y = 0; // project the point onto S_base
            intersections.push_front(v);
        }
    }

    /*
     * Intersect the edges of the far plane
     * The edge vertex indices are as follows:
     *
     *      6----------7
     *      |          |
     *      |          |
     *      |          |
     *      4----------5
     */
    for (int i = 4; i < 8; i += 3) {
        for (int j = 5; j < 7; j++) {
            if (intersectSegmentPlane(corners[i], corners[j], delta, v)) {
                v.y = 0; // project the point onto S_base
                intersections.push_front(v);
            }
            if (delta > DBL_EPSILON && intersectSegmentPlane(corners[i], corners[j], -delta, v)) {
                v.y = 0; // project the point onto S_base
                intersections.push_front(v);
            }
        }
    }

    /*
     * Intersect the edges of the near plane
     * The edge vertex indices are as follows:
     *
     *      2----------3
     *      |          |
     *      |          |
     *      |          |
     *      0----------1
     */
    for (int i = 0; i < 4; i += 3) {
        for (int j = 1; j < 3; j++) {
            if (intersectSegmentPlane(corners[i], corners[j], delta, v)) {
                v.y = 0; // project the point onto S_base
                intersections.push_front(v);
            }
            if (delta > DBL_EPSILON && intersectSegmentPlane(corners[i], corners[j], -delta, v)) {
                v.y = 0; // project the point onto S_base
                intersections.push_front(v);
            }
        }
    }

    // check if any of the corner points lie inside the volume and add them as well
    if (delta > DBL_EPSILON) {
        for (int i = 0; i < 8; i++) {
            v = corners[i];
            if (v.y > -delta && v.y < delta) {
                v.y = 0;
                intersections.push_front(v);
            }
        }
    }

    // if no intersections are found, return false so that the surface isn't rendered
    if (intersections.size() == 0) {
#ifdef PRINT_VALS
        logln("NOT VISIBLE");
#endif
        delete[] corners;
        grid_visible = false;
        return;
    }
#ifdef PRINT_VALS
    logln("VISIBLE");
#endif
    grid_visible = true;


    // find the corner points of the grid
    // TODO: TEST THIS!!
    Vector4 center;
    for (std::list<Vector4>::iterator it = intersections.begin(); it != intersections.end(); ++it) {
        center += (viewproj * (*it)).getHomogenized();
    }
    center /= intersections.size();
    Vector4 lli,lri,uli,uri;
    lri = uli = uri = lli = center;
    for (std::list<Vector4>::iterator it = intersections.begin(); it != intersections.end(); ++it) {
        v = viewproj * (*it);
        v.homogenize();
        if (v.x < center.x && v.y < lli.y) {
            lli = v;
            ll = (*it);
        } else if (v.x > center.x && v.y > uri.y) {
            uri = v;
            ur = (*it);
        } else if (v.x < center.x && v.y > uli.y) {
            uli = v;
            ul = (*it);
        } else if (v.x > center.x && v.y < lri.y) {
            lri = v;
            lr = (*it);
        }
    }
#ifdef PRINT_VALS
    logln(intersections.size());
    logln("RESULTS: \n");
    logln(lli);
    logln(lri);
    logln(uli);
    logln(uri);
#endif
    delete[] corners;

    // store the left and right sides of the projected grid
    delete[] left_points;
    left_points = new Vector4[settings.grid_resolution + 1];
    delete[] right_points;
    right_points = new Vector4[settings.grid_resolution + 1];
    delete[] depths;
    depths = new float[settings.grid_resolution + 1];

    Vector4 screen_left = viewproj * ul;
    screen_left.homogenize();
    Vector4 screen_right = viewproj * ur;
    screen_right.homogenize();

    Vector4 left_dir = (viewproj * ll).homogenize() - screen_left;
    left_dir.unhomgenize();
    left_dir = left_dir.getNormalized() * (left_dir.getMagnitude()/static_cast<REAL>(settings.grid_resolution));

    Vector4 right_dir = (viewproj * lr).homogenize() - screen_right;
    right_dir.unhomgenize();
    right_dir = right_dir.getNormalized() * (right_dir.getMagnitude()/static_cast<REAL>(settings.grid_resolution));

    // handle boundary cases seperately, as the transformations cause epsilon errors
    left_points[0] = ul;
    right_points[0] = ur;
    left_points[settings.grid_resolution] = ll;
    right_points[settings.grid_resolution] = lr;
    screen_left += left_dir;
    screen_right += right_dir;
    depths[0] = 1;
    depths[settings.grid_resolution] = 0;

    Vector4 near, far;
    float OPTIMIZED_BIOTCH = (ul - ll).getMagnitude();
    for (unsigned  i = 1; i < settings.grid_resolution; i++) {
        far = (inv_viewproj * Vector4(screen_left.x, screen_left.y, 1, 1)).homogenize();
        near = (inv_viewproj * Vector4(screen_left.x, screen_left.y, 0, 1)).homogenize();
        intersectSegmentPlane(near, far, 0, v);
        left_points[i] = v;
        screen_left += left_dir;

        depths[i] = (v - ll).getMagnitude() / OPTIMIZED_BIOTCH;

        far = (inv_viewproj * Vector4(screen_right.x, screen_right.y, 1, 1)).homogenize();
        near = (inv_viewproj * Vector4(screen_right.x, screen_right.y, 0, 1)).homogenize();
        intersectSegmentPlane(near, far, 0, v);
        right_points[i] = v;
        screen_right += right_dir;
    }
}