Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Information on camera update #15

Closed
giuliods opened this issue Nov 11, 2021 · 4 comments · Fixed by #17
Closed

Information on camera update #15

giuliods opened this issue Nov 11, 2021 · 4 comments · Fixed by #17

Comments

@giuliods
Copy link

With setting the camera3d's mode to free I have to update it on every frame. But the function require the camera to be passed as a pointer. I actually have +camera+ storing the camera3d struct. There is a function or a macro I'm not aware to pass it to the update-camera function?

@longlene
Copy link
Owner

@giuliods Please have a look at #12 That's just the question we talked.

@longlene
Copy link
Owner

@giuliods Currently, seems no solution for it.

@kiran-kp
Copy link
Contributor

kiran-kp commented Apr 4, 2022

Here's my attempt at some macros to help solve this.

This is my first attempt at doing anything serious with macros so I'm very open to feedback.

(defmacro define-struct (name description fields)
  (let* ((cstruct-name (read-from-string (concatenate 'string "%" (string-trim " " name))))
         (cstruct-type (read-from-string (concatenate 'string "%" (string-trim " " name) "-tclass")))
         (lisp-struct-name (read-from-string name))
         (field-names (loop :for f :in fields :collect (nth 0 f))))
    `(progn
       (cffi:defcstruct ,cstruct-name
         ,description
         ,@fields)
       (defstruct ,lisp-struct-name
         ,description
         ,@(loop :for f :in fields
                 :collect (nth 0 f)))
       (defmethod cffi:translate-into-foreign-memory (lisp-var (type ,cstruct-type) ptr)
         (cffi:with-foreign-slots (,field-names ptr (:struct cstruct-name))
           ,@(loop :for f :in field-names
                   :collect `(setf ,f (,(read-from-string (concatenate 'string name "-" (string f))) lisp-var)))))
       (defmethod cffi:translate-from-foreign (ptr (type ,cstruct-type))
         (cffi:with-foreign-slots (,field-names ptr (:struct ,cstruct-name))
           (,(read-from-string (concatenate 'string "make-" name))
            ,@(loop :for f :in field-names
                    :collect `(,(read-from-string (concatenate 'string ":" (string f))) ,f) :into s
                    :finally (return (apply #'append s))))))
       (defmacro ,(read-from-string (concatenate 'string "update-" name "-from-foreign"))
           (lisp-var ptr)
         (,(read-from-string "sb-int:quasiquote")
          (progn
            ,@(loop :for f :in field-names
                    :collect `(setf (,(read-from-string (concatenate 'string name "-" (string f)))
                                     (unquote lisp-var))
                                    (cffi:foreign-slot-value ptr '(:struct ,cstruct-name) ',f)))))))))

;; Example
(define-struct "Camera3D"
  "Camera, defines position/orientation in 3d space"
  ((position (:struct %Vector3))
   (target (:struct %Vector3))
   (up (:struct %Vector3))
   (fovy :float)
   (projection :int)))

(cffi:defcfun ("UpdateCamera" %update-camera) :void
  "Update camera position for selected mode"
  (camera (:pointer (:struct %Camera3D))))

(defmacro update-camera (camera)
  (let ((foreign-camera (gensym)))
    `(cffi:with-foreign-object (,foreign-camera (:struct %Camera))
       (cffi:translate-into-foreign-memory ,camera %Camera-tclass ,foreign-camera)
       (%update-camera ,foreign-camera)
       (update-camera3d-from-foreign ,camera ,foreign-camera))))


;; Example
(update-camera test)

Here's an example of what the macros expand to:

;; (define-struct "Camera3D"...)
(progn
 (cffi:defcstruct %camera3d
   "Camera, defines position/orientation in 3d space"
   (position (:struct %vector3))
   (target (:struct %vector3))
   (up (:struct %vector3))
   (fovy :float)
   (projection :int))
 (defstruct camera3d
   "Camera, defines position/orientation in 3d space"
   position
   target
   up
   fovy
   projection)
 (defmethod cffi:translate-into-foreign-memory
            (lisp-var (type %camera3d-tclass) ptr)
   (cffi:with-foreign-slots ((position target up fovy projection) ptr
                             (:struct cstruct-name))
     (setf position (camera3d-position lisp-var))
     (setf target (camera3d-target lisp-var))
     (setf up (camera3d-up lisp-var))
     (setf fovy (camera3d-fovy lisp-var))
     (setf projection (camera3d-projection lisp-var))))
 (defmethod cffi:translate-from-foreign (ptr (type %camera3d-tclass))
   (cffi:with-foreign-slots ((position target up fovy projection) ptr
                             (:struct %camera3d))
     (make-camera3d :position position :target target :up up :fovy fovy
                    :projection projection)))
 (defmacro update-camera3d-from-foreign (lisp-var ptr)
   `(progn
     (setf (camera3d-position (unquote lisp-var))
             (cffi:foreign-slot-value ptr '(:struct %camera3d) 'position))
     (setf (camera3d-target (unquote lisp-var))
             (cffi:foreign-slot-value ptr '(:struct %camera3d) 'target))
     (setf (camera3d-up (unquote lisp-var))
             (cffi:foreign-slot-value ptr '(:struct %camera3d) 'up))
     (setf (camera3d-fovy (unquote lisp-var))
             (cffi:foreign-slot-value ptr '(:struct %camera3d) 'fovy))
     (setf (camera3d-projection (unquote lisp-var))
             (cffi:foreign-slot-value ptr '(:struct %camera3d) 'projection)))))

;; (update-camera test)
(cffi:with-foreign-object (#:g636 (:struct %camera))
  (cffi:translate-into-foreign-memory test %camera-tclass #:g636)
  (%update-camera #:g636)
  (update-camera3d-from-foreign test #:g636))

It should be fairly simple to create a macro that generates the update-camera type functions too.

@kiran-kp
Copy link
Contributor

kiran-kp commented Apr 4, 2022

Oh, I should add that the define-struct isn't portable because I can't figure out nested backquotes. I wrote this in sbcl but I'll keep working on cleaning it up.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants