Exemplo n.º 1
0
void _imd_calc_bounds(iIMDShape *s, Vector3f *p, int size)
{
	int32_t xmax, ymax, zmax, count;
	double dx, dy, dz, rad_sq, rad, old_to_p_sq, old_to_p, old_to_new;
	double xspan, yspan, zspan, maxspan;
	Vector3f dia1, dia2, cen;
	Vector3f vxmin(0, 0, 0), vymin(0, 0, 0), vzmin(0, 0, 0),
	         vxmax(0, 0, 0), vymax(0, 0, 0), vzmax(0, 0, 0);

	s->max.x = s->max.y = s->max.z = -FP12_MULTIPLIER;
	s->min.x = s->min.y = s->min.z = FP12_MULTIPLIER;

	vxmax.x = vymax.y = vzmax.z = -FP12_MULTIPLIER;
	vxmin.x = vymin.y = vzmin.z = FP12_MULTIPLIER;

	// set up bounding data for minimum number of vertices
	for (count = 0; count < size; p++, count++)
	{
		if (p->x > s->max.x)
		{
			s->max.x = p->x;
		}
		if (p->x < s->min.x)
		{
			s->min.x = p->x;
		}

		if (p->y > s->max.y)
		{
			s->max.y = p->y;
		}
		if (p->y < s->min.y)
		{
			s->min.y = p->y;
		}

		if (p->z > s->max.z)
		{
			s->max.z = p->z;
		}
		if (p->z < s->min.z)
		{
			s->min.z = p->z;
		}

		// for tight sphere calculations
		if (p->x < vxmin.x)
		{
			vxmin.x = p->x;
			vxmin.y = p->y;
			vxmin.z = p->z;
		}

		if (p->x > vxmax.x)
		{
			vxmax.x = p->x;
			vxmax.y = p->y;
			vxmax.z = p->z;
		}

		if (p->y < vymin.y)
		{
			vymin.x = p->x;
			vymin.y = p->y;
			vymin.z = p->z;
		}

		if (p->y > vymax.y)
		{
			vymax.x = p->x;
			vymax.y = p->y;
			vymax.z = p->z;
		}

		if (p->z < vzmin.z)
		{
			vzmin.x = p->x;
			vzmin.y = p->y;
			vzmin.z = p->z;
		}

		if (p->z > vzmax.z)
		{
			vzmax.x = p->x;
			vzmax.y = p->y;
			vzmax.z = p->z;
		}
	}

	// no need to scale an IMD shape (only FSD)
	xmax = MAX(s->max.x, -s->min.x);
	ymax = MAX(s->max.y, -s->min.y);
	zmax = MAX(s->max.z, -s->min.z);

	s->radius = MAX(xmax, MAX(ymax, zmax));
	s->sradius = sqrtf(xmax * xmax + ymax * ymax + zmax * zmax);

// START: tight bounding sphere

	// set xspan = distance between 2 points xmin & xmax (squared)
	dx = vxmax.x - vxmin.x;
	dy = vxmax.y - vxmin.y;
	dz = vxmax.z - vxmin.z;
	xspan = dx * dx + dy * dy + dz * dz;

	// same for yspan
	dx = vymax.x - vymin.x;
	dy = vymax.y - vymin.y;
	dz = vymax.z - vymin.z;
	yspan = dx * dx + dy * dy + dz * dz;

	// and ofcourse zspan
	dx = vzmax.x - vzmin.x;
	dy = vzmax.y - vzmin.y;
	dz = vzmax.z - vzmin.z;
	zspan = dx * dx + dy * dy + dz * dz;

	// set points dia1 & dia2 to maximally seperated pair
	// assume xspan biggest
	dia1 = vxmin;
	dia2 = vxmax;
	maxspan = xspan;

	if (yspan > maxspan)
	{
		maxspan = yspan;
		dia1 = vymin;
		dia2 = vymax;
	}

	if (zspan > maxspan)
	{
		dia1 = vzmin;
		dia2 = vzmax;
	}

	// dia1, dia2 diameter of initial sphere
	cen.x = (dia1.x + dia2.x) / 2.;
	cen.y = (dia1.y + dia2.y) / 2.;
	cen.z = (dia1.z + dia2.z) / 2.;

	// calc initial radius
	dx = dia2.x - cen.x;
	dy = dia2.y - cen.y;
	dz = dia2.z - cen.z;

	rad_sq = dx * dx + dy * dy + dz * dz;
	rad = sqrt((double)rad_sq);

	// second pass (find tight sphere)
	for (p = s->points; p < s->points + s->npoints; p++)
	{
		dx = p->x - cen.x;
		dy = p->y - cen.y;
		dz = p->z - cen.z;
		old_to_p_sq = dx * dx + dy * dy + dz * dz;

		// do r**2 first
		if (old_to_p_sq > rad_sq)
		{
			// this point outside current sphere
			old_to_p = sqrt((double)old_to_p_sq);
			// radius of new sphere
			rad = (rad + old_to_p) / 2.;
			// rad**2 for next compare
			rad_sq = rad * rad;
			old_to_new = old_to_p - rad;
			// centre of new sphere
			cen.x = (rad * cen.x + old_to_new * p->x) / old_to_p;
			cen.y = (rad * cen.y + old_to_new * p->y) / old_to_p;
			cen.z = (rad * cen.z + old_to_new * p->z) / old_to_p;
		}
	}

	s->ocen = cen;

// END: tight bounding sphere
}
Exemplo n.º 2
0
static bool _imd_load_points( const char **ppFileData, iIMDShape *s )
{
    Vector3f *p = NULL;
    int32_t xmax, ymax, zmax;
    double dx, dy, dz, rad_sq, rad, old_to_p_sq, old_to_p, old_to_new;
    double xspan, yspan, zspan, maxspan;
    Vector3f dia1, dia2, cen;
    Vector3f vxmin(0, 0, 0), vymin(0, 0, 0), vzmin(0, 0, 0),
             vxmax(0, 0, 0), vymax(0, 0, 0), vzmax(0, 0, 0);

    //load the points then pass through a second time to setup bounding datavalues
    s->points = (Vector3f*)malloc(sizeof(Vector3f) * s->npoints);
    if (s->points == NULL)
    {
        return false;
    }

    // Read in points and remove duplicates (!)
    if ( ReadPoints( ppFileData, s ) == false )
    {
        free(s->points);
        s->points = NULL;
        return false;
    }

    s->max.x = s->max.y = s->max.z = -FP12_MULTIPLIER;
    s->min.x = s->min.y = s->min.z = FP12_MULTIPLIER;

    vxmax.x = vymax.y = vzmax.z = -FP12_MULTIPLIER;
    vxmin.x = vymin.y = vzmin.z = FP12_MULTIPLIER;

    // set up bounding data for minimum number of vertices
    for (p = s->points; p < s->points + s->npoints; p++)
    {
        if (p->x > s->max.x)
        {
            s->max.x = p->x;
        }
        if (p->x < s->min.x)
        {
            s->min.x = p->x;
        }

        if (p->y > s->max.y)
        {
            s->max.y = p->y;
        }
        if (p->y < s->min.y)
        {
            s->min.y = p->y;
        }

        if (p->z > s->max.z)
        {
            s->max.z = p->z;
        }
        if (p->z < s->min.z)
        {
            s->min.z = p->z;
        }

        // for tight sphere calculations
        if (p->x < vxmin.x)
        {
            vxmin.x = p->x;
            vxmin.y = p->y;
            vxmin.z = p->z;
        }

        if (p->x > vxmax.x)
        {
            vxmax.x = p->x;
            vxmax.y = p->y;
            vxmax.z = p->z;
        }

        if (p->y < vymin.y)
        {
            vymin.x = p->x;
            vymin.y = p->y;
            vymin.z = p->z;
        }

        if (p->y > vymax.y)
        {
            vymax.x = p->x;
            vymax.y = p->y;
            vymax.z = p->z;
        }

        if (p->z < vzmin.z)
        {
            vzmin.x = p->x;
            vzmin.y = p->y;
            vzmin.z = p->z;
        }

        if (p->z > vzmax.z)
        {
            vzmax.x = p->x;
            vzmax.y = p->y;
            vzmax.z = p->z;
        }
    }

    // no need to scale an IMD shape (only FSD)
    xmax = MAX(s->max.x, -s->min.x);
    ymax = MAX(s->max.y, -s->min.y);
    zmax = MAX(s->max.z, -s->min.z);

    s->radius = MAX(xmax, MAX(ymax, zmax));
    s->sradius = sqrtf(xmax*xmax + ymax*ymax + zmax*zmax);

// START: tight bounding sphere

    // set xspan = distance between 2 points xmin & xmax (squared)
    dx = vxmax.x - vxmin.x;
    dy = vxmax.y - vxmin.y;
    dz = vxmax.z - vxmin.z;
    xspan = dx*dx + dy*dy + dz*dz;

    // same for yspan
    dx = vymax.x - vymin.x;
    dy = vymax.y - vymin.y;
    dz = vymax.z - vymin.z;
    yspan = dx*dx + dy*dy + dz*dz;

    // and ofcourse zspan
    dx = vzmax.x - vzmin.x;
    dy = vzmax.y - vzmin.y;
    dz = vzmax.z - vzmin.z;
    zspan = dx*dx + dy*dy + dz*dz;

    // set points dia1 & dia2 to maximally seperated pair
    // assume xspan biggest
    dia1 = vxmin;
    dia2 = vxmax;
    maxspan = xspan;

    if (yspan > maxspan)
    {
        maxspan = yspan;
        dia1 = vymin;
        dia2 = vymax;
    }

    if (zspan > maxspan)
    {
        dia1 = vzmin;
        dia2 = vzmax;
    }

    // dia1, dia2 diameter of initial sphere
    cen.x = (dia1.x + dia2.x) / 2.;
    cen.y = (dia1.y + dia2.y) / 2.;
    cen.z = (dia1.z + dia2.z) / 2.;

    // calc initial radius
    dx = dia2.x - cen.x;
    dy = dia2.y - cen.y;
    dz = dia2.z - cen.z;

    rad_sq = dx*dx + dy*dy + dz*dz;
    rad = sqrt((double)rad_sq);

    // second pass (find tight sphere)
    for (p = s->points; p < s->points + s->npoints; p++)
    {
        dx = p->x - cen.x;
        dy = p->y - cen.y;
        dz = p->z - cen.z;
        old_to_p_sq = dx*dx + dy*dy + dz*dz;

        // do r**2 first
        if (old_to_p_sq>rad_sq)
        {
            // this point outside current sphere
            old_to_p = sqrt((double)old_to_p_sq);
            // radius of new sphere
            rad = (rad + old_to_p) / 2.;
            // rad**2 for next compare
            rad_sq = rad*rad;
            old_to_new = old_to_p - rad;
            // centre of new sphere
            cen.x = (rad*cen.x + old_to_new*p->x) / old_to_p;
            cen.y = (rad*cen.y + old_to_new*p->y) / old_to_p;
            cen.z = (rad*cen.z + old_to_new*p->z) / old_to_p;
        }
    }

    s->ocen = cen;

// END: tight bounding sphere

    return true;
}