add disabled tests

add disabled tests

Tests that show totally messed up naming of a show.
I just don't know how to really handle working around the problem.

(in-package :user)

(eval-when (compile eval load)
  (require :tester)
  (use-package :util.test))

(defun test-quality (res)
  `(:container :mp4 :source :hdtv :codec :x264 :resolution ,res))

(defmacro with-tget-tests (options &body body)
  (declare (ignore options))
  `(let ((*learn* t)
	 (*log-stream* nil) ;; messages to stdout
	 (*auto-backup* nil))
     ,@body))

(defun test-tget ()
  (test-tget-date-parser)
  (test-tget-episode-parser)
  (test-tget-epnum-comparisions)
  (test-tget-fuzzy-matching)
  (test-tget-feed-reading)
  (test-tget-feed-bugs)
  (test-tget-complete-to)
  (test-tget-processing)
  (+ util.test:*test-errors* util.test:*test-unexpected-failures*))

(defun test-tget-date-parser ()
  (test (* 5 3600)
	(- (parse-rss20-date "Sun, 06 Nov 1994 08:49:37 +0500")
	   (parse-rss20-date "Sun, 06 Nov 1994 08:49:37 +0000")))
  (test (* 7 3600)
	(- (parse-rss20-date "Sun, 06 Nov 1994 08:49:37 +0000")
	   (parse-rss20-date "Sun, 06 Nov 1994 08:49:37 -0700"))))

(defun test-tget-episode-parser ()
  (macrolet ((test-values (values string epr ja)
	       `(do* ((ref ,values (cdr ref))
		      (vals (multiple-value-list
			     (parse-name-season-and-episode
			      ,string
			      :episode-required ,epr
			      :junk-allowed ,ja))
			    (cdr vals)))
		    ((null ref)
		     (when vals
		       (error "extra values: ~s." vals)))
		  (test (car ref)
			(car vals)
			:test #'equal))))
    ;;                                          epr? junk?
    (test-values '("Foo" 3 4)   "Foo.S03E04.mp4" t   t)
    (test-values '("Foo" 3 4)   "Foo.S03E04"     t   t)
    (test-values '(nil)         "Foo.S03.mp4"    t   t)
    (test-values '(nil)         "Foo.S03E04.mp4" t   nil)
    (test-values '("Foo" 3 4)   "Foo S03E04.mp4" t   t)
    (test-values '("Foo" 3 4)   "Foo S03E04"     t   t)
    (test-values '("Foo" 3 4)   "Foo S03E04"     t   nil)
    (test-values '("Foo" 3 4)   "Foo.S03E04"     t   nil)
    (test-values '(nil)         "Foo.S03E04.mp4" t   nil)
    (test-values '("Foo" 3 nil) "Foo S03.mp4"    nil t)
    (test-values '("Foo" 3 nil) "Foo S03"        nil nil)
    (test-values '(nil)         "Foo S03"        t   nil)

    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar.2014.01.02.mp4" nil t)
    (test-values '(nil)                  "The.Foo.Bar.2014.1.2.mp4"   nil t)
    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar 2014.01.02"     nil nil)
    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar 2014.01.02"     nil t)
    (test-values '(nil)                  "The.Foo.Bar 2014.01"        nil nil)
    (test-values '(nil)                  "The.Foo.Bar 2014"           nil nil)
    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar.2014x01.02.mp4" nil t)
    (test-values '(nil)                  "The.Foo.Bar.2014x1.2.mp4"   nil t)
    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar 2014x01.02"     nil nil)
    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar 2014x01.02"     nil t)
    (test-values '(nil)                  "The.Foo.Bar 2014x01"        nil nil)
    ))

(defun test-tget-epnum-comparisions ()
  (test t   (epnum< 1 2))
  (test nil (epnum< 1 1))
  (test t   (epnum< 1 10))
  (test t   (epnum< 1 '(2 . 3)))
  (test t   (epnum< '(1 . 2) 3))
  (test nil (epnum< '(2 . 3) 1))
  (test nil (epnum< 3 '(1 . 2))))

(defun test-tget-fuzzy-matching ()
  (let ((things '(("late night with jimmy fallon"
		   "jimmy fallon"
		   ;; result:
		   "late night with jimmy fallon")
		  ("archer 2009"
		   "archer (2009)"
		   "archer (2009)")
		  ("scandal us"
		   "scandal (us)"
		   "scandal (us)")
		  ("60 minutes"
		   "60 minutes (us)"
		   "60 minutes (us)")
		  ("nattpatruljen (norwegian)"
		   "nattpatruljen"
		   "nattpatruljen (norwegian)")
		  ("the tonight show with jay leno"
		   "jay leno"
		   "the tonight show with jay leno")
		  ("mike & molly"
		   "mike and molly"
		   "mike and molly")
		  ("ncis: los angeles"
		   "ncis los angeles"
		   "ncis: los angeles")
		  ("mr & mrs murder"
		   "mr and mrs murder"
		   "mr and mrs murder")
		  ("law and order: svu"
		   "law & order svu"
		   "law and order: svu")
		  ("dag (norwegian)"
		   "dag"
		   "dag (norwegian)")
		  ("the murdoch mysteries (2008)"
		   "murdoch mysteries"
		   "the murdoch mysteries (2008)")
		  ("pokemon"
		   "pokemon adventures in unova"
		   "pokemon adventures in unova")
		  ("antiques roadshow (uk)"
		   "antiques roadshow uk"
		   "antiques roadshow (uk)")
		  ("diners, drive-ins and dives"
		   "diners drive-ins & dives"
		   "diners, drive-ins and dives")
		  ("r u faster than a redneck?"
		   "r u faster than a redneck"
		   "r u faster than a redneck?")
		  ("foo" "foo" "foo")
		  ("the biggest loser (au)"
		   "the biggest loser australia"
		   "the biggest loser (au)")
		  ("the daily show with jon stewart"
		   "the daily show"
		   "the daily show with jon stewart")
		  ("ntsf:sd:suv" "ntsf sd suv" "ntsf:sd:suv")
		  ("ntsf sd suv" "ntsf:sd:suv" "ntsf:sd:suv")
		  )))
    (dolist (thing things)
      (test (third thing)
	    (fuzzy-compare-series-names (first thing) (second thing))
	    :test #'string=))))

(defvar *tvt-delay*)

(defun test-db-init ()
  (open-tget-database :if-exists :supersede)
  (setq *torrent-handler* nil)
  ;; Define this before loading the config file, so we don't rely on that
  ;; value.  The test suite requires the value `6'.
  (setq *tvt-delay* 6)
  (load "tget-config/config.cl" :verbose t))

(defun test-tget-feed-reading ()
  (with-tget-tests ()
    (dolist (feed '("tget-test-data/btn.xml"
		    "tget-test-data/eztv.xml"
		    "tget-test-data/tvt.xml"))
      (test-db-init)
      (format t "~%~%;;;;; PARSE FEED: ~a~%~%" feed)
      (mapcar #'rss-to-episode (feed-to-rss-objects :file feed)))))

(defun test-tget-feed-bugs ()
  ;; malformed data
  (with-tget-tests ()
    (test-db-init)
    (let ((e (rss-to-episode
	      (make-rss-item
	       :source :tvtorrents.com

	       :title "The Daily Show with Jon Stewart - 2013x19.12 - Jonah Hill (.mp4)"
	       :link "http://foo.bar.com/blahblah"
	       :guid nil
	       :comments "foo bar"
	       :pub-date "Tue, 31 Dec 2013 00:25:15 +0000"

	       :description
	       "Show Name:The Daily Show with Jon Stewart; Show Title: Jonah Hill (.mp4); Season: 2013; Episode: 19.12; Filename: The.Daily.Show.2013.19.12.Jonah.Hill.HDTV.x264-2HD.mp4;"
	       :type "application/x-bittorrent"
	       :length "417684110"))))
      (test t (episode-p e))
      (test 2013 (episode-season e))
      (test 353 (episode-episode e)))

    (let ((e (rss-to-episode
	      (make-rss-item
	       :source :tvtorrents.com

	       :title "Vikings - 4x00.11 - Foo the Bar (.mp4)"
	       :link "http://foo.bar.com/blahblah"
	       :guid nil
	       :comments "foo the bar"
	       :pub-date "Tue, 31 Dec 2013 00:25:15 +0000"

	       :description
	       "Show Name:Vikings; Show Title: Foo the Bar (.mp4); Season: 4; Episode: 00.11; Filename: Vikings.S04.Foo.the.Bar.HDTV.x264-2HD.mp4;"
	       :type "application/x-bittorrent"
	       :length "417684110"))))
      (test t (episode-p e))
      (test 4 (episode-season e))
      (test 11 (episode-episode e)))))

(defun test-tget-complete-to ()
  (test-db-init)
  (with-tget-tests ()
    (macrolet
	((with-series ((var &key name complete-to discontinuous-episodes)
		       &body body)
	   (let ((g-name (gensym))
		 (g-c-t (gensym))
		 (g-d-e (gensym)))
	     `(let* ((,g-name ,name)
		     (,g-c-t ,complete-to)
		     (,g-d-e ,discontinuous-episodes)
		     (,var
		      (make-instance 'series
			:name (gensym ,g-name)
			:complete-to ,g-c-t
			:date-based nil
			:discontinuous-episodes ,g-d-e)))
		(unwind-protect (progn ,@body)
		  (delete-instance ,var))))))

      (with-series (series
		    :name "vikings"
		    :complete-to nil
		    :discontinuous-episodes nil)
	(update-complete-to series 1 3)
	(test '(1 . 3) (series-complete-to series)
	      :test #'equal :fail-info "test 1a")
	(test nil (series-discontinuous-episodes series)
	       :fail-info "test 1b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes nil)
	(update-complete-to series 1 3)
	(test '(1 . 3) (series-complete-to series)
	      :test #'equal :fail-info "test 2a")
	(test nil (series-discontinuous-episodes series) :fail-info "test 2b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes nil)
	(update-complete-to series 1 1)
	(test '(1 . 2) (series-complete-to series)
	      :test #'equal :fail-info "test 3a")
	(test nil (series-discontinuous-episodes series) :fail-info "test 3b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes nil)
	(update-complete-to series 1 4)
	(test '(1 . 2) (series-complete-to series)
	      :test #'equal :fail-info "test 4a")
	(test '((1 . 4)) (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 4b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes '((1 . 4)))
	(update-complete-to series 1 3)
	(test '(1 . 4) (series-complete-to series)
	      :test #'equal :fail-info "test 5a")
	(test nil (series-discontinuous-episodes series) :fail-info "test 5b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes '((1 . 4) (1 . 5)
					      (1 . 7) (1 . 8)))
	(update-complete-to series 1 3)
	(test '(1 . 5) (series-complete-to series)
	      :test #'equal :fail-info "test 6a")
	(test '((1 . 7) (1 . 8)) (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 6b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes '((1 . 6)))
	(update-complete-to series 1 4)
	(test '(1 . 4) (series-complete-to series)
	      :test #'equal :fail-info "test 7a")
	(test '((1 . 6)) (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 7b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 10)
		    :discontinuous-episodes nil)
	(update-complete-to series 2 1)
	(test '(2 . 1) (series-complete-to series)
	      :test #'equal :fail-info "test 8a")
	(test nil (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 8b"))

      ;; This should never happen, in practice, but you never know:
      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 10)
		    :discontinuous-episodes nil)
	(update-complete-to series 2 2)
	(test '(1 . 10) (series-complete-to series)
	      :test #'equal :fail-info "test 9a")
	(test '((2 . 2)) (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 9b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(28 . 11)
		    :discontinuous-episodes '((28 . 14)))
	(update-complete-to series 28 11)
	(test '(28 . 11) (series-complete-to series) :test #'equal
	      :fail-info "test 10a")
	(test '((28 . 14)) (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 10b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(28 . 11)
		    :discontinuous-episodes '((28 . 14)))
	(update-complete-to series 28 9999)
	(test '(28 . 9999) (series-complete-to series) :test #'equal
	      :fail-info "test 11a")
	(test nil (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 11b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(28 . 11)
		    :discontinuous-episodes '((28 . 14) (28 . 16) (28 . 20)))
	(update-complete-to series 28 9999)
	(test '(28 . 9999) (series-complete-to series) :test #'equal
	      :fail-info "test 11c")
	(test nil (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 11d"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(28 . 11)
		    :discontinuous-episodes '((28 . 14) (28 . 16) (28 . 20)
					      (29 . 1)))
	(update-complete-to series 28 9999)
	(test '(29 . 1) (series-complete-to series) :test #'equal
	      :fail-info "test 12a")
	(test nil (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 12b"))
      )))

(defvar *test-downloaded-episodes* nil)

(defun test-select-episode (ep)
  (format t "select=~a~%" ep)
  (push ep *test-downloaded-episodes*))

(defun test-make-eps (&rest things)
  (test-db-init)
  (dolist (thing things)
    (destructuring-bind (filename &key hours transient)
	thing
      (multiple-value-bind (series-name season episode repack
			    container source codec resolution)
	  (extract-episode-info-from-filename filename)
	(let ((title (format nil "~a S~aE~a" series-name
			     season episode))
	      (pub-date
	       ;; `hours' is the hours back from now
	       (- (get-universal-time)
		  ;; seconds in the past
		  (floor (* hours 3600)))))
	  (make-episode
	   :series (or (query-series-name-to-series series-name)
		       (error "no series??? ~s" series-name))
	   :series-name series-name
	   :full-title title
	   :title title
	   :torrent-url title
	   :pub-date pub-date
	   :season season
	   :episode episode
	   :pretty-epnum
	   (season-and-episode-to-pretty-epnum season episode)
	   :repack repack
	   :container container
	   :source source
	   :codec codec
	   :resolution resolution
	   :filename filename
	   :transient transient)))))
  (tget-commit *main*)
  (tget-commit *temp*)
  (setq *test-downloaded-episodes* nil)
  (process-transient-objects (retrieve-from-index 'group 'name :kevin
						  :db *main*)
			     #'test-select-episode))

(defun test-tget-processing (&aux *test-downloaded-episodes*)
  (with-tget-tests ()
;;;; weird naming:
    (test-make-eps
     '("Vikings.S22E11E12.720p.HDTV.X264-DIMENSION.mkv" :hours 1
       :transient t))
    (test 0 (length *test-downloaded-episodes*)
	  :fail-info "test 0")

;;;; should wait longer for :sd ep
    (test-make-eps
     '("vikings.s01e01.repack.hdtv.x264-2hd.mp4" :hours 5.5 :transient t)
     '("vikings.s01e01.720p.hdtv.x264-2hd.mkv" :hours 6.5 :transient t))
    (test 0 (length *test-downloaded-episodes*)
	  :fail-info "test 1")

;;;; should download the :sd ep
    (test-make-eps
     '("vikings.s01e01.repack.hdtv.x264-2hd.mp4" :hours 6.5 :transient t)
     '("vikings.s01e01.720p.hdtv.x264-2hd.mkv" :hours 7.5 :transient t))
    (when (test 1 (length *test-downloaded-episodes*)
		:fail-info "test 2.1")
      (test :sd (episode-resolution (car *test-downloaded-episodes*))
	    :fail-info "test 2.2"))

;;;; should download the repack
    (test-make-eps
     '("vikings.s01e01.hdtv.x264-2hd.mp4" :hours 10 :transient nil)
     '("vikings.s01e01.repack.hdtv.x264-2hd.mp4" :hours 6.5 :transient t))
    (when (test 1 (length *test-downloaded-episodes*)
		:fail-info "test 3.1")
      (test t (episode-repack (car *test-downloaded-episodes*))
	    :fail-info "test 3.2"))

;;;; should NOT download the repack
    (test-make-eps
     '("vikings.s01e01.hdtv.x264-2hd.mp4" :hours 10 :transient nil)
     '("vikings.s01e01.REPACK.720p.hdtv.x264-2hd.mkv" :hours 7.5
       :transient t))
    (test 0 (length *test-downloaded-episodes*)
	  :fail-info "test 4")

;;;; should download the repack
    (test-make-eps
     '("vikings.s01e01.hdtv.x264-2hd.mp4" :hours 10 :transient nil)
     '("vikings.s01e01.REPACK.720p.hdtv.x264-2hd.mkv" :hours 7.5
       :transient t)
     '("vikings.s01e01.REPACK.hdtv.x264-2hd.mp4" :hours 6.5
       :transient t))
    (when (test 1 (length *test-downloaded-episodes*)
		:fail-info "test 5")
      (test t (episode-repack (car *test-downloaded-episodes*))
	    :fail-info "test 5.2")
      (test :sd (episode-resolution (car *test-downloaded-episodes*))
	    :fail-info "test 5.3"))

    (dolist (name '("Mad.Men.S06E01-E02.PROPER.HDTV.x264-2HD.mp4"
		    "Mad.Men.S06E01E02.PROPER.HDTV.x264-2HD.mp4"
		    "mad.men.s06e01e02.repack.hdtv.x264-2hd.mp4"))
      (test-make-eps (list name :hours 7 :transient t))
      (when (test 1 (length *test-downloaded-episodes*)
		  :fail-info "test 6.1")
	(let ((ep (car *test-downloaded-episodes*)))
	  (test t (episode-repack ep)
		:fail-info "test 6.2")
	  (test :sd (episode-resolution ep)
		:fail-info "test 6.3")
	  (test "S06E01-E02" (episode-pretty-epnum ep)
		:test #'string=
		:fail-info "test 6.4")
	  (test '(6 . 2) (series-complete-to (episode-series ep))
		:test #'equal
		:fail-info "test 6.5"))))

;;;; inconsistent naming: switching from ep numbering & date numbering.  If
;;;; ep #'s are there, use those
    #+ignore

;;;; need to figure out the right way to deal with this one....

;;;; maybe signal a warning when an ep-based name is found for a date-based
;;;; series??? (or vice versa)

    (let ((e1 (convert-rss-to-episode
	       :tvtorrents.com
	       #S(rss-item :source :tvtorrents.com
			   :title "Last Week Tonight with John Oliver - 1x14 - Episode 14 (.mp4) (Repack)"
			   :link "http://torrent.tvtorrents.com/FetchTorrentServlet?info_hash=3a88c4a7c21d1b2b1eec230ab941254ab3aa269f&digest=0a8994688db11176c1a3ec73737ed3d0cfccf25a&hash=c4811c3cd8c978b652b9964e44b01ad99982ba6f"
			   :guid nil
			   :comments "http://www.tvtorrents.com/loggedin/torrent.do?info_hash=3a88c4a7c21d1b2b1eec230ab941254ab3aa269f"
			   :pub-date "Tue, 12 Aug 2014 05:49:03 +0000"
			   :description "Show Name:Last Week Tonight with John Oliver; Show Title: Episode 14 (.mp4) (Repack); Season: 1; Episode: 14; Filename: Last.Week.Tonight.With.John.Oliver.2014.08.10.REPACK.HDTV.x264-BAJSKORV.mp4;"
			   :type "application/x-bittorrent"
			   :length "201587214")))
	  (e2 (convert-rss-to-episode
	       :tvtorrents.com
	       #S(rss-item :source :tvtorrents.com
			   :title "Last Week Tonight with John Oliver - 1x15 - Episode 15 (720p .mkv)"
			   :link "http://torrent.tvtorrents.com/FetchTorrentServlet?info_hash=4d1b44b442ccdba4ba24e9d1dfe3394ca3d9dd82&digest=0a8994688db11176c1a3ec73737ed3d0cfccf25a&hash=2c1c500c1fd2fc45a7af0886b379a35488c31086"
			   :guid nil
			   :comments "http://www.tvtorrents.com/loggedin/torrent.do?info_hash=4d1b44b442ccdba4ba24e9d1dfe3394ca3d9dd82"
			   :pub-date "Mon, 18 Aug 2014 09:34:40 +0000"
			   :description "Show Name:Last Week Tonight with John Oliver; Show Title: Episode 15 (720p .mkv); Season: 1; Episode: 15; Filename: Last.Week.Tonight.With.John.Oliver.S01E15.720p.HDTV.x264-BATV.mkv;"
			   :type "application/x-bittorrent"
			   :length "902990079")))
	  )
      )

    ))

(in-package :user)

(eval-when (compile eval load)
  (require :tester)
  (use-package :util.test))

(defun test-quality (res)
  `(:container :mp4 :source :hdtv :codec :x264 :resolution ,res))

(defmacro with-tget-tests (options &body body)
  (declare (ignore options))
  `(let ((*learn* t)
	 (*log-stream* nil) ;; messages to stdout
	 (*auto-backup* nil))
     ,@body))

(defun test-tget ()
  (test-tget-date-parser)
  (test-tget-episode-parser)
  (test-tget-epnum-comparisions)
  (test-tget-fuzzy-matching)
  (test-tget-feed-reading)
  (test-tget-feed-bugs)
  (test-tget-complete-to)
  (test-tget-processing)
  (+ util.test:*test-errors* util.test:*test-unexpected-failures*))

(defun test-tget-date-parser ()
  (test (* 5 3600)
	(- (parse-rss20-date "Sun, 06 Nov 1994 08:49:37 +0500")
	   (parse-rss20-date "Sun, 06 Nov 1994 08:49:37 +0000")))
  (test (* 7 3600)
	(- (parse-rss20-date "Sun, 06 Nov 1994 08:49:37 +0000")
	   (parse-rss20-date "Sun, 06 Nov 1994 08:49:37 -0700"))))

(defun test-tget-episode-parser ()
  (macrolet ((test-values (values string epr ja)
	       `(do* ((ref ,values (cdr ref))
		      (vals (multiple-value-list
			     (parse-name-season-and-episode
			      ,string
			      :episode-required ,epr
			      :junk-allowed ,ja))
			    (cdr vals)))
		    ((null ref)
		     (when vals
		       (error "extra values: ~s." vals)))
		  (test (car ref)
			(car vals)
			:test #'equal))))
    ;;                                          epr? junk?
    (test-values '("Foo" 3 4)   "Foo.S03E04.mp4" t   t)
    (test-values '("Foo" 3 4)   "Foo.S03E04"     t   t)
    (test-values '(nil)         "Foo.S03.mp4"    t   t)
    (test-values '(nil)         "Foo.S03E04.mp4" t   nil)
    (test-values '("Foo" 3 4)   "Foo S03E04.mp4" t   t)
    (test-values '("Foo" 3 4)   "Foo S03E04"     t   t)
    (test-values '("Foo" 3 4)   "Foo S03E04"     t   nil)
    (test-values '("Foo" 3 4)   "Foo.S03E04"     t   nil)
    (test-values '(nil)         "Foo.S03E04.mp4" t   nil)
    (test-values '("Foo" 3 nil) "Foo S03.mp4"    nil t)
    (test-values '("Foo" 3 nil) "Foo S03"        nil nil)
    (test-values '(nil)         "Foo S03"        t   nil)

    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar.2014.01.02.mp4" nil t)
    (test-values '(nil)                  "The.Foo.Bar.2014.1.2.mp4"   nil t)
    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar 2014.01.02"     nil nil)
    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar 2014.01.02"     nil t)
    (test-values '(nil)                  "The.Foo.Bar 2014.01"        nil nil)
    (test-values '(nil)                  "The.Foo.Bar 2014"           nil nil)
    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar.2014x01.02.mp4" nil t)
    (test-values '(nil)                  "The.Foo.Bar.2014x1.2.mp4"   nil t)
    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar 2014x01.02"     nil nil)
    (test-values '("The.Foo.Bar" 2014 2) "The.Foo.Bar 2014x01.02"     nil t)
    (test-values '(nil)                  "The.Foo.Bar 2014x01"        nil nil)
    ))

(defun test-tget-epnum-comparisions ()
  (test t   (epnum< 1 2))
  (test nil (epnum< 1 1))
  (test t   (epnum< 1 10))
  (test t   (epnum< 1 '(2 . 3)))
  (test t   (epnum< '(1 . 2) 3))
  (test nil (epnum< '(2 . 3) 1))
  (test nil (epnum< 3 '(1 . 2))))

(defun test-tget-fuzzy-matching ()
  (let ((things '(("late night with jimmy fallon"
		   "jimmy fallon"
		   ;; result:
		   "late night with jimmy fallon")
		  ("archer 2009"
		   "archer (2009)"
		   "archer (2009)")
		  ("scandal us"
		   "scandal (us)"
		   "scandal (us)")
		  ("60 minutes"
		   "60 minutes (us)"
		   "60 minutes (us)")
		  ("nattpatruljen (norwegian)"
		   "nattpatruljen"
		   "nattpatruljen (norwegian)")
		  ("the tonight show with jay leno"
		   "jay leno"
		   "the tonight show with jay leno")
		  ("mike & molly"
		   "mike and molly"
		   "mike and molly")
		  ("ncis: los angeles"
		   "ncis los angeles"
		   "ncis: los angeles")
		  ("mr & mrs murder"
		   "mr and mrs murder"
		   "mr and mrs murder")
		  ("law and order: svu"
		   "law & order svu"
		   "law and order: svu")
		  ("dag (norwegian)"
		   "dag"
		   "dag (norwegian)")
		  ("the murdoch mysteries (2008)"
		   "murdoch mysteries"
		   "the murdoch mysteries (2008)")
		  ("pokemon"
		   "pokemon adventures in unova"
		   "pokemon adventures in unova")
		  ("antiques roadshow (uk)"
		   "antiques roadshow uk"
		   "antiques roadshow (uk)")
		  ("diners, drive-ins and dives"
		   "diners drive-ins & dives"
		   "diners, drive-ins and dives")
		  ("r u faster than a redneck?"
		   "r u faster than a redneck"
		   "r u faster than a redneck?")
		  ("foo" "foo" "foo")
		  ("the biggest loser (au)"
		   "the biggest loser australia"
		   "the biggest loser (au)")
		  ("the daily show with jon stewart"
		   "the daily show"
		   "the daily show with jon stewart")
		  ("ntsf:sd:suv" "ntsf sd suv" "ntsf:sd:suv")
		  ("ntsf sd suv" "ntsf:sd:suv" "ntsf:sd:suv")
		  )))
    (dolist (thing things)
      (test (third thing)
	    (fuzzy-compare-series-names (first thing) (second thing))
	    :test #'string=))))

(defvar *tvt-delay*)

(defun test-db-init ()
  (open-tget-database :if-exists :supersede)
  (setq *torrent-handler* nil)
  ;; Define this before loading the config file, so we don't rely on that
  ;; value.  The test suite requires the value `6'.
  (setq *tvt-delay* 6)
  (load "tget-config/config.cl" :verbose t))

(defun test-tget-feed-reading ()
  (with-tget-tests ()
    (dolist (feed '("tget-test-data/btn.xml"
		    "tget-test-data/eztv.xml"
		    "tget-test-data/tvt.xml"))
      (test-db-init)
      (format t "~%~%;;;;; PARSE FEED: ~a~%~%" feed)
      (mapcar #'rss-to-episode (feed-to-rss-objects :file feed)))))

(defun test-tget-feed-bugs ()
  ;; malformed data
  (with-tget-tests ()
    (test-db-init)
    (let ((e (rss-to-episode
	      (make-rss-item
	       :source :tvtorrents.com

	       :title "The Daily Show with Jon Stewart - 2013x19.12 - Jonah Hill (.mp4)"
	       :link "http://foo.bar.com/blahblah"
	       :guid nil
	       :comments "foo bar"
	       :pub-date "Tue, 31 Dec 2013 00:25:15 +0000"

	       :description
	       "Show Name:The Daily Show with Jon Stewart; Show Title: Jonah Hill (.mp4); Season: 2013; Episode: 19.12; Filename: The.Daily.Show.2013.19.12.Jonah.Hill.HDTV.x264-2HD.mp4;"
	       :type "application/x-bittorrent"
	       :length "417684110"))))
      (test t (episode-p e))
      (test 2013 (episode-season e))
      (test 353 (episode-episode e)))

    (let ((e (rss-to-episode
	      (make-rss-item
	       :source :tvtorrents.com

	       :title "Vikings - 4x00.11 - Foo the Bar (.mp4)"
	       :link "http://foo.bar.com/blahblah"
	       :guid nil
	       :comments "foo the bar"
	       :pub-date "Tue, 31 Dec 2013 00:25:15 +0000"

	       :description
	       "Show Name:Vikings; Show Title: Foo the Bar (.mp4); Season: 4; Episode: 00.11; Filename: Vikings.S04.Foo.the.Bar.HDTV.x264-2HD.mp4;"
	       :type "application/x-bittorrent"
	       :length "417684110"))))
      (test t (episode-p e))
      (test 4 (episode-season e))
      (test 11 (episode-episode e)))))

(defun test-tget-complete-to ()
  (test-db-init)
  (with-tget-tests ()
    (macrolet
	((with-series ((var &key name complete-to discontinuous-episodes)
		       &body body)
	   (let ((g-name (gensym))
		 (g-c-t (gensym))
		 (g-d-e (gensym)))
	     `(let* ((,g-name ,name)
		     (,g-c-t ,complete-to)
		     (,g-d-e ,discontinuous-episodes)
		     (,var
		      (make-instance 'series
			:name (gensym ,g-name)
			:complete-to ,g-c-t
			:date-based nil
			:discontinuous-episodes ,g-d-e)))
		(unwind-protect (progn ,@body)
		  (delete-instance ,var))))))

      (with-series (series
		    :name "vikings"
		    :complete-to nil
		    :discontinuous-episodes nil)
	(update-complete-to series 1 3)
	(test '(1 . 3) (series-complete-to series)
	      :test #'equal :fail-info "test 1a")
	(test nil (series-discontinuous-episodes series)
	       :fail-info "test 1b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes nil)
	(update-complete-to series 1 3)
	(test '(1 . 3) (series-complete-to series)
	      :test #'equal :fail-info "test 2a")
	(test nil (series-discontinuous-episodes series) :fail-info "test 2b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes nil)
	(update-complete-to series 1 1)
	(test '(1 . 2) (series-complete-to series)
	      :test #'equal :fail-info "test 3a")
	(test nil (series-discontinuous-episodes series) :fail-info "test 3b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes nil)
	(update-complete-to series 1 4)
	(test '(1 . 2) (series-complete-to series)
	      :test #'equal :fail-info "test 4a")
	(test '((1 . 4)) (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 4b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes '((1 . 4)))
	(update-complete-to series 1 3)
	(test '(1 . 4) (series-complete-to series)
	      :test #'equal :fail-info "test 5a")
	(test nil (series-discontinuous-episodes series) :fail-info "test 5b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes '((1 . 4) (1 . 5)
					      (1 . 7) (1 . 8)))
	(update-complete-to series 1 3)
	(test '(1 . 5) (series-complete-to series)
	      :test #'equal :fail-info "test 6a")
	(test '((1 . 7) (1 . 8)) (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 6b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 2)
		    :discontinuous-episodes '((1 . 6)))
	(update-complete-to series 1 4)
	(test '(1 . 4) (series-complete-to series)
	      :test #'equal :fail-info "test 7a")
	(test '((1 . 6)) (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 7b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 10)
		    :discontinuous-episodes nil)
	(update-complete-to series 2 1)
	(test '(2 . 1) (series-complete-to series)
	      :test #'equal :fail-info "test 8a")
	(test nil (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 8b"))

      ;; This should never happen, in practice, but you never know:
      (with-series (series
		    :name "vikings"
		    :complete-to '(1 . 10)
		    :discontinuous-episodes nil)
	(update-complete-to series 2 2)
	(test '(1 . 10) (series-complete-to series)
	      :test #'equal :fail-info "test 9a")
	(test '((2 . 2)) (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 9b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(28 . 11)
		    :discontinuous-episodes '((28 . 14)))
	(update-complete-to series 28 11)
	(test '(28 . 11) (series-complete-to series) :test #'equal
	      :fail-info "test 10a")
	(test '((28 . 14)) (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 10b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(28 . 11)
		    :discontinuous-episodes '((28 . 14)))
	(update-complete-to series 28 9999)
	(test '(28 . 9999) (series-complete-to series) :test #'equal
	      :fail-info "test 11a")
	(test nil (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 11b"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(28 . 11)
		    :discontinuous-episodes '((28 . 14) (28 . 16) (28 . 20)))
	(update-complete-to series 28 9999)
	(test '(28 . 9999) (series-complete-to series) :test #'equal
	      :fail-info "test 11c")
	(test nil (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 11d"))

      (with-series (series
		    :name "vikings"
		    :complete-to '(28 . 11)
		    :discontinuous-episodes '((28 . 14) (28 . 16) (28 . 20)
					      (29 . 1)))
	(update-complete-to series 28 9999)
	(test '(29 . 1) (series-complete-to series) :test #'equal
	      :fail-info "test 12a")
	(test nil (series-discontinuous-episodes series)
	      :test #'equal :fail-info "test 12b"))
      )))

(defvar *test-downloaded-episodes* nil)

(defun test-select-episode (ep)
  (format t "select=~a~%" ep)
  (push ep *test-downloaded-episodes*))

(defun test-make-eps (&rest things)
  (test-db-init)
  (dolist (thing things)
    (destructuring-bind (filename &key hours transient)
	thing
      (multiple-value-bind (series-name season episode repack
			    container source codec resolution)
	  (extract-episode-info-from-filename filename)
	(let ((title (format nil "~a S~aE~a" series-name
			     season episode))
	      (pub-date
	       ;; `hours' is the hours back from now
	       (- (get-universal-time)
		  ;; seconds in the past
		  (floor (* hours 3600)))))
	  (make-episode
	   :series (or (query-series-name-to-series series-name)
		       (error "no series??? ~s" series-name))
	   :series-name series-name
	   :full-title title
	   :title title
	   :torrent-url title
	   :pub-date pub-date
	   :season season
	   :episode episode
	   :pretty-epnum
	   (season-and-episode-to-pretty-epnum season episode)
	   :repack repack
	   :container container
	   :source source
	   :codec codec
	   :resolution resolution
	   :filename filename
	   :transient transient)))))
  (tget-commit *main*)
  (tget-commit *temp*)
  (setq *test-downloaded-episodes* nil)
  (process-transient-objects (retrieve-from-index 'group 'name :kevin
						  :db *main*)
			     #'test-select-episode))

(defun test-tget-processing (&aux *test-downloaded-episodes*)
  (with-tget-tests ()
;;;; weird naming:
    (test-make-eps
     '("Vikings.S22E11E12.720p.HDTV.X264-DIMENSION.mkv" :hours 1
       :transient t))
    (test 0 (length *test-downloaded-episodes*)
	  :fail-info "test 0")

;;;; should wait longer for :sd ep
    (test-make-eps
     '("vikings.s01e01.repack.hdtv.x264-2hd.mp4" :hours 5.5 :transient t)
     '("vikings.s01e01.720p.hdtv.x264-2hd.mkv" :hours 6.5 :transient t))
    (test 0 (length *test-downloaded-episodes*)
	  :fail-info "test 1")

;;;; should download the :sd ep
    (test-make-eps
     '("vikings.s01e01.repack.hdtv.x264-2hd.mp4" :hours 6.5 :transient t)
     '("vikings.s01e01.720p.hdtv.x264-2hd.mkv" :hours 7.5 :transient t))
    (when (test 1 (length *test-downloaded-episodes*)
		:fail-info "test 2.1")
      (test :sd (episode-resolution (car *test-downloaded-episodes*))
	    :fail-info "test 2.2"))

;;;; should download the repack
    (test-make-eps
     '("vikings.s01e01.hdtv.x264-2hd.mp4" :hours 10 :transient nil)
     '("vikings.s01e01.repack.hdtv.x264-2hd.mp4" :hours 6.5 :transient t))
    (when (test 1 (length *test-downloaded-episodes*)
		:fail-info "test 3.1")
      (test t (episode-repack (car *test-downloaded-episodes*))
	    :fail-info "test 3.2"))

;;;; should NOT download the repack
    (test-make-eps
     '("vikings.s01e01.hdtv.x264-2hd.mp4" :hours 10 :transient nil)
     '("vikings.s01e01.REPACK.720p.hdtv.x264-2hd.mkv" :hours 7.5
       :transient t))
    (test 0 (length *test-downloaded-episodes*)
	  :fail-info "test 4")

;;;; should download the repack
    (test-make-eps
     '("vikings.s01e01.hdtv.x264-2hd.mp4" :hours 10 :transient nil)
     '("vikings.s01e01.REPACK.720p.hdtv.x264-2hd.mkv" :hours 7.5
       :transient t)
     '("vikings.s01e01.REPACK.hdtv.x264-2hd.mp4" :hours 6.5
       :transient t))
    (when (test 1 (length *test-downloaded-episodes*)
		:fail-info "test 5")
      (test t (episode-repack (car *test-downloaded-episodes*))
	    :fail-info "test 5.2")
      (test :sd (episode-resolution (car *test-downloaded-episodes*))
	    :fail-info "test 5.3"))

    (dolist (name '("Mad.Men.S06E01-E02.PROPER.HDTV.x264-2HD.mp4"
		    "Mad.Men.S06E01E02.PROPER.HDTV.x264-2HD.mp4"
		    "mad.men.s06e01e02.repack.hdtv.x264-2hd.mp4"))
      (test-make-eps (list name :hours 7 :transient t))
      (when (test 1 (length *test-downloaded-episodes*)
		  :fail-info "test 6.1")
	(let ((ep (car *test-downloaded-episodes*)))
	  (test t (episode-repack ep)
		:fail-info "test 6.2")
	  (test :sd (episode-resolution ep)
		:fail-info "test 6.3")
	  (test "S06E01-E02" (episode-pretty-epnum ep)
		:test #'string=
		:fail-info "test 6.4")
	  (test '(6 . 2) (series-complete-to (episode-series ep))
		:test #'equal
		:fail-info "test 6.5"))))
    ))


added cone and cylinder normal, seems ok

#include "kernel_header.h"
#include "kernel_matrix.h"
#include "kernel_cam.h"
#include "kernel_color.h"
#include "kernel_cone.h"
#include "kernel_cylinder.h"
#include "kernel_data.h"
#include "kernel_debug.h"
#include "kernel_plane.h"
#include "kernel_sphere.h"

float3					rotate_obj(float3 v, float pitch, float yaw, float roll)
{
	float3				res;

	res = rotat_zyx(v, pitch, yaw, roll);

	return (normalize(res));
}

static t_hit			ray_hit(const float3 origin, const float3 ray, const t_scene scene)
{
	unsigned int			i = 0;
	int						max = get_max_obj(PARAM);
	t_hit					hit = hit_init();
	float					dist = 0;

	while (i < max)
	{
		if (i < PARAM->n_cones)
			if (((dist = inter_cone(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 1;
				hit.id = i;
			}
		if (i < PARAM->n_cylinders)
			if (((dist = inter_cylinder(CYLIND[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
		//	if (((dist = inter_cylinder(CYLIND[i].height, rotate_obj(CYLIND[i].dir, CYLIND[i].pitch, CYLIND[i].yaw, 0), CYLIND[i].radius, CYLIND[i].pos, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 2;
				hit.id = i;
			}
		if (i < PARAM->n_planes)
			if (((dist = inter_plan(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 4;
				hit.id = i;
			}
		if (i < PARAM->n_spheres)
			if (((dist = inter_sphere(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 5;
				hit.id = i;
			}
		i++;
	}
	return (hit);
}

float3			rotate_matrix(float angle, float3 v)
{
	float3		res;

	res.x = v.x;
	res.y = (cos(angle) * v.y) - (sin(angle) * v.z);
	res.z = (sin(angle) * v.y) + (cos(angle) * v.z);
	return (res);
}

float16			trans_matrix(float3 dir, float angle)
{
	float16		res = 0;
	float3		rot = 0;

	rot = rotate_obj(dir, 0, angle, 0);
	res[0] = rot.x;
	res[1] = rot.y;
	res[2] = rot.z;
	rot = rotate_obj(dir, -angle, 0, 0);
	res[4] = rot.x;
	res[5] = rot.y;
	res[6] = rot.z;
	res[8] = dir.x;
	res[9] = dir.y;
	res[10] = dir.z;
	return (res);
}

float3			apply_matrix(float16 mat, float3 v)
{
	float3		res = 0;

	res.x = mat[0] * v.x + mat[4] * v.y + mat[8] * v.z;
	res.y = mat[1] * v.x + mat[5] * v.y + mat[9] * v.z;
	res.z = mat[2] * v.x + mat[6] * v.y + mat[10] * v.z;
	return (res);
}

float3			get_cylinder_normal(const t_scene scene, const t_hit hit)
{
	float3 res = 0;
	float3 v = 0;
	float3 project = 0;
	float3 cyl_dir = 0;
	float doty = 0;

	cyl_dir = normalize(CYLIND[hit.id].dir);
	v = hit.pos - CYLIND[hit.id].pos;
	doty = dot(v, cyl_dir);
	project = doty * cyl_dir;
	res = v - project;
	return (normalize(res));
}

float3			get_cone_normale(const t_scene scene, const t_hit hit)
{
	float3 res = 0;
	float3 v = 0;
	float3 project = 0;
	float3 cone_dir = 0;
	float doty = 0;

	cone_dir = normalize(CONES[hit.id].dir);
	v = hit.pos - CONES[hit.id].pos;
	doty = dot(v, CONES[hit.id].dir);
	project = doty * cone_dir;
	res = v - project;
	return (normalize(res));
}

float3			get_hit_normale(t_scene scene, t_hit hit)
{
	float3		res;

	if (hit.type == 1)
	{
		res = get_cone_normale(scene, hit);
	//	float k = radians(CONES[hit.id].angle);
	//	k = tan(k);
	//	k = 1 + k * k;
	//	res = dot(-scene.ray, fast_normalize(CONES[hit.id].dir)) * \
	//		hit.dist - dot(ACTIVECAM.pos + PARAM->mvt - CONES[hit.id].pos, fast_normalize(CONES[hit.id].dir));
	//	res = ((hit.pos - fast_normalize(CONES[hit.id].pos)) - (k * fast_normalize(CONES[hit.id].dir) * res)) * -1;
	}
	else if (hit.type == 2)
	{
		res = get_cylinder_normal(scene, hit);
	}
	else if (hit.type == 4)
	{
		if (dot(PLANE[hit.id].normale, -scene.ray) < 0)
			res = -PLANE[hit.id].normale;
		else
			res = PLANE[hit.id].normale;
	}
	else if (hit.type == 5)
		res = hit.pos - SPHERE[hit.id].pos;
	return (fast_normalize(res));
}

static unsigned int			phong(const t_hit hit, const t_scene scene)
{
	int					i = -1;
	unsigned int		res_color = get_ambient(scene, get_obj_hue(scene, hit));
	float				tmp;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit = hit_init();

	while (++i < PARAM->n_lights)
	{
		tmp = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = length(light_ray.dir);
		light_ray.dir = normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		light_hit.id = i;
		light_hit.type = 3;
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

unsigned int			phong2(t_hit hit, t_scene scene)
{
	int					i = -1;
	unsigned int		res_color = get_ambient(scene, get_obj_hue(scene, hit));
	float				tmp = 0;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit;

	while (++i < PARAM->n_lights)
	{
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = length(light_ray.dir);
		light_ray.dir = normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

static unsigned int		bounce(const t_scene scene, const t_hit old_hit, const int depth)
{
	int				i = depth;
	unsigned int	color = 0;
	float3			reflex = 0;
	t_hit			new_hit;
	while (i > 0)
	{
		reflex = normalize(scene.ray - (2 * (float)dot(old_hit.normale, scene.ray) * old_hit.normale));
		new_hit.dist = MAX_DIST;
		new_hit = ray_hit(old_hit.pos, reflex, scene);
		if (new_hit.dist > 0 && new_hit.dist < MAX_DIST)
		{
			new_hit.pos = (new_hit.dist * reflex) + old_hit.pos;
			new_hit.normale = get_hit_normale(scene, new_hit);
			new_hit.pos = new_hit.pos + ((new_hit.dist / 100) * new_hit.normale);
			color += 0.1 * phong2(new_hit, scene);
		}
		i--;
	}
	return (color);
}

static unsigned int	get_pixel_color(const t_scene scene)
{
	t_hit			hit;
	int				depth = PARAM->depth;
	unsigned int	color  = 0;
	unsigned int	bounce_color = 0;

	hit.dist = MAX_DIST;
	hit = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	if (hit.dist > 0 && hit.dist < MAX_DIST) // ajout d'une distance max pour virer acnee mais pas fiable a 100%
	{
		hit.pos = (hit.dist * scene.ray) + (ACTIVECAM.pos + PARAM->mvt);
		hit.normale = get_hit_normale(scene, hit);
		hit.pos = hit.pos + ((hit.dist / 100) * hit.normale);
		color = phong(hit, scene);
		if (depth > 0)
			bounce_color = bounce(scene, hit, depth);
		return (color + bounce_color);
//		return (blend_add(color, 0.8*bounce_color));
	}
	return (get_ambient(scene, BACKCOLOR));
}

__kernel void	ray_trace(__global		char		*output,
						  				t_param		param,
						  __constant	t_cam		*cameras,
						  __constant	t_cone		*cones,
						  __constant	t_cylinder	*cylinders,
						  __constant	t_light		*lights,
						  __constant	t_plane		*planes,
						  __constant	t_sphere	*spheres,
						  __global		t_hit		*target_obj)
{
	t_scene		scene = grab_data(cameras, cones, cylinders, lights, planes, spheres, param);
	scene.pix.x = get_global_id(0);
	scene.pix.y = get_global_id(1);
	int			id = scene.pix.x + (PARAM->win_w * scene.pix.y); // NE PAS VIRER ID CAR BESOIN DANS MACRO OUTPUTE
	scene.ray = get_ray_cam(ACTIVECAM, scene, scene.pix.x ,scene.pix.y);
	if (scene.pix.x == PARAM->mou_x && scene.pix.y == PARAM->mou_y)
		*target_obj = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	OUTPUTE = get_pixel_color(scene);
}

#include "kernel_header.h"
#include "kernel_matrix.h"
#include "kernel_cam.h"
#include "kernel_color.h"
#include "kernel_cone.h"
#include "kernel_cylinder.h"
#include "kernel_data.h"
#include "kernel_debug.h"
#include "kernel_plane.h"
#include "kernel_sphere.h"

float3					rotate_obj(float3 v, float pitch, float yaw, float roll)
{
	float3				res;

	res = rotat_zyx(v, pitch, yaw, roll);

	return (normalize(res));
}

static t_hit			ray_hit(const float3 origin, const float3 ray, const t_scene scene)
{
	unsigned int			i = 0;
	int						max = get_max_obj(PARAM);
	t_hit					hit = hit_init();
	float					dist = 0;

	while (i < max)
	{
		if (i < PARAM->n_cones)
			if (((dist = inter_cone(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 1;
				hit.id = i;
			}
		if (i < PARAM->n_cylinders)
			if (((dist = inter_cylinder(CYLIND[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
		//	if (((dist = inter_cylinder(CYLIND[i].height, rotate_obj(CYLIND[i].dir, CYLIND[i].pitch, CYLIND[i].yaw, 0), CYLIND[i].radius, CYLIND[i].pos, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 2;
				hit.id = i;
			}
		if (i < PARAM->n_planes)
			if (((dist = inter_plan(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 4;
				hit.id = i;
			}
		if (i < PARAM->n_spheres)
			if (((dist = inter_sphere(scene, i, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 5;
				hit.id = i;
			}
		i++;
	}
	return (hit);
}

float3			rotate_matrix(float angle, float3 v)
{
	float3		res;

	res.x = v.x;
	res.y = (cos(angle) * v.y) - (sin(angle) * v.z);
	res.z = (sin(angle) * v.y) + (cos(angle) * v.z);
	return (res);
}

float16			trans_matrix(float3 dir, float angle)
{
	float16		res = 0;
	float3		rot = 0;

	rot = rotate_obj(dir, 0, angle, 0);
	res[0] = rot.x;
	res[1] = rot.y;
	res[2] = rot.z;
	rot = rotate_obj(dir, -angle, 0, 0);
	res[4] = rot.x;
	res[5] = rot.y;
	res[6] = rot.z;
	res[8] = dir.x;
	res[9] = dir.y;
	res[10] = dir.z;
	return (res);
}

float3			apply_matrix(float16 mat, float3 v)
{
	float3		res = 0;

	res.x = mat[0] * v.x + mat[4] * v.y + mat[8] * v.z;
	res.y = mat[1] * v.x + mat[5] * v.y + mat[9] * v.z;
	res.z = mat[2] * v.x + mat[6] * v.y + mat[10] * v.z;
	return (res);
}

float3			get_hit_normale(t_scene scene, t_hit hit)
{
	float3		res;

	if (hit.type == 1)
	{
		float k = radians(CONES[hit.id].angle);
		k = tan(k);
		k = 1 + k * k;
		res = dot(-scene.ray, fast_normalize(CONES[hit.id].dir)) * \
			hit.dist - dot(ACTIVECAM.pos + PARAM->mvt - CONES[hit.id].pos, fast_normalize(CONES[hit.id].dir));
		res = ((hit.pos - fast_normalize(CONES[hit.id].pos)) - (k * fast_normalize(CONES[hit.id].dir) * res)) * -1;
	}
	else if (hit.type == 2)
	{
		res = hit.pos - scene.cylinders[hit.id].pos;
		res.z = 0;
	}
	else if (hit.type == 4)
	{
		if (dot(PLANE[hit.id].normale, -scene.ray) < 0)
			res = -PLANE[hit.id].normale;
		else
			res = PLANE[hit.id].normale;
	}
	else if (hit.type == 5)
		res = hit.pos - SPHERE[hit.id].pos;
	return (fast_normalize(res));
}

static unsigned int			phong(const t_hit hit, const t_scene scene)
{
	int					i = -1;
	unsigned int		res_color = get_ambient(scene, get_obj_hue(scene, hit));
	float				tmp;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit = hit_init();

	while (++i < PARAM->n_lights)
	{
		tmp = 0;
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = length(light_ray.dir);
		light_ray.dir = normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		light_hit.id = i;
		light_hit.type = 3;
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

unsigned int			phong2(t_hit hit, t_scene scene)
{
	int					i = -1;
	unsigned int		res_color = get_ambient(scene, get_obj_hue(scene, hit));
	float				tmp = 0;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit;

	while (++i < PARAM->n_lights)
	{
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = length(light_ray.dir);
		light_ray.dir = normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0)
				res_color = color_diffuse(scene, hit, light_hit, res_color, tmp);
			reflect = normalize(((float)(2.0 * dot(hit.normale, light_ray.dir)) * hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(scene, hit, light_hit, res_color, tmp);
		}
	}
	return (res_color);
}

static unsigned int		bounce(const t_scene scene, const t_hit old_hit, const int depth)
{
	int				i = depth;
	unsigned int	color = 0;
	float3			reflex = 0;
	t_hit			new_hit;
	while (i > 0)
	{
		reflex = normalize(scene.ray - (2 * (float)dot(old_hit.normale, scene.ray) * old_hit.normale));
		new_hit.dist = MAX_DIST;
		new_hit = ray_hit(old_hit.pos, reflex, scene);
		if (new_hit.dist > 0 && new_hit.dist < MAX_DIST)
		{
			new_hit.pos = (new_hit.dist * reflex) + old_hit.pos;
			new_hit.normale = get_hit_normale(scene, new_hit);
			new_hit.pos = new_hit.pos + ((new_hit.dist / 100) * new_hit.normale);
			color += 0.1 * phong(new_hit, scene);
		}
		i--;
	}
	return (color);
}

static unsigned int	get_pixel_color(const t_scene scene)
{
	t_hit			hit;
	int				depth = PARAM->depth;
	unsigned int	color  = 0;
	unsigned int	bounce_color = 0;

	hit.dist = MAX_DIST;
	hit = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	if (hit.dist > 0 && hit.dist < MAX_DIST) // ajout d'une distance max pour virer acnee mais pas fiable a 100%
	{
		hit.pos = (hit.dist * scene.ray) + (ACTIVECAM.pos + PARAM->mvt);
		hit.normale = get_hit_normale(scene, hit);
		hit.pos = hit.pos + ((hit.dist / 100) * hit.normale);
		color = phong(hit, scene);
		if (depth > 0)
			bounce_color = bounce(scene, hit, depth);
		return (color + bounce_color);
//		return (blend_add(color, 0.8*bounce_color));
	}
	return (get_ambient(scene, BACKCOLOR));
}

__kernel void	ray_trace(__global		char		*output,
						  				t_param		param,
						  __constant	t_cam		*cameras,
						  __constant	t_cone		*cones,
						  __constant	t_cylinder	*cylinders,
						  __constant	t_light		*lights,
						  __constant	t_plane		*planes,
						  __constant	t_sphere	*spheres,
						  __global		t_hit		*target_obj)
{
	t_scene		scene = grab_data(cameras, cones, cylinders, lights, planes, spheres, param);
	scene.pix.x = get_global_id(0);
	scene.pix.y = get_global_id(1);
	int			id = scene.pix.x + (PARAM->win_w * scene.pix.y); // NE PAS VIRER ID CAR BESOIN DANS MACRO OUTPUTE
	scene.ray = get_ray_cam(ACTIVECAM, scene, scene.pix.x ,scene.pix.y);
	if (scene.pix.x == PARAM->mou_x && scene.pix.y == PARAM->mou_y)
		*target_obj = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	OUTPUTE = get_pixel_color(scene);
}


trying to debug speculos

trying to debug speculos

#include "kernel_header.h"
#include "kernel_color.h"
#include "kernel_data.h"
#include "kernel_vector.h"
#include "kernel_debug.h"

float3						rotat_zyx(float3 vect, float pitch, float yaw, float roll)
{
	float3					res;
	float					rad_pitch = pitch * DEG2RAD;
	float					rad_yaw = yaw * DEG2RAD;
	float					rad_roll = roll * DEG2RAD;

	res.x = vect.x * cos(rad_roll) * cos(rad_yaw) + vect.y * (cos(rad_pitch) * -sin(rad_roll) + cos(rad_roll) * sin(rad_yaw) * sin(rad_pitch)) + vect.z * (-sin(rad_roll) * -sin(rad_pitch) + cos(rad_roll) * sin(rad_yaw) * cos(rad_pitch));
	res.y = vect.x * sin(rad_roll) * cos(rad_yaw) + vect.y * (cos(rad_roll) * cos(rad_pitch) + sin(rad_roll) * sin(rad_yaw) * sin(rad_pitch)) + vect.z * (cos(rad_roll) * -sin(rad_pitch) + sin(rad_roll) * sin(rad_yaw) * cos(rad_pitch));
	res.z = vect.x * -sin(rad_yaw) + vect.y * cos(rad_yaw) * sin(rad_pitch) + vect.z * cos(rad_yaw) * cos(rad_pitch);
	return (res);
}

float3						rotat_xyz(float3 vect, float pitch, float yaw, float roll)
{
	float3					res;
	float					rad_pitch = pitch * DEG2RAD;
	float					rad_yaw = yaw * DEG2RAD;
	float					rad_roll = roll * DEG2RAD;

	res.x = vect.x * cos(rad_yaw) * cos(rad_roll) + vect.y * cos(rad_yaw) * -sin(rad_roll) + vect.z * sin(rad_yaw);
	res.y = vect.x * (-sin(rad_pitch) * -sin(rad_yaw) * cos(rad_roll) + cos(rad_pitch) * sin(rad_roll)) + vect.y * (-sin(rad_pitch) * -sin(rad_yaw) * -sin(rad_roll) + cos(rad_pitch) * cos(rad_roll)) + vect.z * cos(rad_yaw) * -sin(rad_pitch);
	res.z = vect.x * (cos(rad_pitch) * -sin(rad_yaw) * cos(rad_roll) + sin(rad_pitch) * sin(rad_roll)) + vect.y * (cos(rad_pitch) * -sin(rad_yaw) * -sin(rad_roll) + sin(rad_pitch) * cos(rad_roll)) + vect.z * cos(rad_yaw) * cos(rad_pitch);
	return (res);
}

float3					rotate_obj(float3 v, float pitch, float yaw, float roll)
{
	float3				res;

	res = rotat_zyx(v, pitch, yaw, roll);

	return (fast_normalize(res));
}

float3					get_sphere_abc(float radius, float3 ray, float3 origin)
{
	float3		abc;

	abc.x = dot(ray, ray);
	abc.y = 2 * dot(ray, origin);
	abc.z = dot(origin, origin) - (radius * radius);
	return (abc);
}

float					inter_sphere(t_sphere sphere, float3 ray, float3 origin)
{
	float3				abc;
	float				d;
	float				res1;
	float				res2;

	origin -= sphere.pos;
	abc = get_sphere_abc(sphere.radius, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		return ((-abc[1]) / (2 * abc[0]));
	res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
	res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
		return (res1);
	return (res2);
}

float3					get_cylinder_abc(float radius, float3 dir, float3 ray, float3 origin)
{
	float3		abc;

	// SEMBLE OK
	abc.x = dot(ray, ray) - (dot(ray, dir) * dot(ray, dir));
	abc.y = 2 * (dot(ray, origin) - (dot(ray, dir) * dot(origin, dir)));
	abc.z = dot(origin, origin) - (dot(origin, dir) * dot(origin, dir)) - (radius * radius);
	return (abc);
}

float					inter_cylinder(float height, float3 dir, float radius, float3 pos, float3 ray, float3 origin)
{
	float3				abc;
	//float3				dir = rotate_obj(cyl.dir, cyl.pitch, cyl.yaw, 0);
	float				d;
	float				res1 = 0;
	float				res2 = 0;
	float				m;

	origin -= pos;
	abc = get_cylinder_abc(radius, dir, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		res1 = (-abc[1]) / (2 * abc[0]);
	else
	{
		res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
		res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	}
	if (res1 < 0 && res2 < 0)
		return (0);
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
	{
		if (height == 0 || (dot(ray, dir) * res1 +
			dot(origin, dir) < height && dot(ray, dir) * res1 +
			dot(origin, dir) > 0))
			return (res1);
	}
	if (height ==  0 || (dot(ray, dir) * res2 +
			dot(origin, dir) < height && dot(ray, dir) * res2 +
			dot(origin, dir) > 0))
		return (res2);
	else
		return (0);
}

float3					get_cone_abc(t_cone cone, float3 ray, float3 origin)
{
	float3		abc = 0;
	float		k = cone.angle * DEG2RAD;
	k = tan(k);
	k = 1 + k * k;

	abc.x = dot(ray, ray) - (k * (dot(ray, cone.dir) * dot(ray, cone.dir)));
	abc.y = 2 * (dot(ray, origin) - (k * \
			(dot(ray, cone.dir) * dot(origin, cone.dir))));
	abc.z = (dot(origin, origin) - \
			(k * (dot(origin, cone.dir) * dot(origin, cone.dir))));
	return (abc);
}

float					inter_cone(t_cone cone, float3 ray, float3 origin)
{
	float3				abc;
	float				d;
	float				res1;
	float				res2;
	float				res;

	origin -= cone.pos;
	abc = get_cone_abc(cone, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		res = (-abc[1]) / (2 * abc[0]);
	res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
	res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
		res = res1;
	else
		res = res2;
	return (res);
}

float					inter_plan(t_plane plane, float3 ray, float3 origin)
{
	float				t;

	if ((t = dot(fast_normalize(ray), fast_normalize(plane.normale))) == 0)
		return (0);
	t = (dot(plane.pos - origin, fast_normalize(plane.normale))) / t;
		if (t < 0.001)
		return (0);
	return (t);
}

t_hit			ray_hit(float3 origin, float3 ray, t_scene scene)
{
	unsigned int			i = 0;
	int			max = get_max_obj(PARAM);
	t_hit		hit;
	float		dist = 0;

	hit.dist = 0;
	hit.type = 0;
	hit.id = 0;
	hit.pos = (0, 0, 0);
	hit.normale = (0, 0, 0);
	while (i < max)
	{
		if (i < PARAM->n_cones)
			if (((dist = inter_cone(CONES[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 1;
				hit.id = i;
			}
		if (i < PARAM->n_cylinders)
			if (((dist = inter_cylinder(CYLIND[i].height, rotate_obj(CYLIND[i].dir, CYLIND[i].pitch, CYLIND[i].yaw, 0), CYLIND[i].radius, CYLIND[i].pos, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 2;
				hit.id = i;
			}
		if (i < PARAM->n_planes)
			if (((dist = inter_plan(PLANE[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 4;
				hit.id = i;
			}
		if (i < PARAM->n_spheres)
			if (((dist = inter_sphere(SPHERE[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 5;
				hit.id = i;
			}
		i++;
	}
	return (hit);
}

float3			rotate_matrix(float angle, float3 v)
{
	float3		res;

	res.x = v.x;
	res.y = (cos(angle) * v.y) - (sin(angle) * v.z);
	res.z = (sin(angle) * v.y) + (cos(angle) * v.z);
	return (res);
}

float16			trans_matrix(float3 dir, float angle)
{
	float16		res = 0;
	float3		rot = 0;

	rot = rotate_obj(dir, 0, angle, 0);
	res[0] = rot.x;
	res[1] = rot.y;
	res[2] = rot.z;
	rot = rotate_obj(dir, -angle, 0, 0);
	res[4] = rot.x;
	res[5] = rot.y;
	res[6] = rot.z;
	res[8] = dir.x;
	res[9] = dir.y;
	res[10] = dir.z;
	return (res);
}

float3			apply_matrix(float16 mat, float3 v)
{
	float3		res = 0;

	res.x = mat[0] * v.x + mat[4] * v.y + mat[8] * v.z;
	res.y = mat[1] * v.x + mat[5] * v.y + mat[9] * v.z;
	res.z = mat[2] * v.x + mat[6] * v.y + mat[10] * v.z;
	return (res);
}

float3			get_hit_normale(t_scene scene, t_hit hit)
{
	float3		res;

	if (hit.type == 1)
	{
		float k = CONES[hit.id].angle * DEG2RAD;
		k = tan(k);
		k = 1 + k * k;
		res = dot(-scene.ray, fast_normalize(CONES[hit.id].dir)) * \
			hit.dist - dot(ACTIVECAM.pos + PARAM->mvt - CONES[hit.id].pos, fast_normalize(CONES[hit.id].dir));
		res = ((hit.pos - fast_normalize(CONES[hit.id].pos)) - (k * fast_normalize(CONES[hit.id].dir) * res)) * -1;
	}
	else if (hit.type == 2)
	{
		/*float3	base = CYLIND[hit.id].pos;
		res = hit.pos;

		res = rotate_matrix(45 * DEG2RAD, res);
		base.z = res.z;
		base = rotate_matrix(-45 * DEG2RAD, base);
		res = rotate_matrix(-45 * DEG2RAD, res);
		res -= base;*/
//		res = dot(-scene.ray, fast_normalize(CYLIND[hit.id].dir) * hit.dist + \
//			dot(ACTIVECAM.pos + PARAM->mvt - CYLIND[hit.id].pos, fast_normalize(CYLIND[hit.id].dir)));
//		res = hit.pos - CYLIND[hit.id].pos - fast_normalize(CYLIND[hit.id].dir) * res;

	/*	res = fast_normalize(hit.pos - CYLIND[hit.id].pos);
	// fonctionne pour cylindre aligné en Z
		if (dot(fast_normalize(CYLIND[hit.id].dir), res) < 0)
		{
			res += fast_normalize(CYLIND[hit.id].dir);
			res.z += 1;
		}
		else
		{
			res -= fast_normalize(CYLIND[hit.id].dir);
			res.z += 1;
		}*/
		int		i = hit.id;
		float3	dir = rotate_obj(CYLIND[i].dir, CYLIND[i].pitch, CYLIND[i].yaw, 0);
		float16 ok = trans_matrix(dir, 90);
		//printf("the first\n0 : %f, 1 : %f, 2 : %f\n4 : %f, 5 : %f, 6 : %f\n8 : %f, 9 : %f, 10 : %f\n\n", ok[0], ok[1], ok[2], ok[4], ok[5], ok[6], ok[8], ok[9], ok[10]);
		res = apply_matrix(ok, hit.pos) - CYLIND[i].pos;
		res.z = 0;
		//ok = trans_matrix(dir, -90);
		//printf("the second\n0 : %f, 1 : %f, 2 : %f\n4 : %f, 5 : %f, 6 : %f\n8 : %f, 9 : %f, 10 : %f\n\n", ok[0], ok[1], ok[2], ok[4], ok[5], ok[6], ok[8], ok[9], ok[10]);
		res = apply_matrix(-ok, res);
		/*res = trans_matrix(dir, hit.pos);
		res = res - CYLIND[i].pos;
		res.z = 0;*/
		//res = trans_matrix(dir, res;
		/*
		nbase.dist = inter_cylinder(CYLIND[i].height, CYLIND[i].dir, CYLIND[i].radius, CYLIND[i].pos,  rotate_obj(scene.ray, -CYLIND[i].pitch, CYLIND[i].yaw, 0), (ACTIVECAM.pos + PARAM->mvt));
		nbase.pos = (ACTIVECAM.pos + PARAM->mvt) + fast_normalize((rotate_obj(scene.ray, -CYLIND[i].pitch, -CYLIND[i].yaw, 0)) * nbase.dist);
		res = nbase.pos - CYLIND[i].pos;
		res.z = 0;
		res = rotate_obj(fast_normalize(res), CYLIND[i].pitch, CYLIND[i].yaw, 0);*/
	}
	else if (hit.type == 4)
	{
		if (dot(PLANE[hit.id].normale, -scene.ray) < 0)
			res = -PLANE[hit.id].normale;
		else
			res = PLANE[hit.id].normale;
	}
	else if (hit.type == 5)
		res = hit.pos - SPHERE[hit.id].pos;
	return (fast_normalize(res));
}

/*
if (a == 1 && a == 2 && a == 3)
{
	printf("c est cool\n");
}*/

unsigned int			phong(t_hit hit, t_scene scene)
{
	int					i = -1;
	unsigned int		obj_color = get_obj_hue(scene, hit);
	unsigned int		ambient_color = get_ambient(obj_color, scene);
	unsigned int		res_color = ambient_color;
	float				tmp = 0;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit;

	while (++i < PARAM->n_lights)
	{
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0)
				res_color = color_diffuse(hit, scene, res_color, tmp);
			reflect = fast_normalize(mult_fvect(2.0 * dot(hit.normale, light_ray.dir), hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(hit, scene, res_color, tmp);
		}
	}
	return (res_color);
}

unsigned int			phong2(t_hit hit, t_scene scene)
{
	int					i = -1;
	unsigned int		obj_color = get_obj_hue(scene, hit);
	unsigned int		ambient_color = get_ambient(obj_color, scene);
	unsigned int		res_color = ambient_color;
	float				tmp = 0;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit;

	while (++i < PARAM->n_lights)
	{
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0)
				res_color = color_diffuse(hit, scene, res_color, tmp);
			reflect = fast_normalize(mult_fvect(2.0 * dot(hit.normale, light_ray.dir), hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(hit, scene, res_color, tmp);
		}
	}
	return (res_color);
}

unsigned int		bounce(t_scene scene, t_hit old_hit, int depth)
{
	unsigned int	color = 0;
	float3			reflex = 0;
	t_hit			new_hit;
	while (depth > 0)
	{
		reflex = fast_normalize(scene.ray - mult_fvect((2 * dot(old_hit.normale, scene.ray)), old_hit.normale));
		new_hit.dist = MAX_DIST;
		new_hit = ray_hit(old_hit.pos, reflex, scene);
		if (new_hit.dist > 0 && new_hit.dist < MAX_DIST)
		{
			new_hit.pos = mult_fvect(new_hit.dist, reflex) + old_hit.pos;
			new_hit.normale = get_hit_normale(scene, new_hit);
			new_hit.pos = new_hit.pos + ((new_hit.dist / 100) * new_hit.normale);
			color += 0.1 * phong2(new_hit, scene);
		}
		depth--;
	}
	return (color);
}
unsigned int	get_pixel_color(t_scene scene)
{
	t_hit			hit;
	int				depth = PARAM->depth;
	unsigned int	color  = 0;
	unsigned int	bounce_color = 0;

	hit.dist = MAX_DIST;
	hit = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	if (hit.dist > 0 && hit.dist < MAX_DIST) // ajout d'une distance max pour virer acnee mais pas fiable a 100%
	{
		hit.pos = mult_fvect(hit.dist, scene.ray) + (ACTIVECAM.pos + PARAM->mvt);
		hit.normale = get_hit_normale(scene, hit);
		hit.pos = hit.pos + ((hit.dist / 100) * hit.normale);
		if ((scene.pi
		color = phong(hit, scene);
//		if (depth > 0)
//			bounce_color = bounce(scene, hit, depth);
		return (color + bounce_color);
//		return (blend_add(color, 0.8*bounce_color));
	}
	return (get_ambient(BACKCOLOR, scene));
}

float3						get_ray_cam(t_cam cam, t_scene scene, int x, int y)
{
	float3					cam_ray = 0;
	float					ratio = (float)PARAM->win_w / (float)PARAM->win_h;

	cam_ray.x = ((2 * ((x + 0.5) / PARAM->win_w)) - 1) * ratio * (tan((cam.fov / 2) * DEG2RAD));
	cam_ray.y = ((1 - (2 * ((y + 0.5) / PARAM->win_h))) * tan((cam.fov / 2) * DEG2RAD));
	cam_ray.z = 1;
/*  rotation XYZ
	cam_ray.x = xx * cos(yaw) * cos(roll) + yy * cos(yaw) * -sin(roll) + sin(yaw);
	cam_ray.y = xx * (-sin(pitch) * -sin(yaw) * cos(roll) + cos(pitch) * sin(roll)) + yy * (-sin(pitch) * -sin(yaw) * -sin(roll) + cos(pitch) * cos(roll)) + cos(yaw) * -sin(pitch);
	cam_ray.z = xx * (cos(pitch) * -sin(yaw) * cos(roll) + sin(pitch) * sin(roll)) + yy * (cos(pitch) * -sin(yaw) * -sin(roll) + sin(pitch) * cos(roll)) + cos(yaw) * cos(pitch);

// rotation ZYX
	cam_ray.x = xx * cos(roll) * cos(yaw) + yy * (cos(pitch) * -sin(roll) + cos(roll) * sin(yaw) * sin(pitch)) + (-sin(roll) * -sin(pitch) + cos(roll) * sin(yaw) * cos(pitch));
	cam_ray.y = xx * sin(roll) * cos(yaw) + yy * (cos(roll) * cos(pitch) + sin(roll) * sin(yaw) * sin(pitch)) + (cos(roll) * -sin(pitch) + sin(roll) * sin(yaw) * cos(pitch));
	cam_ray.z = xx * -sin(yaw) + yy * cos(yaw) * sin(pitch) + cos(yaw) * cos(pitch);
calcul simplifié
	cam_ray.x = xx * cos(yaw) + yy * (sin(yaw) * sin(pitch)) + (sin(yaw) * cos(pitch));
	cam_ray.y = yy * cos(pitch) + -sin(pitch);
	cam_ray.z = xx * -sin(yaw) + yy * cos(yaw) * sin(pitch) + cos(yaw) * cos(pitch);
*/
	cam_ray = rotat_zyx(cam_ray, cam.pitch, cam.yaw, 0);
	return(normalize(cam_ray));
}

__kernel void	ray_trace(__global		char		*output,
						  				t_param		param,
						  __constant	t_cam		*cameras,
						  __constant	t_cone		*cones,
						  __constant	t_cylinder	*cylinders,
						  __constant	t_light		*lights,
						  __constant	t_plane		*planes,
						  __constant	t_sphere	*spheres,
						  __global		t_hit		*target_obj)
{
	t_scene		scene = grab_data(cameras, cones, cylinders, lights, planes, spheres, param);
	int			x = get_global_id(0);
	int			y = get_global_id(1);
	int			id = x + (PARAM->win_w * y); // NE PAS VIRER ID CAR BESOIN DANS MACRO OUTPUTE
	scene.ray = get_ray_cam(ACTIVECAM, scene, x ,y);
	if (x == PARAM->mou_x && y == PARAM->mou_y)
		*target_obj = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	OUTPUTE = get_pixel_color(scene);
}

#include "kernel_header.h"
#include "kernel_color.h"
#include "kernel_data.h"
#include "kernel_vector.h"
#include "kernel_debug.h"

float3						rotat_zyx(float3 vect, float pitch, float yaw, float roll)
{
	float3					res;
	float					rad_pitch = pitch * DEG2RAD;
	float					rad_yaw = yaw * DEG2RAD;
	float					rad_roll = roll * DEG2RAD;

	res.x = vect.x * cos(rad_roll) * cos(rad_yaw) + vect.y * (cos(rad_pitch) * -sin(rad_roll) + cos(rad_roll) * sin(rad_yaw) * sin(rad_pitch)) + vect.z * (-sin(rad_roll) * -sin(rad_pitch) + cos(rad_roll) * sin(rad_yaw) * cos(rad_pitch));
	res.y = vect.x * sin(rad_roll) * cos(rad_yaw) + vect.y * (cos(rad_roll) * cos(rad_pitch) + sin(rad_roll) * sin(rad_yaw) * sin(rad_pitch)) + vect.z * (cos(rad_roll) * -sin(rad_pitch) + sin(rad_roll) * sin(rad_yaw) * cos(rad_pitch));
	res.z = vect.x * -sin(rad_yaw) + vect.y * cos(rad_yaw) * sin(rad_pitch) + vect.z * cos(rad_yaw) * cos(rad_pitch);
	return (res);
}

float3						rotat_xyz(float3 vect, float pitch, float yaw, float roll)
{
	float3					res;
	float					rad_pitch = pitch * DEG2RAD;
	float					rad_yaw = yaw * DEG2RAD;
	float					rad_roll = roll * DEG2RAD;

	res.x = vect.x * cos(rad_yaw) * cos(rad_roll) + vect.y * cos(rad_yaw) * -sin(rad_roll) + vect.z * sin(rad_yaw);
	res.y = vect.x * (-sin(rad_pitch) * -sin(rad_yaw) * cos(rad_roll) + cos(rad_pitch) * sin(rad_roll)) + vect.y * (-sin(rad_pitch) * -sin(rad_yaw) * -sin(rad_roll) + cos(rad_pitch) * cos(rad_roll)) + vect.z * cos(rad_yaw) * -sin(rad_pitch);
	res.z = vect.x * (cos(rad_pitch) * -sin(rad_yaw) * cos(rad_roll) + sin(rad_pitch) * sin(rad_roll)) + vect.y * (cos(rad_pitch) * -sin(rad_yaw) * -sin(rad_roll) + sin(rad_pitch) * cos(rad_roll)) + vect.z * cos(rad_yaw) * cos(rad_pitch);
	return (res);
}

float3					rotate_obj(float3 v, float pitch, float yaw, float roll)
{
	float3				res;

	res = rotat_zyx(v, pitch, yaw, roll);

	return (fast_normalize(res));
}

float3					get_sphere_abc(float radius, float3 ray, float3 origin)
{
	float3		abc;

	abc.x = dot(ray, ray);
	abc.y = 2 * dot(ray, origin);
	abc.z = dot(origin, origin) - (radius * radius);
	return (abc);
}

float					inter_sphere(t_sphere sphere, float3 ray, float3 origin)
{
	float3				abc;
	float				d;
	float				res1;
	float				res2;

	origin -= sphere.pos;
	abc = get_sphere_abc(sphere.radius, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		return ((-abc[1]) / (2 * abc[0]));
	res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
	res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
		return (res1);
	return (res2);
}

float3					get_cylinder_abc(float radius, float3 dir, float3 ray, float3 origin)
{
	float3		abc;

	// SEMBLE OK
	abc.x = dot(ray, ray) - (dot(ray, dir) * dot(ray, dir));
	abc.y = 2 * (dot(ray, origin) - (dot(ray, dir) * dot(origin, dir)));
	abc.z = dot(origin, origin) - (dot(origin, dir) * dot(origin, dir)) - (radius * radius);
	return (abc);
}

float					inter_cylinder(float height, float3 dir, float radius, float3 pos, float3 ray, float3 origin)
{
	float3				abc;
	//float3				dir = rotate_obj(cyl.dir, cyl.pitch, cyl.yaw, 0);
	float				d;
	float				res1 = 0;
	float				res2 = 0;
	float				m;

	origin -= pos;
	abc = get_cylinder_abc(radius, dir, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		res1 = (-abc[1]) / (2 * abc[0]);
	else
	{
		res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
		res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	}
	if (res1 < 0 && res2 < 0)
		return (0);
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
	{
		if (height == 0 || (dot(ray, dir) * res1 +
			dot(origin, dir) < height && dot(ray, dir) * res1 +
			dot(origin, dir) > 0))
			return (res1);
	}
	if (height ==  0 || (dot(ray, dir) * res2 +
			dot(origin, dir) < height && dot(ray, dir) * res2 +
			dot(origin, dir) > 0))
		return (res2);
	else
		return (0);
}

float3					get_cone_abc(t_cone cone, float3 ray, float3 origin)
{
	float3		abc = 0;
	float		k = cone.angle * DEG2RAD;
	k = tan(k);
	k = 1 + k * k;

	abc.x = dot(ray, ray) - (k * (dot(ray, cone.dir) * dot(ray, cone.dir)));
	abc.y = 2 * (dot(ray, origin) - (k * \
			(dot(ray, cone.dir) * dot(origin, cone.dir))));
	abc.z = (dot(origin, origin) - \
			(k * (dot(origin, cone.dir) * dot(origin, cone.dir))));
	return (abc);
}

float					inter_cone(t_cone cone, float3 ray, float3 origin)
{
	float3				abc;
	float				d;
	float				res1;
	float				res2;
	float				res;

	origin -= cone.pos;
	abc = get_cone_abc(cone, ray, origin);
	d = (abc.y * abc.y) - (4 * (abc.x * abc.z));
	if (d < 0)
		return (0);
	if (d == 0)
		res = (-abc[1]) / (2 * abc[0]);
	res1 = (((-abc[1]) + sqrt(d)) / (2 * abc[0]));
	res2 = (((-abc[1]) - sqrt(d)) / (2 * abc[0]));
	if ((res1 < res2 && res1 > 0) || (res1 > res2 && res2 < 0))
		res = res1;
	else
		res = res2;
	return (res);
}

float					inter_plan(t_plane plane, float3 ray, float3 origin)
{
	float				t;

	if ((t = dot(fast_normalize(ray), fast_normalize(plane.normale))) == 0)
		return (0);
	t = (dot(plane.pos - origin, fast_normalize(plane.normale))) / t;
		if (t < 0.001)
		return (0);
	return (t);
}

t_hit			ray_hit(float3 origin, float3 ray, t_scene scene)
{
	unsigned int			i = 0;
	int			max = get_max_obj(PARAM);
	t_hit		hit;
	float		dist = 0;

	hit.dist = 0;
	hit.type = 0;
	hit.id = 0;
	hit.pos = (0, 0, 0);
	hit.normale = (0, 0, 0);
	while (i < max)
	{
		if (i < PARAM->n_cones)
			if (((dist = inter_cone(CONES[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 1;
				hit.id = i;
			}
		if (i < PARAM->n_cylinders)
			if (((dist = inter_cylinder(CYLIND[i].height, rotate_obj(CYLIND[i].dir, CYLIND[i].pitch, CYLIND[i].yaw, 0), CYLIND[i].radius, CYLIND[i].pos, ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 2;
				hit.id = i;
			}
		if (i < PARAM->n_planes)
			if (((dist = inter_plan(PLANE[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 4;
				hit.id = i;
			}
		if (i < PARAM->n_spheres)
			if (((dist = inter_sphere(SPHERE[i], ray, origin)) < hit.dist || hit.dist == 0) && dist > 0)
			{
				hit.dist = dist;
				hit.type = 5;
				hit.id = i;
			}
		i++;
	}
	return (hit);
}

float3			rotate_matrix(float angle, float3 v)
{
	float3		res;

	res.x = v.x;
	res.y = (cos(angle) * v.y) - (sin(angle) * v.z);
	res.z = (sin(angle) * v.y) + (cos(angle) * v.z);
	return (res);
}

float16			trans_matrix(float3 dir, float angle)
{
	float16		res = 0;
	float3		rot = 0;

	rot = rotate_obj(dir, 0, angle, 0);
	res[0] = rot.x;
	res[1] = rot.y;
	res[2] = rot.z;
	rot = rotate_obj(dir, -angle, 0, 0);
	res[4] = rot.x;
	res[5] = rot.y;
	res[6] = rot.z;
	res[8] = dir.x;
	res[9] = dir.y;
	res[10] = dir.z;
	return (res);
}

float3			apply_matrix(float16 mat, float3 v)
{
	float3		res = 0;

	res.x = mat[0] * v.x + mat[4] * v.y + mat[8] * v.z;
	res.y = mat[1] * v.x + mat[5] * v.y + mat[9] * v.z;
	res.z = mat[2] * v.x + mat[6] * v.y + mat[10] * v.z;
	return (res);
}

float3			get_hit_normale(t_scene scene, t_hit hit)
{
	float3		res;

	if (hit.type == 1)
	{
		float k = CONES[hit.id].angle * DEG2RAD;
		k = tan(k);
		k = 1 + k * k;
		res = dot(-scene.ray, fast_normalize(CONES[hit.id].dir)) * \
			hit.dist - dot(ACTIVECAM.pos + PARAM->mvt - CONES[hit.id].pos, fast_normalize(CONES[hit.id].dir));
		res = ((hit.pos - fast_normalize(CONES[hit.id].pos)) - (k * fast_normalize(CONES[hit.id].dir) * res)) * -1;
	}
	else if (hit.type == 2)
	{
		/*float3	base = CYLIND[hit.id].pos;
		res = hit.pos;

		res = rotate_matrix(45 * DEG2RAD, res);
		base.z = res.z;
		base = rotate_matrix(-45 * DEG2RAD, base);
		res = rotate_matrix(-45 * DEG2RAD, res);
		res -= base;*/
//		res = dot(-scene.ray, fast_normalize(CYLIND[hit.id].dir) * hit.dist + \
//			dot(ACTIVECAM.pos + PARAM->mvt - CYLIND[hit.id].pos, fast_normalize(CYLIND[hit.id].dir)));
//		res = hit.pos - CYLIND[hit.id].pos - fast_normalize(CYLIND[hit.id].dir) * res;

	/*	res = fast_normalize(hit.pos - CYLIND[hit.id].pos);
	// fonctionne pour cylindre aligné en Z
		if (dot(fast_normalize(CYLIND[hit.id].dir), res) < 0)
		{
			res += fast_normalize(CYLIND[hit.id].dir);
			res.z += 1;
		}
		else
		{
			res -= fast_normalize(CYLIND[hit.id].dir);
			res.z += 1;
		}*/
		int		i = hit.id;
		float3	dir = rotate_obj(CYLIND[i].dir, CYLIND[i].pitch, CYLIND[i].yaw, 0);
		float16 ok = trans_matrix(dir, 90);
		//printf("the first\n0 : %f, 1 : %f, 2 : %f\n4 : %f, 5 : %f, 6 : %f\n8 : %f, 9 : %f, 10 : %f\n\n", ok[0], ok[1], ok[2], ok[4], ok[5], ok[6], ok[8], ok[9], ok[10]);
		res = apply_matrix(ok, hit.pos) - CYLIND[i].pos;
		res.z = 0;
		//ok = trans_matrix(dir, -90);
		//printf("the second\n0 : %f, 1 : %f, 2 : %f\n4 : %f, 5 : %f, 6 : %f\n8 : %f, 9 : %f, 10 : %f\n\n", ok[0], ok[1], ok[2], ok[4], ok[5], ok[6], ok[8], ok[9], ok[10]);
		res = apply_matrix(-ok, res);
		/*res = trans_matrix(dir, hit.pos);
		res = res - CYLIND[i].pos;
		res.z = 0;*/
		//res = trans_matrix(dir, res;
		/*
		nbase.dist = inter_cylinder(CYLIND[i].height, CYLIND[i].dir, CYLIND[i].radius, CYLIND[i].pos,  rotate_obj(scene.ray, -CYLIND[i].pitch, CYLIND[i].yaw, 0), (ACTIVECAM.pos + PARAM->mvt));
		nbase.pos = (ACTIVECAM.pos + PARAM->mvt) + fast_normalize((rotate_obj(scene.ray, -CYLIND[i].pitch, -CYLIND[i].yaw, 0)) * nbase.dist);
		res = nbase.pos - CYLIND[i].pos;
		res.z = 0;
		res = rotate_obj(fast_normalize(res), CYLIND[i].pitch, CYLIND[i].yaw, 0);*/
	}
	else if (hit.type == 4)
	{
		if (dot(PLANE[hit.id].normale, -scene.ray) < 0)
			res = -PLANE[hit.id].normale;
		else
			res = PLANE[hit.id].normale;
	}
	else if (hit.type == 5)
		res = hit.pos - SPHERE[hit.id].pos;
	return (fast_normalize(res));
}

/*
if (a == 1 && a == 2 && a == 3)
{
	printf("c est cool\n");
}*/

unsigned int			phong(t_hit hit, t_scene scene)
{
	int					i = -1;
	unsigned int		obj_color = get_obj_hue(scene, hit);
	unsigned int		ambient_color = get_ambient(obj_color, scene);
	unsigned int		res_color = ambient_color;
	float				tmp = 0;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit;

	while (++i < PARAM->n_lights)
	{
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0)
				res_color = color_diffuse(hit, scene, res_color, tmp);
			reflect = fast_normalize(mult_fvect(2.0 * dot(hit.normale, light_ray.dir), hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(hit, scene, res_color, tmp);
		}
	}
	return (res_color);
}

unsigned int			phong2(t_hit hit, t_scene scene)
{
	int					i = -1;
	unsigned int		obj_color = get_obj_hue(scene, hit);
	unsigned int		ambient_color = get_ambient(obj_color, scene);
	unsigned int		res_color = ambient_color;
	float				tmp = 0;
	float3				reflect = 0;

	t_light_ray			light_ray;
	t_hit				light_hit;

	while (++i < PARAM->n_lights)
	{
		light_ray.dir = LIGHT[i].pos - hit.pos;
		light_ray.dist = fast_length(light_ray.dir);
		light_ray.dir = fast_normalize(light_ray.dir);
		light_hit = ray_hit(hit.pos, light_ray.dir, scene);
		if (light_hit.dist < light_ray.dist && light_hit.dist > 0)
		;
		else
		{
			tmp = dot(hit.normale, light_ray.dir);
			if (tmp > 0)
				res_color = color_diffuse(hit, scene, res_color, tmp);
			reflect = fast_normalize(mult_fvect(2.0 * dot(hit.normale, light_ray.dir), hit.normale) - light_ray.dir);
			tmp = dot(reflect, -scene.ray);
			if (tmp > 0)
				res_color = color_specular(hit, scene, res_color, tmp);
		}
	}
	return (res_color);
}

unsigned int		bounce(t_scene scene, t_hit old_hit, int depth)
{
	unsigned int	color = 0;
	float3			reflex = 0;
	t_hit			new_hit;
	while (depth > 0)
	{
//		printf("IM REFLECTING!\n");
		reflex = fast_normalize(scene.ray - mult_fvect((2 * dot(old_hit.normale, scene.ray)), old_hit.normale));
		new_hit.dist = MAX_DIST;
		new_hit = ray_hit(old_hit.pos, reflex, scene);
		if (new_hit.dist > 0 && new_hit.dist < MAX_DIST)
		{
			new_hit.pos = mult_fvect(new_hit.dist, reflex) + old_hit.pos;
			new_hit.normale = get_hit_normale(scene, new_hit);
			new_hit.pos = new_hit.pos + ((new_hit.dist / 100) * new_hit.normale);
			color += 0.1 * phong2(new_hit, scene);
		}
		depth--;
	}
	return (color);
}
unsigned int	get_pixel_color(t_scene scene)
{
	t_hit			hit;
	int				depth = PARAM->depth;
	unsigned int	color  = 0;
	unsigned int	bounce_color = 0;

	hit.dist = MAX_DIST;
	hit = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	if (hit.dist > 0 && hit.dist < MAX_DIST) // ajout d'une distance max pour virer acnee mais pas fiable a 100%
	{
		hit.pos = mult_fvect(hit.dist, scene.ray) + (ACTIVECAM.pos + PARAM->mvt);
		hit.normale = get_hit_normale(scene, hit);
		hit.pos = hit.pos + ((hit.dist / 100) * hit.normale);
		color = phong(hit, scene);
		if (depth > 0)
			bounce_color = bounce(scene, hit, depth);
//		return (color + bounce_color);
		return (blend_add(color, 0.8*bounce_color));
	}
	return (get_ambient(BACKCOLOR, scene));
}

float3						get_ray_cam(t_cam cam, t_scene scene, int x, int y)
{
	float3					cam_ray = 0;
	float					ratio = (float)PARAM->win_w / (float)PARAM->win_h;

	cam_ray.x = ((2 * ((x + 0.5) / PARAM->win_w)) - 1) * ratio * (tan((cam.fov / 2) * DEG2RAD));
	cam_ray.y = ((1 - (2 * ((y + 0.5) / PARAM->win_h))) * tan((cam.fov / 2) * DEG2RAD));
	cam_ray.z = 1;
/*  rotation XYZ
	cam_ray.x = xx * cos(yaw) * cos(roll) + yy * cos(yaw) * -sin(roll) + sin(yaw);
	cam_ray.y = xx * (-sin(pitch) * -sin(yaw) * cos(roll) + cos(pitch) * sin(roll)) + yy * (-sin(pitch) * -sin(yaw) * -sin(roll) + cos(pitch) * cos(roll)) + cos(yaw) * -sin(pitch);
	cam_ray.z = xx * (cos(pitch) * -sin(yaw) * cos(roll) + sin(pitch) * sin(roll)) + yy * (cos(pitch) * -sin(yaw) * -sin(roll) + sin(pitch) * cos(roll)) + cos(yaw) * cos(pitch);

// rotation ZYX
	cam_ray.x = xx * cos(roll) * cos(yaw) + yy * (cos(pitch) * -sin(roll) + cos(roll) * sin(yaw) * sin(pitch)) + (-sin(roll) * -sin(pitch) + cos(roll) * sin(yaw) * cos(pitch));
	cam_ray.y = xx * sin(roll) * cos(yaw) + yy * (cos(roll) * cos(pitch) + sin(roll) * sin(yaw) * sin(pitch)) + (cos(roll) * -sin(pitch) + sin(roll) * sin(yaw) * cos(pitch));
	cam_ray.z = xx * -sin(yaw) + yy * cos(yaw) * sin(pitch) + cos(yaw) * cos(pitch);
calcul simplifié
	cam_ray.x = xx * cos(yaw) + yy * (sin(yaw) * sin(pitch)) + (sin(yaw) * cos(pitch));
	cam_ray.y = yy * cos(pitch) + -sin(pitch);
	cam_ray.z = xx * -sin(yaw) + yy * cos(yaw) * sin(pitch) + cos(yaw) * cos(pitch);
*/
	cam_ray = rotat_zyx(cam_ray, cam.pitch, cam.yaw, 0);
	return(normalize(cam_ray));
}

__kernel void	ray_trace(__global		char		*output,
						  				t_param		param,
						  __constant	t_cam		*cameras,
						  __constant	t_cone		*cones,
						  __constant	t_cylinder	*cylinders,
						  __constant	t_light		*lights,
						  __constant	t_plane		*planes,
						  __constant	t_sphere	*spheres,
						  __global		t_hit		*target_obj)
{
	t_scene		scene = grab_data(cameras, cones, cylinders, lights, planes, spheres, param);
	int			x = get_global_id(0);
	int			y = get_global_id(1);
	int			id = x + (PARAM->win_w * y); // NE PAS VIRER ID CAR BESOIN DANS MACRO OUTPUTE
	scene.ray = get_ray_cam(ACTIVECAM, scene, x ,y);
	if (x == PARAM->mou_x && y == PARAM->mou_y)
		*target_obj = ray_hit((ACTIVECAM.pos + PARAM->mvt), scene.ray, scene);
	OUTPUTE = get_pixel_color(scene);
}


Delete spmv_csr_kernel.cl

Delete spmv_csr_kernel.cl

/*
 */

void __kernel csr(const unsigned int num_rows,
                       __global unsigned int * Ap,
                       __global unsigned int * Aj,
                       __global float * Ax,
                       __global float * x,
                       __global float * y)
{
   unsigned int row = get_global_id(0);

    if(row < num_rows){
        float sum = y[row];

        const unsigned int row_start = Ap[row];
        const unsigned int row_end   = Ap[row+1];

        unsigned int jj = 0;
        for (jj = row_start; jj < row_end; jj++){
            sum += Ax[jj] * x[Aj[jj]];
        }
        y[row] = sum;
    }

}