diff options
Diffstat (limited to 'src/bltGrMisc.C')
-rw-r--r-- | src/bltGrMisc.C | 344 |
1 files changed, 0 insertions, 344 deletions
diff --git a/src/bltGrMisc.C b/src/bltGrMisc.C index d795fae..e9a3770 100644 --- a/src/bltGrMisc.C +++ b/src/bltGrMisc.C @@ -1139,347 +1139,3 @@ Blt_GetLineExtents(size_t nPoints, Point2d *points, Region2d *r) } } } - -typedef struct { - float x, y, z; -} Vector3f; - -typedef struct { - float x, y, z, w; -} Vector4f; - -typedef Vector4f Quaternion; - -typedef float Matrix3x3f[3][3]; - -typedef struct _ArcBall { - Vector3f click; - Vector3f drag; - float xScale; - float yScale; -} ArcBall; - -/* - * Arcball sphere constants: - * Diameter is 2.0f - * Radius is 1.0f - * Radius squared is 1.0f - */ - -/* assuming IEEE-754 (float), which i believe has max precision of 7 bits */ -#define EPSILON FLT_EPSILON -static INLINE float -LengthVector3f(Vector3f *a) -{ - return sqrtf((a->x * a->x) + (a->y * a->y) + (a->z * a->z)); -} - -static INLINE float DotProductVector3f(Vector3f *a, Vector3f *b) -{ - return (a->x * b->x) + (a->y * b->y) + (a->z * b->z); -} - -/** - * Calculate the cross product of two 3D vectors: c = a x b. - * "c" must not refer to the same memory location as "a" or "b". - */ -static INLINE void -CrossProductVector3f(Vector3f *a, Vector3f *b, Vector3f *c) -{ - c->x = (a->y * b->z) - (b->y * a->z); - c->y = (a->z * b->x) - (b->z * a->x); - c->z = (a->x * b->y) - (b->x * a->y); -} - -static void -PointOnSphere (ArcBall *arcPtr, float x, float y, Vector3f *outPtr) -{ - float sx, sy; - float d; - - /* Adjust point coords and scale down to range of [-1 ... 1] */ - sx = (x * arcPtr->xScale) - 1.0f; - sy = 1.0f - (y * arcPtr->yScale); - - /* Compute the square of the length of the vector to the point from the - * center. */ - d = (sx * sx) + (sy * sy); - - /* If the point is mapped outside of the sphere ... - * (length > radius squared) - */ - if (d > 1.0f) { - float scale; - - /* Compute a normalizing factor (radius / sqrt(length)) */ - scale = 1.0f / sqrt (d); - - /* Return the "normalized" vector, a point on the sphere */ - outPtr->x = sx * scale; - outPtr->y = sy * scale; - outPtr->z = 0.0f; - } else { /* else it's on the inside */ - /* Return a vector to a point mapped inside the sphere - * sqrt(radius squared - length) */ - outPtr->x = sx; - outPtr->y = sy; - outPtr->z = sqrtf(1.0f - d); - } -} - -static void -SetArcBallBounds(ArcBall *arcPtr, float w, float h) -{ - if (w <= 1.0f ) { - w = 2.0f; - } - if (h <= 1.0f ) { - h = 2.0f; - } - /* Set adjustment factor for width/height */ - arcPtr->xScale = 1.0f / ((w - 1.0f) * 0.5f); - arcPtr->yScale = 1.0f / ((h - 1.0f) * 0.5f); -} - -static ArcBall * -CreateArcBall (float w, float h) -{ - ArcBall *arcPtr; - - arcPtr = calloc(1, sizeof(ArcBall)); - SetArcBallBounds (arcPtr, w, h); - return arcPtr; -} - -static void -DestroyArcBall(ArcBall *arcPtr) -{ - if (arcPtr != NULL) { - free(arcPtr); - } -} - -/* Mouse down: Supply mouse position in x and y */ -static void -ArcBallOnClick(ArcBall *arcPtr, float x, float y) -{ - PointOnSphere (arcPtr, x, y, &arcPtr->click); -} - -/* Mouse drag, calculate rotation: Supply mouse position in x and y */ -static void -ArcBallOnDrag(ArcBall *arcPtr, float x, float y, Quaternion *outPtr) -{ - /* Map the point to the sphere */ - PointOnSphere(arcPtr, x, y, &arcPtr->drag); - - /* Return the quaternion equivalent to the rotation */ - if (outPtr != NULL) { - Vector3f perp; - - /* Compute the vector perpendicular to the begin and end vectors */ - CrossProductVector3f(&arcPtr->drag, &arcPtr->click, &perp); - - /* Compute the length of the perpendicular vector */ - if (LengthVector3f(&perp) > FLT_EPSILON) { - /* If its non-zero, we're ok, so return the perpendicular - * vector as the transform after all - */ - outPtr->x = perp.x; - outPtr->y = perp.y; - outPtr->z = perp.z; - /* In the quaternion values, w is cosine (theta / 2), - * where theta is rotation angle - */ - outPtr->w = DotProductVector3f(&arcPtr->click, &arcPtr->drag); - } else { - /* If it is zero, the begin and end vectors coincide, - * so return an identity transform - */ - outPtr->x = outPtr->y = outPtr->z = outPtr->z = 0.0f; - } - } -} - - -static INLINE void -SetRotationMatrix(const Quaternion* q, Matrix3x3f mat) -{ - float n, s; - float xs, ys, zs; - float wx, wy, wz; - float xx, xy, xz; - float yy, yz, zz; - - assert(mat && q); - - n = (q->x * q->x) + (q->y * q->y) + (q->z * q->z) + (q->w * q->w); - - s = (n > 0.0f) ? (2.0f / n) : 0.0f; - - xs = q->x * s; - ys = q->y * s; - zs = q->z * s; - wx = q->w * xs; - wy = q->w * ys; - wz = q->w * zs; - xx = q->x * xs; - xy = q->x * ys; - xz = q->x * zs; - yy = q->y * ys; - yz = q->y * zs; - zz = q->z * zs; - - mat[0][0] = 1.0f - (yy + zz); - mat[0][1] = xy - wz; - mat[0][2] = xz + wy; - mat[1][0] = xy + wz; - mat[1][1] = 1.0f - (xx + zz); - mat[1][2] = yz - wx; - mat[2][0] = xz - wy; - mat[2][1] = yz + wx; - mat[2][2] = 1.0f - (xx + yy); -} - -/* Return quaternion product qL * qR. Note: order is important! - * To combine rotations, use the product Mul(Second, First), - * which gives the effect of rotating by First then Second. */ -static INLINE void -CombineRotations(Quaternion *a, Quaternion *b, Quaternion *result) -{ - result->w = (a->w * b->w) - (a->x * b->x) - (a->y * b->y) - (a->z * b->z); - result->x = (a->w * b->x) + (a->x * b->w) + (a->y * b->z) - (a->z * b->y); - result->y = (a->w * b->y) + (a->y * b->w) + (a->z * b->x) - (a->x * b->z); - result->z = (a->w * b->z) + (a->z * b->w) + (a->x * b->y) - (a->y * b->x); -} - - -static int -GetQuaternionFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr, Quaternion *q) -{ - Tcl_Obj **objv; - int objc; - double x, y, z, w; - - if (Tcl_ListObjGetElements(interp, objPtr, &objc, &objv) != TCL_OK) { - return TCL_ERROR; - } - if (objc != 4) { - Tcl_AppendResult(interp, "wrong number of elements in quaternion \"", - Tcl_GetString(objPtr), "\"", (char *)NULL); - return TCL_ERROR; - } - if ((Tcl_GetDoubleFromObj(interp, objv[0], &x) != TCL_OK) || - (Tcl_GetDoubleFromObj(interp, objv[1], &y) != TCL_OK) || - (Tcl_GetDoubleFromObj(interp, objv[2], &z) != TCL_OK) || - (Tcl_GetDoubleFromObj(interp, objv[3], &w) != TCL_OK)) { - return TCL_ERROR; - } - q->x = x, q->y = y, q->z = z, q->w = w; - return TCL_OK; -} - -static int -ArcBallCombineOp(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *const *objv) -{ - Tcl_Obj *listObjPtr; - Quaternion q1, q2, r; - - if (GetQuaternionFromObj(interp, objv[2], &q1) != TCL_OK) { - return TCL_ERROR; - } - if (GetQuaternionFromObj(interp, objv[3], &q2) != TCL_OK) { - return TCL_ERROR; - } - CombineRotations(&q2, &q1, &r); - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(r.x)); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(r.y)); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(r.w)); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(r.z)); - Tcl_SetObjResult(interp, listObjPtr); - return TCL_OK; -} - -static int -ArcBallRotateOp(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *const *objv) -{ - ArcBall *arcPtr; - Tcl_Obj *listObjPtr; - Quaternion q; - double x1, y1, x2, y2; - int w, h; - - if ((Tcl_GetIntFromObj(interp, objv[2], &w) != TCL_OK) || - (Tcl_GetIntFromObj(interp, objv[3], &h) != TCL_OK)) { - return TCL_ERROR; - } - if ((Tcl_GetDoubleFromObj(interp, objv[4], &x1) != TCL_OK) || - (Tcl_GetDoubleFromObj(interp, objv[5], &y1) != TCL_OK) || - (Tcl_GetDoubleFromObj(interp, objv[6], &x2) != TCL_OK) || - (Tcl_GetDoubleFromObj(interp, objv[7], &y2) != TCL_OK)) { - return TCL_ERROR; - } - arcPtr = CreateArcBall((float)w, (float)h); - ArcBallOnClick(arcPtr, x1, y1); - ArcBallOnDrag(arcPtr, x2, y2, &q); - DestroyArcBall(arcPtr); - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(q.x)); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(q.y)); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(q.w)); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(q.z)); - Tcl_SetObjResult(interp, listObjPtr); - return TCL_OK; -} - -static int -ArcBallMatrixOp(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *const *objv) -{ - Matrix3x3f rot; - Tcl_Obj *listObjPtr; - Quaternion q; - - if (GetQuaternionFromObj(interp, objv[2], &q) != TCL_OK) { - return TCL_ERROR; - } - SetRotationMatrix(&q, rot); - listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(rot[0][0])); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(rot[0][1])); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(rot[0][2])); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(rot[1][0])); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(rot[1][1])); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(rot[1][2])); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(rot[2][0])); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(rot[2][1])); - Tcl_ListObjAppendElement(interp, listObjPtr, Tcl_NewDoubleObj(rot[2][2])); - Tcl_SetObjResult(interp, listObjPtr); - return TCL_OK; -} - -static Blt_OpSpec arcBallOps[] = -{ - {"combine", 1, ArcBallCombineOp, 4, 4, "quat1 quat2",}, - {"matrix", 1, ArcBallMatrixOp, 3, 3, "quat",}, - {"rotate", 1, ArcBallRotateOp, 8, 8, "w h x1 y1 x2 y2",}, -}; -static int nArcBallOps = sizeof(arcBallOps) / sizeof(Blt_OpSpec); - -static int -ArcBallCmd(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *const *objv) -{ - Tcl_ObjCmdProc *proc; - - proc = Blt_GetOpFromObj(interp, nArcBallOps, arcBallOps, BLT_OP_ARG1, - objc, objv, 0); - if (proc == NULL) { - return TCL_ERROR; - } - return (*proc) (clientData, interp, objc, objv); -} - |