Beispiel #1
0
Polyhedron Frustum::ToPolyhedron() const
{
	// Note to maintainer: This function is an exact copy of AABB:ToPolyhedron() and OBB::ToPolyhedron().

	Polyhedron p;
	// Populate the corners of this Frustum.
	// The will be in the order 0: ---, 1: --+, 2: -+-, 3: -++, 4: +--, 5: +-+, 6: ++-, 7: +++.
	for(int i = 0; i < 8; ++i)
		p.v.push_back(CornerPoint(i));

	// Generate the 6 faces of this Frustum.
	const int faces[6][4] =
	{
		{ 0, 2, 3, 1 }, // X-
		{ 4, 5, 7, 6 }, // X+
		{ 0, 1, 5, 4 }, // Y-
		{ 7, 3, 2, 6 }, // Y+
		{ 0, 4, 6, 2 }, // Z-
		{ 1, 3, 7, 5 }, // Z+
	};

	for(int f = 0; f < 6; ++f)
	{
		Polyhedron::Face face;
		for(int v = 0; v < 4; ++v)
			face.v.push_back(faces[f][v]);
		p.f.push_back(face);
	}

	return p;
}
Beispiel #2
0
AABB Frustum::MinimalEnclosingAABB() const
{
	AABB aabb;
	aabb.SetNegativeInfinity();
	for(int i = 0; i < 8; ++i)
		aabb.Enclose(CornerPoint(i));
	return aabb;
}
Beispiel #3
0
void AABB::GetCornerPoints(vec *outPointArray) const
{
	assume(outPointArray);
#ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS
	if (!outPointArray)
		return;
#endif
	for(int i = 0; i < 8; ++i)
		outPointArray[i] = CornerPoint(i);
}
Beispiel #4
0
float3 Frustum::ExtremePoint(const float3 &direction) const
{
	float3 mostExtreme = float3::nan;
	float mostExtremeDist = -FLT_MAX;
	for(int i = 0; i < 8; ++i)
	{
		float3 pt = CornerPoint(i);
		float d = Dot(direction, pt);
		if (d > mostExtremeDist)
		{
			mostExtremeDist = d;
			mostExtreme = pt;
		}
	}
	return mostExtreme;
}
std::vector<CornerPoint> CornerDetector::run(const std::vector<FieldLine> &lines) const
{
    std::vector<FieldLine>::const_iterator it1, it2;
    std::vector<CornerPoint> results;

    if(lines.size() < 2) {
        return results;
    }

    if(m_tolerance < 0 || m_tolerance > 1) {
        errorlog << "CornerDetector::run called with invalid tolerance: " << m_tolerance << " (must be in [0, 1]." << std::endl;
        return results;
    }

    for(it1 = lines.begin(); it1 != lines.end()-1; it1++) {
        Line l1 = it1->getGroundLineEquation();
        Vector2<NUPoint> l1_pts = it1->getEndPoints();
        for(it2 = it1+1; it2 < lines.end(); it2++) {
            Line l2 = it2->getGroundLineEquation();
            Vector2<NUPoint> l2_pts = it2->getEndPoints();
            if(l1.getAngleBetween(l2) > (1-m_tolerance)*mathGeneral::PI*0.5) {
                //nearly perpendicular
                //now build corner from end points
                NUPoint intersection;
                if(l1.getIntersection(l2, intersection.groundCartesian)) {
                    CornerPoint::TYPE type = findCorner(l1_pts, l2_pts, intersection, m_tolerance);
                    if(type != CornerPoint::INVALID) {
                        //need screen loc
                        if(it1->getScreenLineEquation().getIntersection(it2->getScreenLineEquation(), intersection.screenCartesian)) {
                            results.push_back(CornerPoint(type, intersection));
                        }
                        else {
                            errorlog << "CornerDetector::run - no intersection found for screen lines - transforms are probably not valid, not publishing corner" <<
                                        "\t" << it1->getScreenLineEquation() << "\t" << it2->getScreenLineEquation() << std::endl;
                        }
                    }
                }
            }
        }
    }

    return results;
}
Beispiel #6
0
Polyhedron Frustum::ToPolyhedron() const
{
	// Note to maintainer: This function is an exact copy of AABB:ToPolyhedron() and OBB::ToPolyhedron().

	Polyhedron p;
	// Populate the corners of this Frustum.
	// The will be in the order 0: ---, 1: --+, 2: -+-, 3: -++, 4: +--, 5: +-+, 6: ++-, 7: +++.
	for(int i = 0; i < 8; ++i)
		p.v.push_back(CornerPoint(i));

	// Generate the 6 faces of this Frustum. The function Frustum::GetPlane() has a convention of returning
	// the planes in order near,far,left,right,top,bottom, so follow the same convention here.
	const int faces[6][4] =
	{
		{ 0, 4, 6, 2 }, // Z-: near plane
		{ 1, 3, 7, 5 }, // Z+: far plane
		{ 0, 2, 3, 1 }, // X-: left plane
		{ 4, 5, 7, 6 }, // X+: right plane
		{ 7, 3, 2, 6 }, // Y+: top plane
		{ 0, 1, 5, 4 }, // Y-: bottom plane
	};

	for(int f = 0; f < 6; ++f)
	{
		Polyhedron::Face face;
		if (this->handedness == FrustumLeftHanded)
		{
			for(int v = 0; v < 4; ++v)
				face.v.push_back(faces[f][3-v]);
		}
		else
		{
			for(int v = 0; v < 4; ++v)
				face.v.push_back(faces[f][v]);
		}
		p.f.push_back(face);
	}

	return p;
}
Beispiel #7
0
OBB Frustum::MinimalEnclosingOBB(float expandGuardband) const
{
	assume(IsFinite());
	assume(front.IsNormalized());
	assume(up.IsNormalized());

	OBB obb;
	obb.pos = pos + (nearPlaneDistance + farPlaneDistance) * 0.5f * front;
	obb.axis[1] = up;
	obb.axis[2] = -front;
	obb.axis[0] = Cross(obb.axis[1], obb.axis[2]);
	obb.r = float3::zero;
	for(int i = 0; i < 8; ++i)
		obb.Enclose(CornerPoint(i));

	// Expand the generated OBB very slightly to avoid numerical issues when
	// testing whether this Frustum actually is contained inside the generated OBB.
	obb.r.x += expandGuardband;
	obb.r.y += expandGuardband;
	obb.r.z += expandGuardband;
	return obb;
}
Beispiel #8
0
Polyhedron AABB::ToPolyhedron() const
{
	// Note to maintainer: This function is an exact copy of OBB:ToPolyhedron() and Frustum::ToPolyhedron().
	Polyhedron p;
	// Populate the corners of this AABB.
	// The will be in the order 0: ---, 1: --+, 2: -+-, 3: -++, 4: +--, 5: +-+, 6: ++-, 7: +++.
	for(int i = 0; i < 8; ++i)
		p.v.push_back(CornerPoint(i));

	// Generate the 6 faces of this AABB.
	const int faces[6][4] =
	{
		{ 0, 1, 3, 2 }, // X-
		{ 4, 6, 7, 5 }, // X+
		{ 0, 4, 5, 1 }, // Y-
		{ 7, 6, 2, 3 }, // Y+
		{ 0, 2, 6, 4 }, // Z-
		{ 1, 5, 7, 3 }, // Z+
	};

	for(int f = 0; f < 6; ++f)
	{
		Polyhedron::Face face;
		for(int v = 0; v < 4; ++v)
			face.v.push_back(faces[f][v]);
		p.f.push_back(face);
	}
	
	assume(p.IsClosed());
	assume(p.IsConvex());
	assume(p.EulerFormulaHolds());
	assume(p.FaceIndicesValid());
	assume(p.FacesAreNondegeneratePlanar());
	assume(p.Contains(this->CenterPoint()));
	return p;
}
Beispiel #9
0
vec AABB::RandomCornerPoint(LCG &rng) const
{
	return CornerPoint(rng.Int(0, 7));
}
Beispiel #10
0
void OBB::GetCornerPoints(float3 *outPointArray) const
{
    assert(outPointArray);
    for(int i = 0; i < 8; ++i)
        outPointArray[i] = CornerPoint(i);
}
Beispiel #11
0
LineSegment OBB::Edge(int edgeIndex) const
{
    assume(0 <= edgeIndex && edgeIndex <= 11);
    switch(edgeIndex)
    {
        default: // For release builds where assume() is disabled, return always the first option if out-of-bounds.
        case 0: return LineSegment(CornerPoint(0), CornerPoint(1));
        case 1: return LineSegment(CornerPoint(0), CornerPoint(2));
        case 2: return LineSegment(CornerPoint(0), CornerPoint(4));
        case 3: return LineSegment(CornerPoint(1), CornerPoint(3));
        case 4: return LineSegment(CornerPoint(1), CornerPoint(5));
        case 5: return LineSegment(CornerPoint(2), CornerPoint(3));
        case 6: return LineSegment(CornerPoint(2), CornerPoint(6));
        case 7: return LineSegment(CornerPoint(3), CornerPoint(7));
        case 8: return LineSegment(CornerPoint(4), CornerPoint(5));
        case 9: return LineSegment(CornerPoint(4), CornerPoint(6));
        case 10: return LineSegment(CornerPoint(5), CornerPoint(7));
        case 11: return LineSegment(CornerPoint(6), CornerPoint(7));
    }
}
 ARFloat
Tracker::arMultiGetTransMatHull(ARMarkerInfo *marker_info, int marker_num, ARMultiMarkerInfoT *config)
{
	//return arMultiGetTransMat(marker_info, marker_num, config);

	int numInPoints=0;
	std::vector<int> trackedMarkers;
	int trackedCenterX=-1,trackedCenterY=-1;

	//const int indices[4] = {idx0,idx1,idx2,idx3};
	//rpp_vec ppos2d[4];
	//rpp_vec ppos3d[4];

	const int maxHullPoints = 16;
	int indices[maxHullPoints];
	rpp_vec ppos2d[maxHullPoints];
	rpp_vec ppos3d[maxHullPoints];


	// create an array of 2D points and keep references
	// to the source points
	//
	for(int i=0; i<marker_num; i++)
	{
		int mId = marker_info[i].id;
		int configIdx = -1;

		for(int j=0; j<config->marker_num; j++)
			if(config->marker[j].patt_id==mId)
			{
				configIdx = j;
				break;
			}

		if(configIdx==-1)
			continue;

		trackedMarkers.push_back(i);

		for(int c=0; c<4; c++)
		{
			int dir = marker_info[i].dir;
			int cornerIdx = (c+4-dir)%4;
			hullInPoints[numInPoints].x = (MarkerPoint::coord_type)marker_info[i].vertex[cornerIdx][0];
			hullInPoints[numInPoints].y = (MarkerPoint::coord_type)marker_info[i].vertex[cornerIdx][1];
			hullInPoints[numInPoints].cornerIdx = c;
			hullInPoints[numInPoints].markerIdx = configIdx;
			numInPoints++;
		}

		if(numInPoints>=MAX_HULL_POINTS)
			break;
	}


	// next get the convex hull of all points
	// (decrease amount by one to ignore last point, which is identical to first point)
	//
	int numHullPoints = nearHull_2D(hullInPoints, numInPoints, numInPoints, hullOutPoints)-1;
	int idx0,idx1,idx2,idx3;


	if(hullTrackingMode==HULL_FOUR && numHullPoints != 0)
	{
		// find those points with furthest distance and that lie on
		// opposite parts of the hull. this fixes the first two points of our quad.
		//
		findLongestDiameter(hullOutPoints, numHullPoints, idx0,idx1);
		assert(iabs(idx0-idx1)>0);

		// find the point that is furthest away of the line
		// of our first two points. this fixes the third point of the quad
		findFurthestAway(hullOutPoints, numHullPoints, idx0,idx1, idx2);
		sortIntegers(idx0,idx1, idx2);

		// of all other points find the one that results in
		// a quad with the largest area.
		maximizeArea(hullOutPoints, numHullPoints, idx0,idx1,idx2,idx3);

		// now that we have all four points we must sort them...
		//
		sortInLastInteger(idx0,idx1,idx2, idx3);

		numHullPoints = 4;
		indices[0] = idx0;
		indices[1] = idx1;
		indices[2] = idx2;
		indices[3] = idx3;
	}
	else
	{
		if(numHullPoints>maxHullPoints)
			numHullPoints = maxHullPoints;

		for(int i=0; i<numHullPoints; i++)
			indices[i] = i;
	}

	assert(numHullPoints<=maxHullPoints);

	// create arrays of vertices for the 2D and 3D positions
	// 
	//const int indices[4] = {idx0,idx1,idx2,idx3};
	//rpp_vec ppos2d[4];
	//rpp_vec ppos3d[4];

	for(int i=0; i<numHullPoints; i++)
	{
		//int idx = indices[(i+1)%4];
		int idx = indices[i];
		const MarkerPoint& pt = hullOutPoints[idx];

		trackedCorners.push_back(CornerPoint(pt.x,pt.y));

		trackedCenterX += pt.x;
		trackedCenterY += pt.y;

		ppos2d[i][0] = pt.x;
		ppos2d[i][1] = pt.y;
		ppos2d[i][2] = 1.0f;

		assert(pt.markerIdx < config->marker_num);
		const ARMultiEachMarkerInfoT& markerInfo = config->marker[pt.markerIdx];
		int cornerIdx = pt.cornerIdx;

		ppos3d[i][0] = markerInfo.pos3d[cornerIdx][0];
		ppos3d[i][1] = markerInfo.pos3d[cornerIdx][1];
		ppos3d[i][2] = 0;
	}

	trackedCenterX /= 4;
	trackedCenterY /= 4;


	// prepare structures and data we need for input and output
	// parameters of the rpp functions
	const rpp_float cc[2] = {arCamera->mat[0][2],arCamera->mat[1][2]};
	const rpp_float fc[2] = {arCamera->mat[0][0],arCamera->mat[1][1]};
	rpp_float err = 1e+20;
	rpp_mat R, R_init;
	rpp_vec t;

	if(poseEstimator==POSE_ESTIMATOR_RPP)
	{
		robustPlanarPose(err,R,t,cc,fc,ppos3d,ppos2d,numHullPoints,R_init, true,0,0,0);
		if(err>1e+10)
			return(-1); // an actual error has occurred in robustPlanarPose()

		for(int k=0; k<3; k++)
		{
			config->trans[k][3] = (ARFloat)t[k];
			for(int j=0; j<3; j++)
				config->trans[k][j] = (ARFloat)R[k][j];
		}
	}
	else
	{
		ARFloat rot[3][3];

		int minIdx=-1, minDist=0x7fffffff;
		for(size_t i=0; i<trackedMarkers.size(); i++)
		{
			assert(trackedMarkers[i]>=0 && trackedMarkers[i]<marker_num);
			int idx = trackedMarkers[i];
			const ARMarkerInfo& mInfo = marker_info[idx];
			int dx = trackedCenterX-(int)mInfo.pos[0], dy = trackedCenterY-(int)mInfo.pos[1];
			int d = dx*dx + dy*dy;
			if(d<minDist)
			{
				minDist = d;
				minIdx = (int)idx;
			}
		}


		//trackedCorners.push_back(CornerPoint((int)marker_info[minIdx].pos[0],(int)marker_info[minIdx].pos[1]));

        if(minIdx >= 0) {
            return  -1;
        }

		if(arGetInitRot(marker_info+minIdx, arCamera->mat, rot )<0)
			return -1;


		// finally use the normal pose estimator to get the pose
		//
		ARFloat tmp_pos2d[maxHullPoints][2], tmp_pos3d[maxHullPoints][2];

		for(int i=0; i<numHullPoints; i++)
		{
			tmp_pos2d[i][0] = (ARFloat)ppos2d[i][0];
			tmp_pos2d[i][1] = (ARFloat)ppos2d[i][1];
			tmp_pos3d[i][0] = (ARFloat)ppos3d[i][0];
			tmp_pos3d[i][1] = (ARFloat)ppos3d[i][1];
		}

		for(int i=0; i<AR_GET_TRANS_MAT_MAX_LOOP_COUNT; i++ )
		{
			err = arGetTransMat3(rot, tmp_pos2d, tmp_pos3d, numHullPoints, config->trans, arCamera);
			if(err<AR_GET_TRANS_MAT_MAX_FIT_ERROR)
				break;
		}
	}

    return (ARFloat)err;
}