-
Notifications
You must be signed in to change notification settings - Fork 5
Selecting geometry in X3D #138
Comments
Thank you for the report. We want to stabilize anchors for use in VRML, X3D as well as X3DOM. Can you indicate what OS, browser, and VRML/X3D plugin you are using? |
Hi Dave, It was on windows 7, with firefox using the BS Contact plugin. Best, From: Dave Cooper [mailto:[email protected]] Thank you for the report. We want to stabilize anchors for use in VRML, X3D as well as X3DOM. Can you indicate what OS, browser, and VRML/X3D plugin you are using? — |
Open for submission: $200-300 Audit and clean up selecting and onclick behavior for X3D and X3DOM output-formats (in theory, these should be identical). |
The fix below to X3D lens adds onclick behavior to X3DOM output. Nice! It required some cleanup of code and an extra parameters attribute. However, there seems to be a strange bug in X3D mode. Whenever the javascript string to eval contains whitespace or comma's, a javascript error is thrown.
At this stage I can't get my head around this. Perhaps a BSContact-related thingy? Strange, because the VRML counterpart is quite identical, and does work. |
The fix for now: (define-lens (x3d base-object)()
:output-functions
(
(cad-output
(&key (header? t))
(when header? (write-the header))
(let ((orientation (the orientation*)))
(let ((rotation (quaternion-to-rotation (matrix-to-quaternion orientation)))
;;(rotation (matrix-to-rotation orientation))
(x (get-x (the center)))
(y (get-y (the center)))
(z (get-z (the center)))
)
(cl-who:with-html-output (*stream* nil :indent nil)
((:|Transform| :|translation| (unless (every #'zerop (list x y z))
(format nil "~3,7f ~3,7f ~3,7f" x y z)))
((:|Transform| :|rotation| (when rotation
(format nil "~3,7f ~3,7f ~3,7f ~3,7f"
(get-x rotation) (get-y rotation) (get-z rotation) (get-w rotation))))
(cond
((or (getf (the display-controls) :billboard)
(getf (the display-controls) :billboard-vector))
(cl-who:htm
((:|Billboard| :|axisOfRotation|
(if (getf (the display-controls) :billboard-vector)
(let ((vector (getf (the display-controls) :billboard-vector)))
(format nil "~a ~a ~a" (get-x vector) (get-y vector) (get-z vector)))
(format nil "0 0 0")))
(if (and (find-package :gwl) (symbol-value (read-safe-string "gwl::*onclick-function*")))
(cl-who:htm
((:|Anchor| :|url| (format nil "javascript:event=null;~a" (funcall *onclick-function* self)) ;;event=null;
:|parameter| "target=_self")
(write-the shape)))
(write-the shape)))))
(t
(if (and (find-package :gwl) (symbol-value (read-safe-string "gwl::*onclick-function*")))
(cl-who:htm
((:|Anchor| :|url| (format nil "javascript:event=null;~a" (funcall *onclick-function* self)) ;;event=null;
:|parameter| "target=_self")
(write-the shape)))
(write-the shape)))))
(when (and (typep self 'outline-specialization-mixin)
(not (ignore-errors (typep self (read-from-string "surf:surface"))))
(not (ignore-errors (typep self (read-from-string "surf:curve")))))
(let* ((center (reverse-vector (the center)))
(x (get-x center)) (y (get-y center)) (z (get-z center))
(inverse (when (the orientation*)
(matrix-to-rotation (matrix:transpose-matrix
(the orientation*)))
#+nil
(quaternion-to-rotation (matrix-to-quaternion (matrix:transpose-matrix
(the orientation*)))))))
(cl-who:htm
((:|Transform| :|rotation| (when inverse
(format nil "~3,7f ~3,7f ~3,7f ~3,7f"
(get-x inverse) (get-y inverse) (get-z inverse) (get-w inverse))))
((:|Transform| :|translation| (when (not (every #'zerop (list x y z)))
(format nil "~3,7f ~3,7f ~3,7f" x y z)))
(mapc #'(lambda(outline-object)
(write-the-object outline-object (cad-output :header? nil)))
(the outline-leaves))
))
)))
#+nil
(when (and (typep self 'outline-specialization-mixin)
(not (ignore-errors (typep self (read-from-string "surf:surface"))))
(not (ignore-errors (typep self (read-from-string "surf:curve")))))
(let* ((center (reverse-vector (the center)))
(x (get-x center)) (y (get-y center)) (z (get-z center))
(inverse (when (the orientation*)
(matrix-to-rotation (matrix:transpose-matrix
(the orientation*)))
#+nil
(quaternion-to-rotation (matrix-to-quaternion (matrix:transpose-matrix
(the orientation*)))))))
(cl-who:htm
((:|Transform| :|translation| (when (not (every #'zerop (list x y z)))
(format nil "~3,7f, ~3,7f, ~3,7f" x y z)))
((:|Transform| :|rotation| (when inverse
(format nil "~3,7f ~3,7f ~3,7f ~3,7f"
(get-x inverse) (get-y inverse) (get-z inverse) (get-w inverse))))
(mapc #'(lambda(outline-object)
(write-the-object outline-object (cad-output :header? nil)))
(the outline-leaves))
))
))))))))
(cad-output-tree
(&key (header? t) (from-root? t))
(when header? (write-the header))
(let ((center (if from-root? (the center) (the local-center*)))
(orientation (if from-root? (the orientation*) (the local-orientation*))))
(let ((rotation (quaternion-to-rotation (matrix-to-quaternion orientation)))
;;(rotation (matrix-to-rotation orientation))
(x (get-x center)) (y (get-y center)) (z (get-z center)))
;;
;; FLAG -- factor out the redundant calls and call directly to
;; cad-output, which will itself call to the shape.
;;
(cl-who:with-html-output (*stream* nil :indent nil)
((:|Transform| :|translation| (unless (every #'zerop (list x y z))
(format nil "~3,7f ~3,7f ~3,7f" x y z)))
((:|Transform| :|rotation| (when rotation
(format nil "~3,7f ~3,7f ~3,7f ~3,7f"
(get-x rotation) (get-y rotation) (get-z rotation) (get-w rotation)))
)
(if (null (the children))
(cond
((or (getf (the display-controls) :billboard)
(getf (the display-controls) :billboard-vector))
(cl-who:htm
((:|Billboard| :|axisOfRotation|
(if (getf (the display-controls) :billboard-vector)
(let ((vector (getf (the display-controls) :billboard-vector)))
(format nil "~a ~a ~a" (get-x vector) (get-y vector) (get-z vector)))
(format nil "0 0 0")))
(if (and (find-package :gwl) (symbol-value (read-safe-string "gwl::*onclick-function*")))
(cl-who:htm
((:|Anchor| :|url| (format nil "javascript:event=null;~a" (funcall *onclick-function* self)) ;;event=null;
:|parameter| "target=_self")
(write-the shape)))
(write-the shape)))))
(t
(if (and (find-package :gwl) (symbol-value (read-safe-string "gwl::*onclick-function*")))
(cl-who:htm
((:|Anchor| :|url| (format nil "javascript:event=null;~a" (funcall *onclick-function* self)) ;;event=null;
:|parameter| "target=_self")
(write-the shape)))
(write-the shape))))
(mapc #'(lambda(child)
(write-the-object child (cad-output-tree :header? nil :from-root? nil))) (the children)))
(when (and (typep self 'outline-specialization-mixin)
(not (ignore-errors (typep self (read-from-string "surf:surface"))))
(not (ignore-errors (typep self (read-from-string "surf:curve")))))
(let* ((center (reverse-vector (the center)))
(x (get-x center)) (y (get-y center)) (z (get-z center))
(inverse (when (the orientation*)
(quaternion-to-rotation (matrix-to-quaternion (matrix:transpose-matrix (the orientation*))))
#+nil
(matrix-to-rotation (matrix:transpose-matrix (the orientation*))))))
(cl-who:htm
((:|Transform| :|rotation| (when inverse
(format nil "~3,7f ~3,7f ~3,7f ~3,7f"
(get-x inverse) (get-y inverse) (get-z inverse) (get-w inverse))))
((:|Transform| :|translation| (when (not (every #'zerop (list x y z)))
(format nil "~3,7f ~3,7f ~3,7f" x y z)))
(mapc #'(lambda(outline-object)
(write-the-object outline-object (cad-output :header? nil)))
(the outline-leaves))
))
)))
#+nil
(when (and (typep self 'outline-specialization-mixin)
(not (ignore-errors (typep self (read-from-string "surf:surface"))))
(not (ignore-errors (typep self (read-from-string "surf:curve")))))
(let* ((center (reverse-vector (the center)))
(x (get-x center)) (y (get-y center)) (z (get-z center))
(inverse (when (the orientation*)
(quaternion-to-rotation (matrix-to-quaternion (matrix:transpose-matrix (the orientation*))))
#+nil
(matrix-to-rotation (matrix:transpose-matrix (the orientation*))))))
(cl-who:htm
((:|Transform| :|translation| (when (not (every #'zerop (list x y z)))
(format nil "~3,7f, ~3,7f, ~3,7f" x y z)))
((:|Transform| :|rotation| (when inverse
(format nil "~3,7f ~3,7f ~3,7f ~3,7f"
(get-x inverse) (get-y inverse) (get-z inverse) (get-w inverse))))
(mapc #'(lambda(outline-object)
(write-the-object outline-object (cad-output :header? nil)))
(the outline-leaves))
))
)))))))))
)) |
Is that apparent Javascript error only affecting X3D in BS Contact, or X3DOM as well? We received the following support response from BS Contact a while back:
This was in response to an example we provided which looked like:
which had been throwing errors. I'm not sure if this is connected to the bug you are seeing or not, putting it out here just in case. By the way, are we sure that Is the way to add anchors in X3DOM is in fact the same as X3D? In X3DOM isn't it possible just to use a standard HTML element and add events to it, for example
|
For X3DOM the proposed fix above works like a charm. Use of proper MFStrings does indeed fix X3D format. See the fix below. However, now X3DOM fails, it complain about a syntax error. While browsing through the DOM tree, I now see |
The fix for X3D: (in-package :geom-base)
(defun %gdlajax-MFString% (str)
"string. Converts gdlajax string to MFString format for X3D output. Example:
gdl-user> (setq str \"gdlajax(null, 'args=XXXX')\")
gdl-user> (%gdlajax-MFString% str)
\"'\"javascript:event=null;gdlAjax(null,\\\\\"args=DQooOmlpZCAiMTMxZDg3YjE3MDAiIDpiYXNoZWUgKDolcnAlIG5pbCkgOmZ1bmN0aW9uIDpwZXJmb3JtLWFjdGlvbiEgOmFyZ3VtZW50cw0KICgoOiVycCUgKDpmb290IDpiYXNlIDpyb2JvdCA6cm9vdC1vYmplY3Qtb2JqZWN0KSkpKQ\\\\\",true);\"'\""
(concatenate 'string "'\"javascript:event=null;" (ppcre:regex-replace-all "'" (remove #\Space str) "\\\"") "\"'"))
(define-lens (x3d base-object)()
:output-functions
(
(cad-output
(&key (header? t))
(when header? (write-the header))
(let ((orientation (the orientation*)))
(let ((rotation (quaternion-to-rotation (matrix-to-quaternion orientation)))
;;(rotation (matrix-to-rotation orientation))
(x (get-x (the center)))
(y (get-y (the center)))
(z (get-z (the center)))
)
(cl-who:with-html-output (*stream* nil :indent nil)
((:|Transform| :|translation| (unless (every #'zerop (list x y z))
(format nil "~3,7f ~3,7f ~3,7f" x y z)))
((:|Transform| :|rotation| (when rotation
(format nil "~3,7f ~3,7f ~3,7f ~3,7f"
(get-x rotation) (get-y rotation) (get-z rotation) (get-w rotation))))
(cond
((or (getf (the display-controls) :billboard)
(getf (the display-controls) :billboard-vector))
(cl-who:htm
((:|Billboard| :|axisOfRotation|
(if (getf (the display-controls) :billboard-vector)
(let ((vector (getf (the display-controls) :billboard-vector)))
(format nil "~a ~a ~a" (get-x vector) (get-y vector) (get-z vector)))
(format nil "0 0 0")))
(if (and (find-package :gwl) (symbol-value (read-safe-string "gwl::*onclick-function*")))
(cl-who:htm
((:|Anchor|
;; use cl-who:fmt to force ' ' around string and not standard " "
;; strange: without :|url| nothing will be printed, so leave it.
:|url| (cl-who:fmt " url=~a" (%gdlajax-MFString% (funcall *onclick-function* self)))
:|parameter| "target=_self")
(write-the shape)))
(write-the shape)))))
(t
(if (and (find-package :gwl) (symbol-value (read-safe-string "gwl::*onclick-function*")))
(cl-who:htm
((:|Anchor|
;; use cl-who:fmt to force ' ' around string and not standard " "
;; strange: without :|url| nothing will be printed, so leave it.
:|url| (cl-who:fmt " url=~a" (%gdlajax-MFString% (funcall *onclick-function* self)))
:|parameter| "target=_self")
(write-the shape)))
(write-the shape)))))
(when (and (typep self 'outline-specialization-mixin)
(not (ignore-errors (typep self (read-from-string "surf:surface"))))
(not (ignore-errors (typep self (read-from-string "surf:curve")))))
(let* ((center (reverse-vector (the center)))
(x (get-x center)) (y (get-y center)) (z (get-z center))
(inverse (when (the orientation*)
(matrix-to-rotation (matrix:transpose-matrix
(the orientation*)))
#+nil
(quaternion-to-rotation (matrix-to-quaternion (matrix:transpose-matrix
(the orientation*)))))))
(cl-who:htm
((:|Transform| :|rotation| (when inverse
(format nil "~3,7f ~3,7f ~3,7f ~3,7f"
(get-x inverse) (get-y inverse) (get-z inverse) (get-w inverse))))
((:|Transform| :|translation| (when (not (every #'zerop (list x y z)))
(format nil "~3,7f ~3,7f ~3,7f" x y z)))
(mapc #'(lambda(outline-object)
(write-the-object outline-object (cad-output :header? nil)))
(the outline-leaves))
))
)))
)))))
(cad-output-tree
(&key (header? t) (from-root? t))
(when header? (write-the header))
(let ((center (if from-root? (the center) (the local-center*)))
(orientation (if from-root? (the orientation*) (the local-orientation*))))
(let ((rotation (quaternion-to-rotation (matrix-to-quaternion orientation)))
;;(rotation (matrix-to-rotation orientation))
(x (get-x center)) (y (get-y center)) (z (get-z center)))
;;
;; FLAG -- factor out the redundant calls and call directly to
;; cad-output, which will itself call to the shape.
;;
(cl-who:with-html-output (*stream* nil :indent nil)
((:|Transform| :|translation| (unless (every #'zerop (list x y z))
(format nil "~3,7f ~3,7f ~3,7f" x y z)))
((:|Transform| :|rotation| (when rotation
(format nil "~3,7f ~3,7f ~3,7f ~3,7f"
(get-x rotation) (get-y rotation) (get-z rotation) (get-w rotation)))
)
(if (null (the children))
(cond
((or (getf (the display-controls) :billboard)
(getf (the display-controls) :billboard-vector))
(cl-who:htm
((:|Billboard| :|axisOfRotation|
(if (getf (the display-controls) :billboard-vector)
(let ((vector (getf (the display-controls) :billboard-vector)))
(format nil "~a ~a ~a" (get-x vector) (get-y vector) (get-z vector)))
(format nil "0 0 0")))
(if (and (find-package :gwl) (symbol-value (read-safe-string "gwl::*onclick-function*")))
(cl-who:htm
((:|Anchor|
;; use cl-who:fmt to force ' ' around string and not standard " "
;; strange: without :|url| nothing will be printed, so leave it.
:|url| (cl-who:fmt " url=~a" (%gdlajax-MFString% (funcall *onclick-function* self)))
:|parameter| "target=_self")
(write-the shape)))
(write-the shape)))))
(t
(if (and (find-package :gwl) (symbol-value (read-safe-string "gwl::*onclick-function*")))
(cl-who:htm
((:|Anchor|
;; use cl-who:fmt to force ' ' around string and not standard " "
;; strange: without :|url| nothing will be printed, so leave it.
:|url| (cl-who:fmt " url=~a" (%gdlajax-MFString% (funcall *onclick-function* self)))
:|parameter| "target=_self")
(write-the shape)))
(write-the shape))))
(mapc #'(lambda(child)
(write-the-object child (cad-output-tree :header? nil :from-root? nil))) (the children)))
(when (and (typep self 'outline-specialization-mixin)
(not (ignore-errors (typep self (read-from-string "surf:surface"))))
(not (ignore-errors (typep self (read-from-string "surf:curve")))))
(let* ((center (reverse-vector (the center)))
(x (get-x center)) (y (get-y center)) (z (get-z center))
(inverse (when (the orientation*)
(quaternion-to-rotation (matrix-to-quaternion (matrix:transpose-matrix (the orientation*))))
#+nil
(matrix-to-rotation (matrix:transpose-matrix (the orientation*))))))
(cl-who:htm
((:|Transform| :|rotation| (when inverse
(format nil "~3,7f ~3,7f ~3,7f ~3,7f"
(get-x inverse) (get-y inverse) (get-z inverse) (get-w inverse))))
((:|Transform| :|translation| (when (not (every #'zerop (list x y z)))
(format nil "~3,7f ~3,7f ~3,7f" x y z)))
(mapc #'(lambda(outline-object)
(write-the-object outline-object (cad-output :header? nil)))
(the outline-leaves))
))
)))
#+nil
(when (and (typep self 'outline-specialization-mixin)
(not (ignore-errors (typep self (read-from-string "surf:surface"))))
(not (ignore-errors (typep self (read-from-string "surf:curve")))))
(let* ((center (reverse-vector (the center)))
(x (get-x center)) (y (get-y center)) (z (get-z center))
(inverse (when (the orientation*)
(quaternion-to-rotation (matrix-to-quaternion (matrix:transpose-matrix (the orientation*))))
#+nil
(matrix-to-rotation (matrix:transpose-matrix (the orientation*))))))
(cl-who:htm
((:|Transform| :|translation| (when (not (every #'zerop (list x y z)))
(format nil "~3,7f, ~3,7f, ~3,7f" x y z)))
((:|Transform| :|rotation| (when inverse
(format nil "~3,7f ~3,7f ~3,7f ~3,7f"
(get-x inverse) (get-y inverse) (get-z inverse) (get-w inverse))))
(mapc #'(lambda(outline-object)
(write-the-object outline-object (cad-output :header? nil)))
(the outline-leaves))
))
)))))))))
)) |
Yes, since x3dom and x3d (as benchmarked by BS Contact) seem to diverge on handling Anchors, let's have the lenses emit two different "flavors" of x3d -- one tuned for BS Contact and one tuned for x3dom. Of course this should be done with minimal duplication of code - just a format-slot should do it, i.e.: (with-format (x3d stream :flavor :x3dom) ... ) or (with-format (x3d stream :flavor :x3d-plugin) ...) I would lean toward the x3dom version using a standard :onclick DOM node, when the intention is to run a function. On the other hand, what about the ability to have a graphical element be an actual anchor, in the traditional sense --- that is, pointing to an actual URL? Then we would want something like: ((:a :href ... ) ... ) so, do we need both an onclick-function and an anchor? And I guess without the possibility of having both at the same time... |
The anchors are not working in X3D, so geometry cannot be selected in that mode and associated onclick functions cannot be used.
It seems to work fine in VRML.
The issue can be seen by viewing robot:assembly in X3D mode.
The text was updated successfully, but these errors were encountered: