<commit_before>;; TODO: about

(in-package #:arc-7)

;; TODO: this might solve the problem:
;; (print (uiop/lisp-build:current-lisp-file-pathname)) ?
(defvar *glsl-directory*
  (merge-pathnames #p "7-chapter/" (asdf/system:system-source-directory :arcsynthesis)))
;;todo: fix this output to slime-repl solution
(defvar out *standard-output*)  (defvar dbg *debug-io*) (defvar err *error-output*)


;;TODO: note from pjb stating to try ":conc-name" regarding a former rejection
;;       to implement program-data using defstruct, as it creates verbose symbols
(defclass program-data ()
  ((the-program :accessor the-program)
   (model-to-world-matrix-unif :accessor model-to-world-matrix-unif)
   (world-to-camera-matrix-unif :accessor world-to-camera-matrix-unif)
   (camera-to-clip-matrix-unif :accessor camera-to-clip-matrix-unif)
   (base-color-unif :accessor base-color-unif)))


;;program-data
(defvar *uniform-color*)
(defvar *object-color*)
(defvar *uniform-color-tint*)

(defun load-program (str-vertex-shader str-fragment-shader)
  "Create program-data object from shader strings. Hardcoded uniform reference."
  (let ((shader-list (list))
	(data (make-instance 'program-data)))
    (push (arc:create-shader :vertex-shader
	   (arc:file-to-string (merge-pathnames str-vertex-shader *glsl-directory*)))
	  shader-list)
    (push (arc:create-shader :fragment-shader
    	   (arc:file-to-string (merge-pathnames str-fragment-shader *glsl-directory*)))
    	  shader-list)
    (setf (the-program data) (arc:create-program shader-list))
    ;; hard-coding time: also this should undergo test if assignment was successful
    (setf (model-to-world-matrix-unif data)
	  (gl:get-uniform-location (the-program data) "model_to_world_matrix"))
    (setf (world-to-camera-matrix-unif data)
	  (gl:get-uniform-location (the-program data) "world_to_camera_matrix"))
    (setf (camera-to-clip-matrix-unif data)
	  (gl:get-uniform-location (the-program data) "camera_to_clip_matrix"))
    ;; TODO: if uniform doesn't really exist in shader, wasn't opengl lenient about it?
    (setf (base-color-unif data)
	  (gl:get-uniform-location (the-program data) "base_color"))
    data))


(defun initialize-program ()
  (setf *uniform-color*
	(load-program "pos-color-local-transformation.vert" "color-passthrough.frag"))
)


(defparameter *number-of-vertices* 4)

(defparameter +red-color+   '(1.0 0.0 0.0 1.0))
(defparameter +green-color+ '(0.0 1.0 0.0 1.0))
(defparameter +blue-color+  '(0.0 0.0 1.0 1.0))

(defparameter +yellow-color+ '(1.0 1.0 0.0 1.0))
(defparameter +cyan-color+ '(0.0 1.0 1.0 1.0))
(defparameter +magenta-color+ '(1.0 0.0 1.0 1.0))


(defparameter *vertex-data*
  (arc:create-gl-array-from-vector 
`#(
   ;; from arc's unit-plane.xml
     0.5  0.0 -0.5
     0.5  0.0  0.5
    -0.5  0.0  0.5
    -0.5  0.0 -0.5
        ;; vertex colors
    ,@+green-color+
    ,@+green-color+
    ,@+green-color+
    ,@+green-color+
  )))


;; IMPORTANT: in arc's code, index alternate every three indices between points and
;;            colors!!!!!!
(defparameter *index-data*
  (arc::create-gl-array-of-unsigned-short-from-vector
   #(
     0 1 2
     2 3 0
     0 2 1
     2 0 3
     )))

(defvar *vertex-buffer-object*)
(defvar *index-buffer-object*)

(defun initialize-vertex-buffer ()
  (setf *vertex-buffer-object* (first (gl:gen-buffers 1)))

  (gl:bind-buffer :array-buffer *vertex-buffer-object*)
  (gl:buffer-data :array-buffer :static-draw *vertex-data*)
  (gl:bind-buffer :array-buffer 0)

  ;; index-array time:
  (setf *index-buffer-object* (first (gl:gen-buffers 1)))

  (gl:bind-buffer :element-array-buffer *index-buffer-object*)
  (gl:buffer-data :element-array-buffer :static-draw *index-data*)
  (gl:bind-buffer :element-array-buffer  0)  
  )

(defvar *vao*)

(defun initialize-vertex-array-objects ()
  (setf *vao* (first (gl:gen-vertex-arrays 1)))
  (gl:bind-vertex-array *vao*)

  (let ((color-data-offset (* #|size-of(float):|# 4 3 *number-of-vertices*)))
    (gl:bind-buffer :array-buffer *vertex-buffer-object*)
    (%gl:enable-vertex-attrib-array 0)
    (%gl:enable-vertex-attrib-array 1)
    (%gl:vertex-attrib-pointer 0 3 :float :false 0 0)
    (%gl:vertex-attrib-pointer 1 4 :float :false 0 color-data-offset)
    (%gl:bind-buffer :element-array-buffer *index-buffer-object*)

    (%gl:bind-vertex-array 0)
    ;; unbind element-array-buffer? since it already, received data, and
    ;; the *vao* implicit setting is done?
    
    )
  )



(defun init ()
	(initialize-program)
	(initialize-vertex-buffer)
	(initialize-vertex-array-objects)

	;; TODO: why doesn't this seem to affect the unit-plane when it is rotated 360?
	(gl:enable :cull-face)
	(%gl:cull-face :back)
	(%gl:front-face :cw) ;; TODO maybe bad order vertices, need to change; test here

	(gl:viewport 0 0 500 500)

	(gl:enable :depth-test)
	(gl:depth-mask :true)
	(%gl:depth-func :lequal)
	(gl:depth-range 0.0 1.0)
)


;; makeshift solution
(defparameter t-mat (let ((translate-mat4 (glm:make-mat4 1.0))
			 (vec4 (glm:vec4-from-vec3 (glm:vec3 3.0 -5.0 -40.0))))
		     (glm:set-mat4-col translate-mat4 3 vec4)
		     translate-mat4))

;;g_ in arcsynthesis code variable names, is a convention for global-variable naming
;;hence replaced by ear-muffs
(defparameter *sphere-cam-rel-pos* (glm:vec3 67.5 -46.0 150.0))
(defparameter *cam-target* (glm:vec3 0.0 0.4 0.0))


(defun resolve-cam-position ()
  (let* (;(temp-mat (make-instance 'glutil:matrix-stack)) ;; well it isn't used
	 (phi (framework:deg-to-rad (glm:vec. *sphere-cam-rel-pos* :x)))
	 (theta (framework:deg-to-rad (+ (glm:vec. *sphere-cam-rel-pos* :y)
					 90.0)))
	 ;; theta is single-float so SIN will return single-float
	 (sin-theta (sin theta))
	 (cos-theta (cos theta))
	 (cos-phi (cos phi))
	 (sin-phi (sin phi))

	 (dir-to-camera (glm:vec3 (* sin-theta cos-phi)
	 			  cos-theta
	 			  (* sin-theta sin-phi)))
	 )
    (sb-cga:vec+ (sb-cga:vec* dir-to-camera (glm:vec. *sphere-cam-rel-pos* :z))
       *cam-target*)
))

;; Note: c++ function signature: foo(const &var) means:
;; &var we don't need a copy (reuse of resource;pass by reference)
;; and 'const' ensures we will not mutate it (save pass by reference for user
;; of this function). Also this probably helps the compiler.
(defparameter tc (lambda () (calc-look-at-matrix
			     (glm:vec3 0.0 0.0 1.0) ;be
			     (glm:vec3 0.0)         ;look at
			     (glm:vec3 0.0 1.0 0.0)))) ;up
;; TODO: hm the resultin matrix from tc has many rounding problems
(defun calc-look-at-matrix (camera-pt look-pt up-pt)<commit_msg> euclidean-coordinate from polar-coordinate explained (resolve-cam-position)<commit_after>;; TODO: about

(in-package #:arc-7)

;; TODO: this might solve the problem:
;; (print (uiop/lisp-build:current-lisp-file-pathname)) ?
(defvar *glsl-directory*
  (merge-pathnames #p "7-chapter/" (asdf/system:system-source-directory :arcsynthesis)))
;;todo: fix this output to slime-repl solution
(defvar out *standard-output*)  (defvar dbg *debug-io*) (defvar err *error-output*)


;;TODO: note from pjb stating to try ":conc-name" regarding a former rejection
;;       to implement program-data using defstruct, as it creates verbose symbols
(defclass program-data ()
  ((the-program :accessor the-program)
   (model-to-world-matrix-unif :accessor model-to-world-matrix-unif)
   (world-to-camera-matrix-unif :accessor world-to-camera-matrix-unif)
   (camera-to-clip-matrix-unif :accessor camera-to-clip-matrix-unif)
   (base-color-unif :accessor base-color-unif)))


;;program-data
(defvar *uniform-color*)
(defvar *object-color*)
(defvar *uniform-color-tint*)

(defun load-program (str-vertex-shader str-fragment-shader)
  "Create program-data object from shader strings. Hardcoded uniform reference."
  (let ((shader-list (list))
	(data (make-instance 'program-data)))
    (push (arc:create-shader :vertex-shader
	   (arc:file-to-string (merge-pathnames str-vertex-shader *glsl-directory*)))
	  shader-list)
    (push (arc:create-shader :fragment-shader
    	   (arc:file-to-string (merge-pathnames str-fragment-shader *glsl-directory*)))
    	  shader-list)
    (setf (the-program data) (arc:create-program shader-list))
    ;; hard-coding time: also this should undergo test if assignment was successful
    (setf (model-to-world-matrix-unif data)
	  (gl:get-uniform-location (the-program data) "model_to_world_matrix"))
    (setf (world-to-camera-matrix-unif data)
	  (gl:get-uniform-location (the-program data) "world_to_camera_matrix"))
    (setf (camera-to-clip-matrix-unif data)
	  (gl:get-uniform-location (the-program data) "camera_to_clip_matrix"))
    ;; TODO: if uniform doesn't really exist in shader, wasn't opengl lenient about it?
    (setf (base-color-unif data)
	  (gl:get-uniform-location (the-program data) "base_color"))
    data))


(defun initialize-program ()
  (setf *uniform-color*
	(load-program "pos-color-local-transformation.vert" "color-passthrough.frag"))
)


(defparameter *number-of-vertices* 4)

(defparameter +red-color+   '(1.0 0.0 0.0 1.0))
(defparameter +green-color+ '(0.0 1.0 0.0 1.0))
(defparameter +blue-color+  '(0.0 0.0 1.0 1.0))

(defparameter +yellow-color+ '(1.0 1.0 0.0 1.0))
(defparameter +cyan-color+ '(0.0 1.0 1.0 1.0))
(defparameter +magenta-color+ '(1.0 0.0 1.0 1.0))


(defparameter *vertex-data*
  (arc:create-gl-array-from-vector 
`#(
   ;; from arc's unit-plane.xml
     0.5  0.0 -0.5
     0.5  0.0  0.5
    -0.5  0.0  0.5
    -0.5  0.0 -0.5
        ;; vertex colors
    ,@+green-color+
    ,@+green-color+
    ,@+green-color+
    ,@+green-color+
  )))


;; IMPORTANT: in arc's code, index alternate every three indices between points and
;;            colors!!!!!!
(defparameter *index-data*
  (arc::create-gl-array-of-unsigned-short-from-vector
   #(
     0 1 2
     2 3 0
     0 2 1
     2 0 3
     )))

(defvar *vertex-buffer-object*)
(defvar *index-buffer-object*)

(defun initialize-vertex-buffer ()
  (setf *vertex-buffer-object* (first (gl:gen-buffers 1)))

  (gl:bind-buffer :array-buffer *vertex-buffer-object*)
  (gl:buffer-data :array-buffer :static-draw *vertex-data*)
  (gl:bind-buffer :array-buffer 0)

  ;; index-array time:
  (setf *index-buffer-object* (first (gl:gen-buffers 1)))

  (gl:bind-buffer :element-array-buffer *index-buffer-object*)
  (gl:buffer-data :element-array-buffer :static-draw *index-data*)
  (gl:bind-buffer :element-array-buffer  0)  
  )

(defvar *vao*)

(defun initialize-vertex-array-objects ()
  (setf *vao* (first (gl:gen-vertex-arrays 1)))
  (gl:bind-vertex-array *vao*)

  (let ((color-data-offset (* #|size-of(float):|# 4 3 *number-of-vertices*)))
    (gl:bind-buffer :array-buffer *vertex-buffer-object*)
    (%gl:enable-vertex-attrib-array 0)
    (%gl:enable-vertex-attrib-array 1)
    (%gl:vertex-attrib-pointer 0 3 :float :false 0 0)
    (%gl:vertex-attrib-pointer 1 4 :float :false 0 color-data-offset)
    (%gl:bind-buffer :element-array-buffer *index-buffer-object*)

    (%gl:bind-vertex-array 0)
    ;; unbind element-array-buffer? since it already, received data, and
    ;; the *vao* implicit setting is done?
    
    )
  )



(defun init ()
	(initialize-program)
	(initialize-vertex-buffer)
	(initialize-vertex-array-objects)

	;; TODO: why doesn't this seem to affect the unit-plane when it is rotated 360?
	(gl:enable :cull-face)
	(%gl:cull-face :back)
	(%gl:front-face :cw) ;; TODO maybe bad order vertices, need to change; test here

	(gl:viewport 0 0 500 500)

	(gl:enable :depth-test)
	(gl:depth-mask :true)
	(%gl:depth-func :lequal)
	(gl:depth-range 0.0 1.0)
)


;; makeshift solution
(defparameter t-mat (let ((translate-mat4 (glm:make-mat4 1.0))
			 (vec4 (glm:vec4-from-vec3 (glm:vec3 3.0 -5.0 -40.0))))
		     (glm:set-mat4-col translate-mat4 3 vec4)
		     translate-mat4))

;;g_ in arcsynthesis code variable names, is a convention for global-variable naming
;;hence replaced by ear-muffs
(defparameter *sphere-cam-rel-pos* (glm:vec3 67.5 -46.0 150.0) "Order: phi theta r")
(defparameter *cam-target* (glm:vec3 0.0 0.4 0.0))


(defun resolve-cam-position ()
  "Return coordinate space position from polar positions stored in *sphere-cam-rel-pos*"
  (let* ((phi (framework:deg-to-rad (glm:vec. *sphere-cam-rel-pos* :x)))
	 (theta (framework:deg-to-rad (+ (glm:vec. *sphere-cam-rel-pos* :y)
					 90.0)))
	 (sin-theta (sin theta))
	 (cos-theta (cos theta))
	 (cos-phi (cos phi))
	 (sin-phi (sin phi))
	 ;; this is black magic, also called trigonometry: we effectively produce a
	 ;; euclideon vector out of polar coordinates cos-theta is the y
	 ;; shortened/reversed by theta given. Complementaryly sin-theta is the
	 ;; perpendicular x value, but since we need to move by phi, from there, we need
	 ;; to shorten/reverse the x value (sin-theta) by cos-phi, which we do by
	 ;; multiplying it with the cos-phi again complementarily we grow/reverse
	 ;; the perpendicular z. z, if phi is 0-degrees is equal to sin-phi (namely 0)
	 ;; but the moment it is not 0, we need to adjust it by multiplying it with
	 ;; its relative "host" axis which is sin-theta.
	 ;; To facilitate intuitive understanding I strongly recommend drawing it
	 ;; on paper trying to anticipate the relations. The same initial rules
	 ;; apply for any "nested" angles added.
	 (dir-to-camera (glm:vec3 (* sin-theta cos-phi)
	 			  cos-theta
	 			  (* sin-theta sin-phi))))
    ;; Once the direction is set, we need to blow it up by multiplying the
    ;; "euclidean" vector by 'r' which is the :z value of *sphere-cam-rel-pos*
    ;; and add it to the target the camera is supposed to look at, thereby creating
    ;; a geometrical dependent positions of the camera to the *cam-target*
    (sb-cga:vec+ (sb-cga:vec* dir-to-camera (glm:vec. *sphere-cam-rel-pos* :z))
		 *cam-target*)
    ))

;; Note: c++ function signature: foo(const &var) means:
;; &var we don't need a copy (reuse of resource;pass by reference)
;; and 'const' ensures we will not mutate it (save pass by reference for user
;; of this function). Also this probably helps the compiler.
(defparameter tc (lambda () (calc-look-at-matrix
			     (glm:vec3 0.0 0.0 1.0) ;be
			     (glm:vec3 0.0)         ;look at
			     (glm:vec3 0.0 1.0 0.0)))) ;up
;; TODO: hm the resultin matrix from tc has many rounding problems
(defun calc-look-at-matrix (camera-pt look-pt up-pt)
{'fraction_non_alphanumeric': 0.1556474794923929, 'fraction_numerical': 0.025170020332328402, 'mean_word_length': 3.561560601215222, 'pattern_counts': {'":': 2, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2852707', 'n_tokens_mistral': 5516, 'n_tokens_neox': 5108, 'n_words': 1369}