// Copyright (C) 1996 Keith Whitwell. // This file may only be copied under the terms of the GNU Library General // Public License - see the file COPYING in the lib3d distribution. #include #include #include #include #include BoundingBox::BoundingBox( const Vertex *v, uint nr ) : min(v->model), max(v->model) { v++; for( uint i = 1 ; i < nr ; i++, v++ ) { if (v->model.v[X] > max.v[X]) max.v[X] = v->model.v[X]; if (v->model.v[Y] > max.v[Y]) max.v[Y] = v->model.v[Y]; if (v->model.v[Z] > max.v[Z]) max.v[Z] = v->model.v[Z]; if (v->model.v[X] < min.v[X]) min.v[X] = v->model.v[X]; if (v->model.v[Y] < min.v[Y]) min.v[Y] = v->model.v[Y]; if (v->model.v[Z] < min.v[Z]) min.v[Z] = v->model.v[Z]; } debug() << "Object space min:" << min << " max:" << max << endlog; } BoundingBox::~BoundingBox() { } // From Graphic Gems 1. bool BoundingBox::testBounds( const Matrix34& toCvv, float D, uint &intersections ) { // Take care of translation. tmin.v[0] = tmax.v[0] = toCvv.v[X][3]; tmin.v[1] = tmax.v[1] = toCvv.v[Y][3]; tmin.v[2] = tmax.v[2] = toCvv.v[Z][3]; // Now find the extreme points by considering the product of the // min and max with each component of the transformation. for( int i = 0; i < 3; i++ ) { for( int j = 0; j < 3; j++ ) { float a = toCvv.v[j][i] * min.v[i]; float b = toCvv.v[j][i] * max.v[i]; if( a < b ) { tmin.v[j] += a; tmax.v[j] += b; } else { tmin.v[j] += b; tmax.v[j] += a; } } } // Compute outcodes uint oc1 = tmin.computeOutcodes(D); uint oc2 = tmax.computeOutcodes(D); uint outside = oc1 & oc2; intersections = oc1 | oc2; // cout << "Intersections: " << intersections << endl; if_debug { debug() << "Transformed min:" << tmin << " max:" << tmax << endlog; debug() << "Outcodes min:" << oc1 << " max:" << oc2 << endlog; debug() << "Intersections: " << bool(intersections) << "Inside: " << bool(!outside) << endlog; printf("Planes: %x\n", intersections); } return !outside; /* intersections = 0x3f; return true; */ } bool BoundingBox::testAndDrawBounds(const Matrix34& toCvv, float D, uint &intersections, Viewport &viewport) { if (testBounds(toCvv, D, intersections)) { DeviceColour colour = viewport.getColour(0xff,0xff,0xff); int wid = viewport.getWidth()/2; int xmin = int(::max(tmin.v[X] * wid + wid, 0)); int xmax = int(::min(tmax.v[X] * wid + wid, viewport.getWidth())); wid = viewport.getHeight()/2; int ymin = int(::max(tmin.v[Y] * wid + wid, 0)); int ymax = int(::min(tmax.v[Y] * wid + wid, viewport.getHeight())); DeviceVector c,d; d.v[X] = c.v[X] = xmin; c.v[Y] = ymin; d.v[Y] = ymax; viewport.clipLine(c,d,colour); d.v[X] = c.v[X] = xmax; viewport.clipLine(c,d,colour); d.v[Y] = c.v[Y] = ymin; c.v[X] = xmin; d.v[X] = xmax; viewport.clipLine(c,d,colour); d.v[Y] = c.v[Y] = ymax; viewport.clipLine(c,d,colour); d.v[X] = c.v[X] = 0; c.v[Y] = 0; d.v[Y] = 10; viewport.clipLine(c,d,colour); d.v[X] = c.v[X] = 10; viewport.clipLine(c,d,colour); d.v[Y] = c.v[Y] = 0; c.v[X] = 0; d.v[X] = 10; viewport.clipLine(c,d,colour); d.v[Y] = c.v[Y] = 10; viewport.clipLine(c,d,colour); return true; } else { return false; } } BoundingBoxExact::BoundingBoxExact( const Vertex *v, uint nr ) { Vector3 min(v->model); Vector3 max(v->model); v++; for( uint i = 1 ; i < nr ; i++, v++ ) { if (v->model.v[X] > max.v[X]) max.v[X] = v->model.v[X]; if (v->model.v[Y] > max.v[Y]) max.v[Y] = v->model.v[Y]; if (v->model.v[Z] > max.v[Z]) max.v[Z] = v->model.v[Z]; if (v->model.v[X] < min.v[X]) min.v[X] = v->model.v[X]; if (v->model.v[Y] < min.v[Y]) min.v[Y] = v->model.v[Y]; if (v->model.v[Z] < min.v[Z]) min.v[Z] = v->model.v[Z]; } debug() << "Object space min:" << min << " max:" << max << endlog; model[0] = min; model[1] = min; model[1].v[X] = max.v[X]; model[2] = max; model[2].v[Z] = min.v[Z]; model[3] = min; model[3].v[Y] = max.v[Y]; model[4] = min; model[4].v[Z] = max.v[Z]; model[5] = min; model[5].v[X] = max.v[X]; model[5].v[Z] = max.v[Z]; model[6] = max; model[7] = min; model[7].v[Y] = max.v[Y]; model[7].v[Z] = max.v[Z]; } BoundingBoxExact::~BoundingBoxExact() { } bool BoundingBoxExact::testBounds(const Matrix34& toCvv, float D, uint &intersections ) { uint outside = 0x3f; uint tmp = 0; for ( int i = 0 ; i < 8 ; i++ ) { cvv[i].mul(toCvv, model[i]); uint oc = cvv[i].computeOutcodes(D); tmp |= oc; outside &= oc; } intersections = tmp; // cout << "Intersections: " << intersections << endl; if_debug { debug() << "Intersections: " << bool(intersections) << "Inside: " << bool(!outside) << endlog; printf("\tPlanes: %x\n", intersections); } return !outside; } bool BoundingBoxExact::testAndDrawBounds(const Matrix34& toCvv, float D, uint &intersections, Viewport &viewport, const Matrix4& toDevice) { if (testBounds( toCvv, D, intersections )) { for ( int i = 0 ; i < 8 ; i++ ) { //cvv[i].v[Z] = min(max(cvv[i].v[Z], D), 1); //cvv[i].v[X] = min(max(cvv[i].v[X], -cvv[i].v[Z]), cvv[i].v[Z]); //cvv[i].v[Y] = min(max(cvv[i].v[Y], -cvv[i].v[Z]), cvv[i].v[Z]); device[i].project(toDevice, cvv[i]); } DeviceColour colour = viewport.getColour(0xff,0xff,0xff); viewport.clipLine(device[0], device[1], colour); viewport.clipLine(device[1], device[2], colour); viewport.clipLine(device[2], device[3], colour); viewport.clipLine(device[3], device[0], colour); viewport.clipLine(device[4], device[5], colour); viewport.clipLine(device[5], device[6], colour); viewport.clipLine(device[6], device[7], colour); viewport.clipLine(device[7], device[4], colour); viewport.clipLine(device[0], device[4], colour); viewport.clipLine(device[1], device[5], colour); viewport.clipLine(device[2], device[6], colour); viewport.clipLine(device[3], device[7], colour); return true; } return false; }