Ejemplo n.º 1
0
double complex
conj(double complex z)
{

	return (cpack(creal(z), -cimag(z)));
}
Ejemplo n.º 2
0
double complex
csinh(double complex z)
{
	double x, y, h;
	int32_t hx, hy, ix, iy, lx, ly;

	x = creal(z);
	y = cimag(z);

	EXTRACT_WORDS(hx, lx, x);
	EXTRACT_WORDS(hy, ly, y);

	ix = 0x7fffffff & hx;
	iy = 0x7fffffff & hy;

	/* Handle the nearly-non-exceptional cases where x and y are finite. */
	if (ix < 0x7ff00000 && iy < 0x7ff00000) {
		if ((iy | ly) == 0)
			return (cpack(sinh(x), y));
		if (ix < 0x40360000)	/* small x: normal case */
			return (cpack(sinh(x) * cos(y), cosh(x) * sin(y)));

		/* |x| >= 22, so cosh(x) ~= exp(|x|) */
		if (ix < 0x40862e42) {
			/* x < 710: exp(|x|) won't overflow */
			h = exp(fabs(x)) * 0.5;
			return (cpack(copysign(h, x) * cos(y), h * sin(y)));
		} else if (ix < 0x4096bbaa) {
			/* x < 1455: scale to avoid overflow */
			z = __ldexp_cexp(cpack(fabs(x), y), -1);
			return (cpack(creal(z) * copysign(1, x), cimag(z)));
		} else {
			/* x >= 1455: the result always overflows */
			h = huge * x;
			return (cpack(h * cos(y), h * h * sin(y)));
		}
	}

	/*
	 * sinh(+-0 +- I Inf) = sign(d(+-0, dNaN))0 + I dNaN.
	 * The sign of 0 in the result is unspecified.  Choice = normally
	 * the same as dNaN.  Raise the invalid floating-point exception.
	 *
	 * sinh(+-0 +- I NaN) = sign(d(+-0, NaN))0 + I d(NaN).
	 * The sign of 0 in the result is unspecified.  Choice = normally
	 * the same as d(NaN).
	 */
	if ((ix | lx) == 0 && iy >= 0x7ff00000)
		return (cpack(copysign(0, x * (y - y)), y - y));

	/*
	 * sinh(+-Inf +- I 0) = +-Inf + I +-0.
	 *
	 * sinh(NaN +- I 0)   = d(NaN) + I +-0.
	 */
	if ((iy | ly) == 0 && ix >= 0x7ff00000) {
		if (((hx & 0xfffff) | lx) == 0)
			return (cpack(x, y));
		return (cpack(x, copysign(0, y)));
	}

	/*
	 * sinh(x +- I Inf) = dNaN + I dNaN.
	 * Raise the invalid floating-point exception for finite nonzero x.
	 *
	 * sinh(x + I NaN) = d(NaN) + I d(NaN).
	 * Optionally raises the invalid floating-point exception for finite
	 * nonzero x.  Choice = don't raise (except for signaling NaNs).
	 */
	if (ix < 0x7ff00000 && iy >= 0x7ff00000)
		return (cpack(y - y, x * (y - y)));

	/*
	 * sinh(+-Inf + I NaN)  = +-Inf + I d(NaN).
	 * The sign of Inf in the result is unspecified.  Choice = normally
	 * the same as d(NaN).
	 *
	 * sinh(+-Inf +- I Inf) = +Inf + I dNaN.
	 * The sign of Inf in the result is unspecified.  Choice = always +.
	 * Raise the invalid floating-point exception.
	 *
	 * sinh(+-Inf + I y)   = +-Inf cos(y) + I Inf sin(y)
	 */
	if (ix >= 0x7ff00000 && ((hx & 0xfffff) | lx) == 0) {
		if (iy >= 0x7ff00000)
			return (cpack(x * x, x * (y - y)));
		return (cpack(x * cos(y), INFINITY * sin(y)));
	}

	/*
	 * sinh(NaN + I NaN)  = d(NaN) + I d(NaN).
	 *
	 * sinh(NaN +- I Inf) = d(NaN) + I d(NaN).
	 * Optionally raises the invalid floating-point exception.
	 * Choice = raise.
	 *
	 * sinh(NaN + I y)    = d(NaN) + I d(NaN).
	 * Optionally raises the invalid floating-point exception for finite
	 * nonzero y.  Choice = don't raise (except for signaling NaNs).
	 */
	return (cpack((x * x) * (y - y), (x + x) * (y - y)));
}
Ejemplo n.º 3
0
void drawSnapping(const struct bContext *C, TransInfo *t)
{
	unsigned char col[4], selectedCol[4], activeCol[4];
	
	if (!activeSnap(t))
		return;
	
	UI_GetThemeColor3ubv(TH_TRANSFORM, col);
	col[3] = 128;
	
	UI_GetThemeColor3ubv(TH_SELECT, selectedCol);
	selectedCol[3] = 128;
	
	UI_GetThemeColor3ubv(TH_ACTIVE, activeCol);
	activeCol[3] = 192;
	
	if (t->spacetype == SPACE_VIEW3D) {
		if (validSnap(t)) {
			TransSnapPoint *p;
			View3D *v3d = CTX_wm_view3d(C);
			RegionView3D *rv3d = CTX_wm_region_view3d(C);
			float imat[4][4];
			float size;
			
			glDisable(GL_DEPTH_TEST);
			
			size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
			
			invert_m4_m4(imat, rv3d->viewmat);
			
			for (p = t->tsnap.points.first; p; p = p->next) {
				if (p == t->tsnap.selectedPoint) {
					glColor4ubv(selectedCol);
				}
				else {
					glColor4ubv(col);
				}
				
				drawcircball(GL_LINE_LOOP, p->co, ED_view3d_pixel_size(rv3d, p->co) * size * 0.75f, imat);
			}
			
			if (t->tsnap.status & POINT_INIT) {
				glColor4ubv(activeCol);
				
				drawcircball(GL_LINE_LOOP, t->tsnap.snapPoint, ED_view3d_pixel_size(rv3d, t->tsnap.snapPoint) * size, imat);
			}
			
			/* draw normal if needed */
			if (usingSnappingNormal(t) && validSnappingNormal(t)) {
				glColor4ubv(activeCol);
				
				glBegin(GL_LINES);
				glVertex3f(t->tsnap.snapPoint[0], t->tsnap.snapPoint[1], t->tsnap.snapPoint[2]);
				glVertex3f(t->tsnap.snapPoint[0] + t->tsnap.snapNormal[0],
				           t->tsnap.snapPoint[1] + t->tsnap.snapNormal[1],
				           t->tsnap.snapPoint[2] + t->tsnap.snapNormal[2]);
				glEnd();
			}
			
			if (v3d->zbuf)
				glEnable(GL_DEPTH_TEST);
		}
	}
	else if (t->spacetype == SPACE_IMAGE) {
		if (validSnap(t)) {
			/* This will not draw, and Im nor sure why - campbell */
#if 0
			float xuser_asp, yuser_asp;
			int wi, hi;
			float w, h;
			
			calc_image_view(G.sima, 'f');   // float
			myortho2(G.v2d->cur.xmin, G.v2d->cur.xmax, G.v2d->cur.ymin, G.v2d->cur.ymax);
			glLoadIdentity();
			
			ED_space_image_get_aspect(t->sa->spacedata.first, &xuser_aspx, &yuser_asp);
			ED_space_image_width(t->sa->spacedata.first, &wi, &hi);
			w = (((float)wi) / IMG_SIZE_FALLBACK) * G.sima->zoom * xuser_asp;
			h = (((float)hi) / IMG_SIZE_FALLBACK) * G.sima->zoom * yuser_asp;
			
			cpack(0xFFFFFF);
			glTranslate2fv(t->tsnap.snapPoint);
			
			//glRectf(0, 0, 1, 1);
			
			setlinestyle(0);
			cpack(0x0);
			fdrawline(-0.020 / w, 0, -0.1 / w, 0);
			fdrawline(0.1 / w, 0, 0.020 / w, 0);
			fdrawline(0, -0.020 / h, 0, -0.1 / h);
			fdrawline(0, 0.1 / h, 0, 0.020 / h);
			
			glTranslatef(-t->tsnap.snapPoint[0], -t->tsnap.snapPoint[1], 0.0f);
			setlinestyle(0);
#endif
		}
	}
	else if (t->spacetype == SPACE_NODE) {
		if (validSnap(t)) {
			ARegion *ar = CTX_wm_region(C);
			TransSnapPoint *p;
			float size;
			
			size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
			
			glEnable(GL_BLEND);
			
			for (p = t->tsnap.points.first; p; p = p->next) {
				if (p == t->tsnap.selectedPoint) {
					glColor4ubv(selectedCol);
				}
				else {
					glColor4ubv(col);
				}
				
				ED_node_draw_snap(&ar->v2d, p->co, size, 0);
			}
			
			if (t->tsnap.status & POINT_INIT) {
				glColor4ubv(activeCol);
				
				ED_node_draw_snap(&ar->v2d, t->tsnap.snapPoint, size, t->tsnap.snapNodeBorder);
			}
			
			glDisable(GL_BLEND);
		}
	}
}
Ejemplo n.º 4
0
static void playanim_toscreen(PlayState *ps, PlayAnimPict *picture, struct ImBuf *ibuf, int fontid, int fstep)
{
    float offsx, offsy;

    if (ibuf == NULL) {
        printf("%s: no ibuf for picture '%s'\n", __func__, picture ? picture->name : "<NIL>");
        return;
    }
    if (ibuf->rect == NULL && ibuf->rect_float) {
        IMB_rect_from_float(ibuf);
        imb_freerectfloatImBuf(ibuf);
    }
    if (ibuf->rect == NULL)
        return;

    GHOST_ActivateWindowDrawingContext(g_WS.ghost_window);

    /* offset within window */
    offsx = 0.5f * (((float)ps->win_x - ps->zoom * ibuf->x) / (float)ps->win_x);
    offsy = 0.5f * (((float)ps->win_y - ps->zoom * ibuf->y) / (float)ps->win_y);

    CLAMP(offsx, 0.0f, 1.0f);
    CLAMP(offsy, 0.0f, 1.0f);
    glRasterPos2f(offsx, offsy);

    glClearColor(0.1, 0.1, 0.1, 0.0);
    glClear(GL_COLOR_BUFFER_BIT);

    /* checkerboard for case alpha */
    if (ibuf->planes == 32) {
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

        fdrawcheckerboard(offsx, offsy, offsx + (ps->zoom * ibuf->x) / (float)ps->win_x, offsy + (ps->zoom * ibuf->y) / (float)ps->win_y);
    }

    glDrawPixels(ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);

    glDisable(GL_BLEND);

    pupdate_time();

    if (picture && (g_WS.qual & (WS_QUAL_SHIFT | WS_QUAL_LMOUSE)) && (fontid != -1)) {
        int sizex, sizey;
        float fsizex_inv, fsizey_inv;
        char str[32 + FILE_MAX];
        cpack(-1);
        BLI_snprintf(str, sizeof(str), "%s | %.2f frames/s", picture->name, fstep / swaptime);

        playanim_window_get_size(&sizex, &sizey);
        fsizex_inv = 1.0f / sizex;
        fsizey_inv = 1.0f / sizey;

        BLF_enable(fontid, BLF_ASPECT);
        BLF_aspect(fontid, fsizex_inv, fsizey_inv, 1.0f);
        BLF_position(fontid, 10.0f * fsizex_inv, 10.0f * fsizey_inv, 0.0f);
        BLF_draw(fontid, str, sizeof(str));
    }

    GHOST_SwapWindowBuffers(g_WS.ghost_window);
}
Ejemplo n.º 5
0
/*
 * cacos(z) = PI/2 - casin(z)
 * but do the computation carefully so cacos(z) is accurate when z is
 * close to 1.
 *
 * cacos(z) = PI/2 - z + O(z^3)   as z -> 0
 *
 * cacos(z) = -sign(y)*I*clog(z) + O(1/z^2)   as z -> infinity
 * The above formula works for the real part as well, because
 * Re(cacos(z)) = atan2(fabs(y), x) + O(y/z^3)
 *    as z -> infinity, uniformly in y
 */
double complex
cacos(double complex z)
{
	double x, y, ax, ay, rx, ry, B, sqrt_A2mx2, new_x;
	int sx, sy;
	int B_is_usable;
	double complex w;

	x = creal(z);
	y = cimag(z);
	sx = signbit(x);
	sy = signbit(y);
	ax = fabs(x);
	ay = fabs(y);

	if (isnan(x) || isnan(y)) {
		/* cacos(+-Inf + I*NaN) = NaN + I*opt(-)Inf */
		if (isinf(x))
			return (cpack(y + y, -INFINITY));
		/* cacos(NaN + I*+-Inf) = NaN + I*-+Inf */
		if (isinf(y))
			return (cpack(x + x, -y));
		/* cacos(0 + I*NaN) = PI/2 + I*NaN with inexact */
		if (x == 0)
			return (cpack(pio2_hi + pio2_lo, y + y));
		/*
		 * All other cases involving NaN return NaN + I*NaN.
		 * C99 leaves it optional whether to raise invalid if one of
		 * the arguments is not NaN, so we opt not to raise it.
		 */
		return (cpack(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
	}

	if (ax > RECIP_EPSILON || ay > RECIP_EPSILON) {
		/* clog...() will raise inexact unless x or y is infinite. */
		w = clog_for_large_values(z);
		rx = fabs(cimag(w));
		ry = creal(w) + m_ln2;
		if (sy == 0)
			ry = -ry;
		return (cpack(rx, ry));
	}

	/* Avoid spuriously raising inexact for z = 1. */
	if (x == 1 && y == 0)
		return (cpack(0, -y));

	/* All remaining cases are inexact. */
	raise_inexact();

	if (ax < SQRT_6_EPSILON / 4 && ay < SQRT_6_EPSILON / 4)
		return (cpack(pio2_hi - (x - pio2_lo), -y));

	do_hard_work(ay, ax, &ry, &B_is_usable, &B, &sqrt_A2mx2, &new_x);
	if (B_is_usable) {
		if (sx == 0)
			rx = acos(B);
		else
			rx = acos(-B);
	} else {
		if (sx == 0)
			rx = atan2(sqrt_A2mx2, new_x);
		else
			rx = atan2(sqrt_A2mx2, -new_x);
	}
	if (sy == 0)
		ry = -ry;
	return (cpack(rx, ry));
}
Ejemplo n.º 6
0
/*
 * catanh(z) = log((1+z)/(1-z)) / 2
 *           = log1p(4*x / |z-1|^2) / 4
 *             + I * atan2(2*y, (1-x)*(1+x)-y*y) / 2
 *
 * catanh(z) = z + O(z^3)   as z -> 0
 *
 * catanh(z) = 1/z + sign(y)*I*PI/2 + O(1/z^3)   as z -> infinity
 * The above formula works for the real part as well, because
 * Re(catanh(z)) = x/|z|^2 + O(x/z^4)
 *    as z -> infinity, uniformly in x
 */
double complex
catanh(double complex z)
{
	double x, y, ax, ay, rx, ry;

	x = creal(z);
	y = cimag(z);
	ax = fabs(x);
	ay = fabs(y);

	/* This helps handle many cases. */
	if (y == 0 && ax <= 1)
		return (cpack(atanh(x), y));

	/* To ensure the same accuracy as atan(), and to filter out z = 0. */
	if (x == 0)
		return (cpack(x, atan(y)));

	if (isnan(x) || isnan(y)) {
		/* catanh(+-Inf + I*NaN) = +-0 + I*NaN */
		if (isinf(x))
			return (cpack(copysign(0, x), y + y));
		/* catanh(NaN + I*+-Inf) = sign(NaN)0 + I*+-PI/2 */
		if (isinf(y))
			return (cpack(copysign(0, x),
				      copysign(pio2_hi + pio2_lo, y)));
		/*
		 * All other cases involving NaN return NaN + I*NaN.
		 * C99 leaves it optional whether to raise invalid if one of
		 * the arguments is not NaN, so we opt not to raise it.
		 */
		return (cpack(x + 0.0L + (y + 0), x + 0.0L + (y + 0)));
	}

	if (ax > RECIP_EPSILON || ay > RECIP_EPSILON)
		return (cpack(real_part_reciprocal(x, y),
			      copysign(pio2_hi + pio2_lo, y)));

	if (ax < SQRT_3_EPSILON / 2 && ay < SQRT_3_EPSILON / 2) {
		/*
		 * z = 0 was filtered out above.  All other cases must raise
		 * inexact, but this is the only only that needs to do it
		 * explicitly.
		 */
		raise_inexact();
		return (z);
	}

	if (ax == 1 && ay < DBL_EPSILON)
		rx = (m_ln2 - log(ay)) / 2;
	else
		rx = log1p(4 * ax / sum_squares(ax - 1, ay)) / 4;

	if (ax == 1)
		ry = atan2(2, -ay) / 2;
	else if (ay < DBL_EPSILON)
		ry = atan2(2 * ay, (1 - ax) * (1 + ax)) / 2;
	else
		ry = atan2(2 * ay, (1 - ax) * (1 + ax) - ay * ay) / 2;

	return (cpack(copysign(rx, x), copysign(ry, y)));
}
Ejemplo n.º 7
0
static void ruler_info_draw_pixel(const struct bContext *C, ARegion *ar, void *arg)
{
	Scene *scene = CTX_data_scene(C);
	UnitSettings *unit = &scene->unit;
	RulerItem *ruler_item;
	RulerInfo *ruler_info = arg;
	RegionView3D *rv3d = ruler_info->ar->regiondata;
//	ARegion *ar = ruler_info->ar;
	const float cap_size = 4.0f;
	const float bg_margin = 4.0f * U.pixelsize;
	const float bg_radius = 4.0f * U.pixelsize;
	const float arc_size = 64.0f * U.pixelsize;
#define ARC_STEPS 24
	const int arc_steps = ARC_STEPS;
	int i;
	//unsigned int color_act = 0x666600;
	unsigned int color_act = 0xffffff;
	unsigned int color_base = 0x0;
	unsigned char color_back[4] = {0xff, 0xff, 0xff, 0x80};
	unsigned char color_text[3];
	unsigned char color_wire[3];

	/* anti-aliased lines for more consistent appearance */
	glEnable(GL_LINE_SMOOTH);

	BLF_enable(blf_mono_font, BLF_ROTATION);
	BLF_size(blf_mono_font, 14 * U.pixelsize, U.dpi);
	BLF_rotation(blf_mono_font, 0.0f);

	UI_GetThemeColor3ubv(TH_TEXT, color_text);
	UI_GetThemeColor3ubv(TH_WIRE, color_wire);

	for (ruler_item = ruler_info->items.first, i = 0; ruler_item; ruler_item = ruler_item->next, i++) {
		const bool is_act = (i == ruler_info->item_active);
		float dir_ruler[2];
		float co_ss[3][2];
		int j;

		/* should these be checked? - ok for now not to */
		for (j = 0; j < 3; j++) {
			ED_view3d_project_float_global(ar, ruler_item->co[j], co_ss[j], V3D_PROJ_TEST_NOP);
		}

		glEnable(GL_BLEND);

		cpack(is_act ? color_act : color_base);

		if (ruler_item->flag & RULERITEM_USE_ANGLE) {
			glBegin(GL_LINE_STRIP);
			for (j = 0; j < 3; j++) {
				glVertex2fv(co_ss[j]);
			}
			glEnd();
			cpack(0xaaaaaa);
			setlinestyle(3);
			glBegin(GL_LINE_STRIP);
			for (j = 0; j < 3; j++) {
				glVertex2fv(co_ss[j]);
			}
			glEnd();
			setlinestyle(0);

			/* arc */
			{
				float dir_tmp[3];
				float co_tmp[3];
				float arc_ss_coords[ARC_STEPS + 1][2];

				float dir_a[3];
				float dir_b[3];
				float quat[4];
				float axis[3];
				float angle;
				const float px_scale = (ED_view3d_pixel_size(rv3d, ruler_item->co[1]) *
				                        min_fff(arc_size,
				                                len_v2v2(co_ss[0], co_ss[1]) / 2.0f,
				                                len_v2v2(co_ss[2], co_ss[1]) / 2.0f));

				sub_v3_v3v3(dir_a, ruler_item->co[0], ruler_item->co[1]);
				sub_v3_v3v3(dir_b, ruler_item->co[2], ruler_item->co[1]);
				normalize_v3(dir_a);
				normalize_v3(dir_b);

				cross_v3_v3v3(axis, dir_a, dir_b);
				angle = angle_normalized_v3v3(dir_a, dir_b);

				axis_angle_to_quat(quat, axis, angle / arc_steps);

				copy_v3_v3(dir_tmp, dir_a);

				glColor3ubv(color_wire);

				for (j = 0; j <= arc_steps; j++) {
					madd_v3_v3v3fl(co_tmp, ruler_item->co[1], dir_tmp, px_scale);
					ED_view3d_project_float_global(ar, co_tmp, arc_ss_coords[j], V3D_PROJ_TEST_NOP);
					mul_qt_v3(quat, dir_tmp);
				}

				glEnableClientState(GL_VERTEX_ARRAY);
				glVertexPointer(2, GL_FLOAT, 0, arc_ss_coords);
				glDrawArrays(GL_LINE_STRIP, 0, arc_steps + 1);
				glDisableClientState(GL_VERTEX_ARRAY);
			}

			/* text */
			{
				char numstr[256];
				float numstr_size[2];
				float pos[2];
				const int prec = 2;  /* XXX, todo, make optional */

				ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);

				BLF_width_and_height(blf_mono_font, numstr, &numstr_size[0], &numstr_size[1]);

				pos[0] = co_ss[1][0] + (cap_size * 2.0f);
				pos[1] = co_ss[1][1] - (numstr_size[1] / 2.0f);

				/* draw text (bg) */
				glColor4ubv(color_back);
				uiSetRoundBox(UI_CNR_ALL);
				uiRoundBox(pos[0] - bg_margin,                  pos[1] - bg_margin,
				           pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1],
				           bg_radius);
				/* draw text */
				glColor3ubv(color_text);
				BLF_position(blf_mono_font, pos[0], pos[1], 0.0f);
				BLF_rotation(blf_mono_font, 0.0f);
				BLF_draw(blf_mono_font, numstr, sizeof(numstr));
			}

			/* capping */
			{
				float rot_90_vec_a[2];
				float rot_90_vec_b[2];
				float cap[2];

				sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[1]);
				rot_90_vec_a[0] = -dir_ruler[1];
				rot_90_vec_a[1] =  dir_ruler[0];
				normalize_v2(rot_90_vec_a);

				sub_v2_v2v2(dir_ruler, co_ss[1], co_ss[2]);
				rot_90_vec_b[0] = -dir_ruler[1];
				rot_90_vec_b[1] =  dir_ruler[0];
				normalize_v2(rot_90_vec_b);

				glEnable(GL_BLEND);

				glColor3ubv(color_wire);

				glBegin(GL_LINES);

				madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, cap_size);
				glVertex2fv(cap);
				madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec_a, -cap_size);
				glVertex2fv(cap);

				madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, cap_size);
				glVertex2fv(cap);
				madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec_b, -cap_size);
				glVertex2fv(cap);

				/* angle vertex */
				glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] - cap_size);
				glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] + cap_size);
				glVertex2f(co_ss[1][0] - cap_size, co_ss[1][1] + cap_size);
				glVertex2f(co_ss[1][0] + cap_size, co_ss[1][1] - cap_size);
				glEnd();

				glDisable(GL_BLEND);
			}
		}
		else {
			glBegin(GL_LINE_STRIP);
			for (j = 0; j < 3; j += 2) {
				glVertex2fv(co_ss[j]);
			}
			glEnd();
			cpack(0xaaaaaa);
			setlinestyle(3);
			glBegin(GL_LINE_STRIP);
			for (j = 0; j < 3; j += 2) {
				glVertex2fv(co_ss[j]);
			}
			glEnd();
			setlinestyle(0);

			sub_v2_v2v2(dir_ruler, co_ss[0], co_ss[2]);

			/* text */
			{
				char numstr[256];
				float numstr_size[2];
				const int prec = 6;  /* XXX, todo, make optional */
				float pos[2];

				ruler_item_as_string(ruler_item, unit, numstr, sizeof(numstr), prec);

				BLF_width_and_height(blf_mono_font, numstr, &numstr_size[0], &numstr_size[1]);

				mid_v2_v2v2(pos, co_ss[0], co_ss[2]);

				/* center text */
				pos[0] -= numstr_size[0] / 2.0f;
				pos[1] -= numstr_size[1] / 2.0f;

				/* draw text (bg) */
				glColor4ubv(color_back);
				uiSetRoundBox(UI_CNR_ALL);
				uiRoundBox(pos[0] - bg_margin,                  pos[1] - bg_margin,
				           pos[0] + bg_margin + numstr_size[0], pos[1] + bg_margin + numstr_size[1],
				           bg_radius);
				/* draw text */
				glColor3ubv(color_text);
				BLF_position(blf_mono_font, pos[0], pos[1], 0.0f);
				BLF_draw(blf_mono_font, numstr, sizeof(numstr));
			}

			/* capping */
			{
				float rot_90_vec[2] = {-dir_ruler[1], dir_ruler[0]};
				float cap[2];

				normalize_v2(rot_90_vec);

				glEnable(GL_BLEND);
				glColor3ubv(color_wire);

				glBegin(GL_LINES);
				madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, cap_size);
				glVertex2fv(cap);
				madd_v2_v2v2fl(cap, co_ss[0], rot_90_vec, -cap_size);
				glVertex2fv(cap);

				madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, cap_size);
				glVertex2fv(cap);
				madd_v2_v2v2fl(cap, co_ss[2], rot_90_vec, -cap_size);
				glVertex2fv(cap);
				glEnd();

				glDisable(GL_BLEND);
			}
		}
	}

	glDisable(GL_LINE_SMOOTH);

	BLF_disable(blf_mono_font, BLF_ROTATION);

#undef ARC_STEPS

	/* draw snap */
	if ((ruler_info->snap_flag & RULER_SNAP_OK) && (ruler_info->state == RULER_STATE_DRAG)) {
		ruler_item = ruler_item_active_get(ruler_info);
		if (ruler_item) {
			/* size from drawSnapping */
			const float size = 2.5f * UI_GetThemeValuef(TH_VERTEX_SIZE);
			float co_ss[3];
			ED_view3d_project_float_global(ar, ruler_item->co[ruler_item->co_index], co_ss, V3D_PROJ_TEST_NOP);

			cpack(color_act);
			circ(co_ss[0], co_ss[1], size * U.pixelsize);
		}
	}

}
Ejemplo n.º 8
0
double complex
ctanh(double complex z)
{
	double x, y;
	double t, beta, s, rho, denom;
	uint32_t hx, ix, lx;

	x = creal(z);
	y = cimag(z);

	EXTRACT_WORDS(hx, lx, x);
	ix = hx & 0x7fffffff;

	/*
	 * ctanh(NaN + i 0) = NaN + i 0
	 *
	 * ctanh(NaN + i y) = NaN + i NaN		for y != 0
	 *
	 * The imaginary part has the sign of x*sin(2*y), but there's no
	 * special effort to get this right.
	 *
	 * ctanh(+-Inf +- i Inf) = +-1 +- 0
	 *
	 * ctanh(+-Inf + i y) = +-1 + 0 sin(2y)		for y finite
	 *
	 * The imaginary part of the sign is unspecified.  This special
	 * case is only needed to avoid a spurious invalid exception when
	 * y is infinite.
	 */
	if (ix >= 0x7ff00000) {
		if ((ix & 0xfffff) | lx)	/* x is NaN */
			return (cpack(x, (y == 0 ? y : x * y)));
		SET_HIGH_WORD(x, hx - 0x40000000);	/* x = copysign(1, x) */
		return (cpack(x, copysign(0, isinf(y) ? y : sin(y) * cos(y))));
	}

	/*
	 * ctanh(x + i NAN) = NaN + i NaN
	 * ctanh(x +- i Inf) = NaN + i NaN
	 */
	if (!isfinite(y))
		return (cpack(y - y, y - y));

	/*
	 * ctanh(+-huge + i +-y) ~= +-1 +- i 2sin(2y)/exp(2x), using the
	 * approximation sinh^2(huge) ~= exp(2*huge) / 4.
	 * We use a modified formula to avoid spurious overflow.
	 */
	if (ix >= 0x40360000) {	/* x >= 22 */
		double exp_mx = exp(-fabs(x));
		return (cpack(copysign(1, x),
		    4 * sin(y) * cos(y) * exp_mx * exp_mx));
	}

	/* Kahan's algorithm */
	t = tan(y);
	beta = 1.0 + t * t;	/* = 1 / cos^2(y) */
	s = sinh(x);
	rho = sqrt(1 + s * s);	/* = cosh(x) */
	denom = 1 + beta * s * s;
	return (cpack((beta * rho * s) / denom, t / denom));
}
Ejemplo n.º 9
0
Archivo: csin.c Proyecto: KGG814/AOS
double complex csin(double complex z)
{
	z = csinh(cpack(-cimag(z), creal(z)));
	return cpack(cimag(z), -creal(z));
}
Ejemplo n.º 10
0
/*
 * Render the volume described by the given volume struct.
 * Return:  1 = ok
 *          0 = bad volume struct.
 */
static int render_volume( Context ctx,
                          struct volume *v, unsigned int ctable[] )
{
   register int rows, cols, slices, i, j, s;
	register int rows1, cols1;
   register uint_1 *cp0, *cp1;
   register float *vp0, *vp1;
	int	fastdraw;
	int	stride = 1;
   if (!v || !v->slices)
      return 0;


#if defined (HAVE_SGI_GL) || defined (DENALI)
   lmcolor( LMC_COLOR );             /* no shading */
   blendfunction( BF_SA, BF_MSA );   /* enable alpha blending */
#endif
#ifdef HAVE_OPENGL
   glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
   glEnable( GL_BLEND );
   check_gl_error( "render_volume (glBlendFunc)" );
#endif

   /* put rows, cols, slices values into registers */
   rows = v->rows-1;  /* number of quad strips = number of data rows - 1 */
   cols = v->cols;
   slices = v->slices;
   /* setup color and vertex pointers */
   cp0 = v->index;
   cp1 = cp0 + cols;
   vp0 = v->vertex;
   vp1 = vp0 + cols * 3;   /* 3 floats per vertex */

/* MJK 12.15.98 */
#ifdef HAVE_PEX

   rows++;
   j = rows * cols;

   for (s = 0; s < slices; s++)
   {
      draw_volume_quadmesh (rows, cols, vp0, cp0, ctable);
      vp0 += j * 3;
      cp0 += j;
   }
   return 1;
#endif

   vis5d_check_fastdraw(ctx->dpy_ctx->dpy_context_index, &fastdraw);

   if (fastdraw) {
	  stride = ctx->dpy_ctx->VStride;
   } 
	/* sanity check */
	if(stride<=0)
	  stride = 1;


   /*
   ** adjust rows and cols based on stride. N.B. appears to be one more
   ** row than we actually use
   */
   rows1 = (rows + 1 - 1) / stride;
   cols1 = ((cols - 1) / stride) + 1;
  

	/* loop over slices */
   for (s=0;s<slices;s+=stride) {

     cp0 = v->index + (s * rows * cols) +
		 (s * cols);	/* skip a row after each slice */

     vp0 = v->vertex + (s * rows * cols * 3) +
		 (s * cols * 3);	/* skip a row after each slice */

     cp1 = cp0 + (cols * stride);
     vp1 = vp0 + (cols * stride * 3);   /* 3 floats per vertex */
  
	  /* draw 'rows' quadrilateral strips */
	  for (i=0;i<rows1;i++) {
#if defined(SGI_GL) || defined(DENALI)
		 bgnqstrip();
		 for (j=0;j<cols1;j++) {
			cpack( ctable[cp0[i*stride*cols+j*stride]] );
			v3f( &vp0[i*stride*cols+j*stride] );
			cpack( ctable[cp1[i*stride*cols+j*stride]] );
			v3f( &vp1[i*stride*cols+j*stride] );
		 }
		 endqstrip();
#endif
#ifdef HAVE_OPENGL
		 glBegin( GL_QUAD_STRIP );
		 for (j=0;j<cols1;j++) {
			glColor4ubv( (GLubyte *) &ctable[cp0[i*stride*cols+j*stride]] );
			glVertex3fv( &vp0[(i*stride*cols+j*stride)*3] );
			
			glColor4ubv( (GLubyte *) &ctable[cp1[i*stride*cols+j*stride]] );
			glVertex3fv( &vp1[(i*stride*cols+j*stride)*3] );
		 }
		 glEnd();
#endif
	  }
	  
	}
	
#if defined(HAVE_SGI_GL) || defined(DENALI)
   blendfunction( BF_ONE, BF_ZERO );  /* disable alpha blending */
#endif
#ifdef HAVE_OPENGL
   glDisable( GL_BLEND );
   check_gl_error( "render_volume (glDisable)" );

#endif
   return 1;
}
Ejemplo n.º 11
0
double complex
csqrt(double complex z)
{
	double complex result;
	double a, b;
	double t;
	int scale;

	a = creal(z);
	b = cimag(z);

	/* Handle special cases. */
	if (z == 0)
		return (cpack(0, b));
	if (isinf(b))
		return (cpack(INFINITY, b));
	if (isnan(a)) {
		t = (b - b) / (b - b);	/* raise invalid if b is not a NaN */
		return (cpack(a, t));	/* return NaN + NaN i */
	}
	if (isinf(a)) {
		/*
		 * csqrt(inf + NaN i)  = inf +  NaN i
		 * csqrt(inf + y i)    = inf +  0 i
		 * csqrt(-inf + NaN i) = NaN +- inf i
		 * csqrt(-inf + y i)   = 0   +  inf i
		 */
		if (signbit(a))
			return (cpack(fabs(b - b), copysign(a, b)));
		else
			return (cpack(a, copysign(b - b, b)));
	}
	/*
	 * The remaining special case (b is NaN) is handled just fine by
	 * the normal code path below.
	 */

	/* Scale to avoid overflow. */
	if (fabs(a) >= THRESH || fabs(b) >= THRESH) {
		a *= 0.25;
		b *= 0.25;
		scale = 1;
	} else {
		scale = 0;
	}

	/* Algorithm 312, CACM vol 10, Oct 1967. */
	if (a >= 0) {
		t = sqrt((a + hypot(a, b)) * 0.5);
		result = cpack(t, b / (2 * t));
	} else {
		t = sqrt((-a + hypot(a, b)) * 0.5);
		result = cpack(fabs(b) / (2 * t), copysign(t, b));
	}

	/* Rescale. */
	if (scale)
		return (result * 2);
	else
		return (result);
}
Ejemplo n.º 12
0
/* init_matplot: initialises distmat plotting. The matrix size should
 * be Row x Col (which is the min. size in pixels). Title is put on the top
 * of the window by the window manager. Xorig and Yorig specify
 * the lower left corner position of the window: if either of them
 * is negative, then the window will be positioned interactively.
 * Return value: the 'gid' window ID number.
 */
long init_matplot(unsigned int Row, unsigned int Col, char *Title, 
	long Xorig, long Yorig)
{
    const unsigned int MINSIZE=500;
    
    long Gid, Xsize, Ysize, Xmax, Ymax;
    float Xmagnif, Ymagnif;
    unsigned int Rs, Cs;
    
    if (!Row) Row=MINSIZE;
    if (!Col) Col=MINSIZE;
    
    Xmagnif=(float)Col/MINSIZE;
    Ymagnif=(float)Row/MINSIZE;
    Rs=Row; Cs=Col;
    if (Col<=Row)
    {
	if (Xmagnif<1.0)
	{
	    Cs=MINSIZE;
	    Rs=round_id(Row/Xmagnif);
	}
    }
    else
    {
	if (Ymagnif<1.0)
	{
	    Rs=MINSIZE;
	    Cs=round_id(Col/Ymagnif);
	}
    }
    
    foreground();	/* enable signal catch etc. */
    Xmax=getgdesc(GD_XPMAX); Ymax=getgdesc(GD_YPMAX);
    keepaspect(Col, Row);

    /* Xmax,Ymax: the maximal screen coordinates */
    Xmax=getgdesc(GD_XPMAX); Ymax=getgdesc(GD_YPMAX);
    if (Xorig+Cs>Xmax) Xorig=Xmax-Cs;
    if (Yorig+Rs>Ymax) Yorig=Ymax-Rs;
    if (Xorig>=0 && Yorig>=0)
	prefposition(Xorig, Xorig+Cs, Yorig, Yorig+Rs);
    iconsize(84, 67);
    Gid=winopen(Title);	/* create window */
    
    RGBmode();
    /* check if double buffering is available */
    if (Dblbuffer=getgdesc(GD_BITS_NORM_DBL_BLUE))
    { doublebuffer(); gconfig(); }
    else fputs("init_matplot: single-buffer mode\n", stderr);

    /* enable resize */
    winconstraints();
    keepaspect(Col, Row);
    winconstraints();
    
    getsize(&Xsize, &Ysize);    /* scale drawing into window */
    Xmagnif=(float)Xsize/Col;
    Ymagnif=(float)Ysize/Row;
    pushmatrix();
    scale(Xmagnif, Ymagnif, 1.0);
    cpack(RGB_BLACK); clear();          /* clears window to black */
    if (Dblbuffer) { swapbuffers(); cpack(RGB_BLACK); clear(); }
    
    /* queue input events */
    qdevice(ESCKEY); qdevice(WINFREEZE); qdevice(WINTHAW);
    qdevice(REDRAWICONIC); qdevice(WINQUIT);
    
    return(Gid);
}
Ejemplo n.º 13
0
double complex
ccosh(double complex z)
{
	double x, y;
	int32_t hx, hy, ix, iy, lx, ly;

	x = creal(z);
	y = cimag(z);

	EXTRACT_WORDS(hx, lx, x);
	EXTRACT_WORDS(hy, ly, y);

	ix = 0x7fffffff & hx;
	iy = 0x7fffffff & hy;

	/* Handle the nearly-non-exceptional cases where x and y are finite. */
	if (ix < 0x7ff00000 && iy < 0x7ff00000) {
		if ((iy | ly) == 0)
			return (cpack(cosh(x), x * y));
		/* XXX We don't handle |x| > DBL_MAX ln(2) yet. */
		return (cpack(cosh(x) * cos(y), sinh(x) * sin(y)));
	}

	/*
	 * cosh(+-0 +- I Inf) = dNaN + I sign(d(+-0, dNaN))0.
	 * The sign of 0 in the result is unspecified.  Choice = normally
	 * the same as dNaN.  Raise the invalid floating-point exception.
	 *
	 * cosh(+-0 +- I NaN) = d(NaN) + I sign(d(+-0, NaN))0.
	 * The sign of 0 in the result is unspecified.  Choice = normally
	 * the same as d(NaN).
	 */
	if ((ix | lx) == 0 && iy >= 0x7ff00000)
		return (cpack(y - y, copysign(0, x * (y - y))));

	/*
	 * cosh(+-Inf +- I 0) = +Inf + I (+-)(+-)0.
	 *
	 * cosh(NaN +- I 0)   = d(NaN) + I sign(d(NaN, +-0))0.
	 * The sign of 0 in the result is unspecified.
	 */
	if ((iy | ly) == 0 && ix >= 0x7ff00000) {
		if (((hx & 0xfffff) | lx) == 0)
			return (cpack(x * x, copysign(0, x) * y));
		return (cpack(x * x, copysign(0, (x + x) * y)));
	}

	/*
	 * cosh(x +- I Inf) = dNaN + I dNaN.
	 * Raise the invalid floating-point exception for finite nonzero x.
	 *
	 * cosh(x + I NaN) = d(NaN) + I d(NaN).
	 * Optionally raises the invalid floating-point exception for finite
	 * nonzero x.  Choice = don't raise (except for signaling NaNs).
	 */
	if (ix < 0x7ff00000 && iy >= 0x7ff00000)
		return (cpack(y - y, x * (y - y)));

	/*
	 * cosh(+-Inf + I NaN)  = +Inf + I d(NaN).
	 *
	 * cosh(+-Inf +- I Inf) = +Inf + I dNaN.
	 * The sign of Inf in the result is unspecified.  Choice = always +.
	 * Raise the invalid floating-point exception.
	 *
	 * cosh(+-Inf + I y)   = +Inf cos(y) +- I Inf sin(y)
	 */
	if (ix >= 0x7ff00000 && ((hx & 0xfffff) | lx) == 0) {
		if (iy >= 0x7ff00000)
			return (cpack(x * x, x * (y - y)));
		return (cpack((x * x) * cos(y), x * sin(y)));
	}

	/*
	 * cosh(NaN + I NaN)  = d(NaN) + I d(NaN).
	 *
	 * cosh(NaN +- I Inf) = d(NaN) + I d(NaN).
	 * Optionally raises the invalid floating-point exception.
	 * Choice = raise.
	 *
	 * cosh(NaN + I y)    = d(NaN) + I d(NaN).
	 * Optionally raises the invalid floating-point exception for finite
	 * nonzero y.  Choice = don't raise (except for signaling NaNs).
	 */
	return (cpack((x * x) * (y - y), (x + x) * (y - y)));
}
Ejemplo n.º 14
0
static void 
_dxf_DRAW_GNOMON (tdmInteractor I, void *udata, float rot[4][4], int draw)
{
  /*
   *  draw == 1 to draw gnomon, draw == 0 to undraw.  This is done with
   *  two separate calls in order to support explicit erasure of edges for
   *  some implementations.  A draw is always preceded by an undraw and
   *  the pair of invocations is atomic.
   *
   *  Computations are done in normalized screen coordinates in order to
   *  render arrow heads correctly.
   */

  DEFDATA(I,tdmRotateData) ;
  DEFPORT(I_PORT_HANDLE) ;
  int dummy = 0 ;
  float origin[2] ;
  float xaxis[2],  yaxis[2],  zaxis[2] ;
  float xlabel[2], ylabel[2], zlabel[2] ;

  ENTRY(("_dxf_DRAW_GNOMON (0x%x, 0x%x, 0x%x, %d)",I, udata, rot, draw));

  if (PDATA(font) == -1)
    {
      /* font width for axes labels in normalized coordinates */
      font(0) ;
      PDATA(font) = 0 ;
      PDATA(swidth) = (float)strwidth("Z")/(float)GNOMONRADIUS ;

      /* 1 pixel in normalized coordinates */
      PDATA(nudge) = 1.0/(float)GNOMONRADIUS ;
    }
  else
      font(PDATA(font)) ;
  
  if (draw)
    {
      lmcolor(LMC_COLOR) ;
      cpack(0xffffffff) ;
      linewidth(1) ;
    }
  else
    {
      if (PDATA(redrawmode) != tdmViewEchoMode)
	{
	  /*
	   *  In tdmViewEchoMode (DX's Execute On Change), we are drawing
	   *  the gnomon echo on top of a background image that is redrawn
	   *  with every frame of a direct interaction.
	   *
	   *  If we're not in that mode, the background image is static
	   *  while the gnomon echo rotates in front of it, so erasing the
	   *  gnomon means we have to repair damage to the background.  We
	   *  do this by blitting a portion of the static image to the
	   *  back buffer, drawing the gnomon over that, then blitting the
	   *  combined results back to the front buffer.
	   */
	  
	  /* force graphics output into back buffer */
	  frontbuffer(FALSE) ;
	  backbuffer(TRUE) ;
	  
	  /* erase gnomon background */
	  lrectwrite (PDATA(illx), PDATA(illy),
		      PDATA(iurx), PDATA(iury), PDATA(background)) ;
	}

#ifndef NOSHADOW      
      /* draw wide black lines to ensure visibility against background */
      lmcolor(LMC_COLOR) ;
      cpack(0x0) ;
      linewidth(2) ;
#else
      EXIT(("No shadow"));
      return ;
#endif
    }

  origin[0] = 0 ;
  origin[1] = 0 ;

  xaxis[0] = 0.7 * rot[0][0] ; xaxis[1] = 0.7 * rot[0][1] ;
  yaxis[0] = 0.7 * rot[1][0] ; yaxis[1] = 0.7 * rot[1][1] ;
  zaxis[0] = 0.7 * rot[2][0] ; zaxis[1] = 0.7 * rot[2][1] ;

  xlabel[0] = 0.8 * rot[0][0] ; xlabel[1] = 0.8 * rot[0][1] ;
  ylabel[0] = 0.8 * rot[1][0] ; ylabel[1] = 0.8 * rot[1][1] ;
  zlabel[0] = 0.8 * rot[2][0] ; zlabel[1] = 0.8 * rot[2][1] ;

  pushmatrix() ;
  loadmatrix(identity) ;
  bgnline() ; v2f(origin) ; v2f(xaxis) ; endline() ;
  _dxf_DRAW_ARROWHEAD(PORT_CTX, xaxis[0], xaxis[1]) ;

  bgnline() ; v2f(origin) ; v2f(yaxis) ; endline() ;
  _dxf_DRAW_ARROWHEAD(PORT_CTX, yaxis[0], yaxis[1]) ;

  bgnline() ; v2f(origin) ; v2f(zaxis) ; endline() ;
  _dxf_DRAW_ARROWHEAD(PORT_CTX, zaxis[0], zaxis[1]) ;
  
  if (xlabel[0] <= 0) xlabel[0] -= PDATA(swidth) ;
  if (xlabel[1] <= 0) xlabel[1] -= PDATA(swidth) ;
  
  if (ylabel[0] <= 0) ylabel[0] -= PDATA(swidth) ;
  if (ylabel[1] <= 0) ylabel[1] -= PDATA(swidth) ;
  
  if (zlabel[0] <= 0) zlabel[0] -= PDATA(swidth) ;
  if (zlabel[1] <= 0) zlabel[1] -= PDATA(swidth) ;

#ifndef NOSHADOW  
  if (!draw)
    {
      /* offset text slightly for shadow */
      xlabel[0] += PDATA(nudge) ; xlabel[1] -= PDATA(nudge) ;
      ylabel[0] += PDATA(nudge) ; ylabel[1] -= PDATA(nudge) ;
      zlabel[0] += PDATA(nudge) ; zlabel[1] -= PDATA(nudge) ;
    }
#endif

  font(0) ;
  cmov2 (xlabel[0], xlabel[1]) ;
  charstr ("X") ;
  cmov2 (ylabel[0], ylabel[1]) ;
  charstr ("Y") ;
  cmov2 (zlabel[0], zlabel[1]) ;
  charstr ("Z") ;

  popmatrix() ;

  if (draw && PDATA(redrawmode) != tdmViewEchoMode)
    {
      /* copy rendered gnomon from back buffer to front buffer */
      readsource(SRC_BACK) ;
      frontbuffer(TRUE) ;
      backbuffer(FALSE) ;
      rectcopy (PDATA(illx), PDATA(illy), PDATA(iurx), PDATA(iury),
		PDATA(illx), PDATA(illy)) ;

      /* restore original buffer config from current tdmFrontBufferDraw */
      _dxf_BUFFER_RESTORE_CONFIG
	  (PORT_CTX, dummy, PDATA(buffermode), tdmFrontBufferDraw) ;
    }

  EXIT((""));
} 
Ejemplo n.º 15
0
static void 
_dxf_DRAW_GLOBE (tdmInteractor I, void *udata, float rot[4][4], int draw)
{
  /*
   *  draw == 1 to draw globe, draw == 0 to undraw.  This is done with two
   *  separate calls in order to support explicit erasure of edges for
   *  some implementations.  A draw is always preceded by an undraw and
   *  the pair of invocations is atomic.
   */

  DEFDATA(I,tdmRotateData) ;
  DEFPORT(I_PORT_HANDLE) ;
  int u, v, on, dummy = 0 ;

  /* globe edge visibility flags.  all globe instance share this data. */
  static struct {
    int latvis, longvis ;
  } edges[LATS][LONGS] ;

  /* globe and globeface defined in tdmGlobeEchoDef.h */
  register const float (*Globe)[LONGS][3] = globe ;
  register const struct Face (*Globeface)[LONGS] = globeface ;

  /* view normal */
  register float z0, z1, z2 ;
  z0 = rot[0][2] ; z1 = rot[1][2] ; z2 = rot[2][2] ;

#define FACEVISIBLE(u,v,z0,z1,z2) \
  (Globeface[u][v].norm[0] * z0 + \
   Globeface[u][v].norm[1] * z1 + \
   Globeface[u][v].norm[2] * z2 > 0.0)

  ENTRY(("_dxf_DRAW_GLOBE (0x%x, 0x%x, 0x%x, %d)",I, udata, rot, draw));

  if (draw)
    {
      lmcolor(LMC_COLOR) ;
      cpack(0xffffffff) ;
      linewidth(1) ;
    }
  else
    {
      if (PDATA(redrawmode) != tdmViewEchoMode)
	{
	  /*
	   *  In tdmViewEchoMode (DX's Execute On Change), we are drawing
	   *  the globe echo on top of a background image that is redrawn
	   *  with every frame of a direct interaction.
	   *
	   *  If we're not in that mode, the background image is static
	   *  while the globe echo rotates in front of it, so erasing the
	   *  globe means we have to repair damage to the background.  We
	   *  do this by blitting a portion of the static image to the
	   *  back buffer, drawing the globe over that, then blitting the
	   *  combined results back to the front buffer.
	   */
	  
	  /* force graphics output into back (draw) buffer */
	  frontbuffer(FALSE) ;
	  backbuffer(TRUE) ;
	  
	  /* erase globe background */
	  lrectwrite (PDATA(illx), PDATA(illy),
		      PDATA(iurx), PDATA(iury), PDATA(background)) ;
	}

#ifndef NOSHADOW      
      /* draw wide black lines to ensure visibility against background */
      lmcolor(LMC_COLOR) ;
      cpack(0x0) ;
      linewidth(2) ;
#else
      EXIT(("No shadow"));
      return ;
#endif
    }

#ifndef FACEVIS
  /*
   *  Compute visible edges explicitly.  This method might be faster and
   *  works in XOR mode but as implemented here is applicable only for a
   *  globe-type object rendered with latitude and longitude lines.
   */
#ifndef NOSHADOW
  if (!draw)
#endif
      for (u=0 ; u<LATS-1 ; u++)
	{
	  if (FACEVISIBLE(u, 0, z0, z1, z2))
	    {
	      edges[u][LONGS-1].latvis++ ;
	      edges[u+1][LONGS-1].latvis++ ;
	      edges[u][0].longvis++ ;
	      edges[u][LONGS-1].longvis++ ;
	    }
	  for (v=1 ; v<LONGS ; v++)
	      if (FACEVISIBLE(u, v, z0, z1, z2))
		{
		  edges[u][v-1].latvis++ ;
		  edges[u+1][v-1].latvis++ ;
		  edges[u][v].longvis++ ;
		  edges[u][v-1].longvis++ ;
		}
	}

  /* north pole */
  if (z1 > 0.0)
      for (v=0 ; v<LONGS ; v++)
	  edges[LATS-1][v].latvis++ ;

  /* south pole */
  if (z1 < 0.0)
      for (v=0 ; v<LONGS ; v++)
	  edges[0][v].latvis++ ;

  /*
   *  Draw each visible edge exactly once.
   */
  for (u=0 ; u<LATS ; u++)
    {
      for (v=0, on=0 ; v<LONGS-1 ; v++)
	  if (edges[u][v].latvis)
	    {
	      if (!on)
		{
		  on = 1 ;
		  bgnline() ;
		  v3f(Globe[u][v]) ;
		}
	      v3f (Globe[u][v+1]) ;
#ifndef NOSHADOW
	      if (draw)
#endif
		  edges[u][v].latvis = 0 ;
	    }
	  else if (on)
	    {
	      on = 0 ;
	      endline() ;
	    }

      /* close latitude line if necessary */
      if (edges[u][LONGS-1].latvis)
	{
	  if (!on)
	    {
	      bgnline() ;
	      v3f(Globe[u][LONGS-1]) ;
	    }
	  v3f (Globe[u][0]) ;
	  endline() ;
#ifndef NOSHADOW
	  if (draw)
#endif
	      edges[u][LONGS-1].latvis = 0 ;
	}
      else if (on)
	  endline() ;
    }
      
  /* longitude lines */
  for (v=0 ; v<LONGS ; v++)
    {
      for (u=0, on=0 ; u<LATS-1 ; u++)
	  if (edges[u][v].longvis)
	    {
	      if (!on)
		{
		  on = 1 ;
		  bgnline() ;
		  v3f(Globe[u][v]) ;
		}
	      v3f(Globe[u+1][v]) ;
#ifndef NOSHADOW
	      if (draw)
#endif
		  edges[u][v].longvis = 0 ;
	    }
	  else if (on)
	    {
	      on = 0 ;
	      endline() ;
	    }
      if (on)
	  endline() ;
    }
#else  
  /*
   *  Do it the easy way:  draw all visible faces regardless of shared
   *  edges.  Most edges are drawn twice, so this is slower and not
   *  compatible with XOR rendering.
   */
  for (u=0 ; u<LATS-1 ; u++)
      for (v=0 ; v<LONGS ; v++)
	  if (FACEVISIBLE(u, v, z0, z1, z2))
	      poly (4, Globeface[u][v].face) ;

  /* north pole */
  if (z1 > 0.0)
      poly (LONGS, Globe[LATS-1]) ;

  /* south pole */
  if (z1 < 0.0)
      poly (LONGS, Globe[0]) ;

#endif /* ifndef FACEVIS */

  if (draw && PDATA(redrawmode) != tdmViewEchoMode)
    {
      /* copy rendered globe from back buffer to front buffer */
      readsource(SRC_BACK) ;
      frontbuffer(TRUE) ;
      backbuffer(FALSE) ;
      rectcopy (PDATA(illx), PDATA(illy), PDATA(iurx), PDATA(iury),
		PDATA(illx), PDATA(illy)) ;

      /* restore original buffer config from current tdmFrontBufferDraw */
      _dxf_BUFFER_RESTORE_CONFIG
	  (PORT_CTX, dummy, PDATA(buffermode), tdmFrontBufferDraw) ;
    }
  EXIT((""));
}