Skip to content

Conversation

@porky11
Copy link

@porky11 porky11 commented Feb 4, 2016

added "RGBA" and "STPQ" as accessors like in glsl
added the posibility to use small-size symbols
use strings instead of character lists

added "RGBA" and "STPQ" as accessors like in glsl
added the posibility to use small-size symbols
use strings instead of character lists
@cbaggers
Copy link
Owner

cbaggers commented Feb 4, 2016

Sounds good but if we are going to have this we should probably adhere to the glsl spec.

Additionally, there are 3 sets of swizzle masks. You can use xyzw, rgba (for colors), or stpq (for texture coordinates). These three sets have no actual difference; they're just syntactic sugar. You cannot combine names from different sets in a single swizzle operation. So ".xrs" is not a valid swizzle mask.

Currently this allows the invalid :xrs mask.

@cbaggers
Copy link
Owner

cbaggers commented Feb 4, 2016

actually this will likely do it

(define-compiler-macro swizzle (&whole form vec pattern)
  (if (keywordp pattern)
      (let* ((name (string-upcase (cl:symbol-name pattern)))
             (len (cl:length name))
             (arr (gensym "arr"))
             )
        (if (or (> len 4) (< len 2))
            (error "Vectors: swizzle: Cepl vectors cannot have a length less that 2 or greater than 4")
            (let* ((m (truncate (position (aref name 0) "XYZWRGBASTPQ" :test #'char=) 4))
                   (mask (aref #("XYZW" "RGBA" "STPQ") m)))
              `(cl:let ((,arr ,vec))
                 (cl:make-array
                  ,len :element-type 'single-float :initial-contents
                  (list ,@(loop :for char :across name
                             :collect `(aref ,arr ,(or (position char mask :test #'char=)
                                                       (swizzle-error char mask))))))))))
      form))

(defun swizzle (vec pattern)
  (let* ((name (string-upcase (cl:symbol-name pattern)))
         (len (cl:length name)))
    (if (or (> len 4) (< len 2))
        (error "Vectors: swizzle: Cepl vectors cannot have a length less that 2 or greater than 4")
        (let* ((result (cl:make-array (cl:length name) :element-type 'single-float))
               (m (truncate (position (aref name 0) "XYZWRGBASTPQ" :test #'char=) 4))
               (mask (aref #("XYZW" "RGBA" "STPQ") m)))
          (loop :for char :across name :for i :from 0 :do
             (setf (aref result i)
                   (aref vec (or (position char mask :test #'char=)
                                 (swizzle-error char mask)))))
          result))))

(defun swizzle-error (char mask)
  (let ((chars (concatenate 'list mask)))
    (error "Vectors: swizzle: Pattern component ~a was not ~{~a, ~}or ~a~%Note that you can use :xyzw -or- :rgba -or- :stpq but you may not mix masks"
           char
           (butlast chars)
           (car (last chars)))))

If your happy with this then I'll merge it in later

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 this pull request may close these issues.

2 participants