/unmaintained/adsoda/adsoda.factor

http://github.com/abeaumont/factor · Factor · 569 lines · 434 code · 95 blank · 40 comment · 54 complexity · 451b635145409c285bdfa6bd2f2bc991 MD5 · raw file

  1. ! Copyright (C) 2008 Jeff Bigot
  2. ! See http://factorcode.org/license.txt for BSD license.
  3. USING: accessors
  4. arrays
  5. assocs
  6. combinators
  7. kernel
  8. fry
  9. math
  10. math.constants
  11. math.functions
  12. math.libm
  13. math.order
  14. math.vectors
  15. math.matrices
  16. math.parser
  17. namespaces
  18. prettyprint
  19. sequences
  20. sequences.deep
  21. sets
  22. slots
  23. sorting
  24. tools.time
  25. vars
  26. continuations
  27. words
  28. opengl
  29. opengl.gl
  30. colors
  31. adsoda.solution2
  32. adsoda.combinators
  33. opengl.demo-support
  34. values
  35. tools.walker
  36. ;
  37. IN: adsoda
  38. DEFER: combinations
  39. VAR: pv
  40. ! -------------------------------------------------------------
  41. ! global values
  42. VALUE: remove-hidden-solids?
  43. VALUE: VERY-SMALL-NUM
  44. VALUE: ZERO-VALUE
  45. VALUE: MAX-FACE-PER-CORNER
  46. t \ remove-hidden-solids? set-value
  47. 0.0000001 \ VERY-SMALL-NUM set-value
  48. 0.0000001 \ ZERO-VALUE set-value
  49. 4 \ MAX-FACE-PER-CORNER set-value
  50. ! -------------------------------------------------------------
  51. ! sequence complement
  52. : with-pv ( i quot -- ) [ swap >pv call ] with-scope ; inline
  53. : dimension ( array -- x ) length 1 - ; inline
  54. : change-last ( seq quot -- )
  55. [ [ dimension ] keep ] dip change-nth ; inline
  56. ! -------------------------------------------------------------
  57. ! light
  58. ! -------------------------------------------------------------
  59. TUPLE: light name { direction array } color ;
  60. : <light> ( -- tuple ) light new ;
  61. ! -------------------------------------------------------------
  62. ! halfspace manipulation
  63. ! -------------------------------------------------------------
  64. : constant+ ( v x -- w ) '[ [ _ + ] change-last ] keep ;
  65. : translate ( u v -- w ) dupd v* sum constant+ ;
  66. : transform ( u matrix -- w )
  67. [ swap m.v ] 2keep ! compute new normal vector
  68. [
  69. [ [ abs ZERO-VALUE > ] find ] keep
  70. ! find a point on the frontier
  71. ! be sure it's not null vector
  72. last ! get constant
  73. swap /f neg swap ! intercept value
  74. ] dip
  75. flip
  76. nth
  77. [ * ] with map ! apply intercep value
  78. over v*
  79. sum neg
  80. suffix ! add value as constant at the end of equation
  81. ;
  82. : position-point ( halfspace v -- x )
  83. -1 suffix v* sum ; inline
  84. : point-inside-halfspace? ( halfspace v -- ? )
  85. position-point VERY-SMALL-NUM > ;
  86. : point-inside-or-on-halfspace? ( halfspace v -- ? )
  87. position-point VERY-SMALL-NUM neg > ;
  88. : project-vector ( seq -- seq )
  89. pv> [ head ] [ 1 + tail ] 2bi append ;
  90. : get-intersection ( matrice -- seq )
  91. [ 1 tail* ] map flip first ;
  92. : islenght=? ( seq n -- seq n ? ) 2dup [ length ] [ = ] bi* ;
  93. : compare-nleft-to-identity-matrix ( seq n -- ? )
  94. [ [ head ] curry map ] keep identity-matrix m-
  95. flatten
  96. [ abs ZERO-VALUE < ] all?
  97. ;
  98. : valid-solution? ( matrice n -- ? )
  99. islenght=?
  100. [ compare-nleft-to-identity-matrix ]
  101. [ 2drop f ] if ; inline
  102. : intersect-hyperplanes ( matrice -- seq )
  103. [ solution dup ] [ first dimension ] bi
  104. valid-solution? [ get-intersection ] [ drop f ] if ;
  105. ! -------------------------------------------------------------
  106. ! faces
  107. ! -------------------------------------------------------------
  108. TUPLE: face { halfspace array }
  109. touching-corners adjacent-faces ;
  110. : <face> ( v -- tuple ) face new swap >>halfspace ;
  111. : flip-face ( face -- face ) [ vneg ] change-halfspace ;
  112. : erase-face-touching-corners ( face -- face )
  113. f >>touching-corners ;
  114. : erase-face-adjacent-faces ( face -- face )
  115. f >>adjacent-faces ;
  116. : faces-intersection ( faces -- v )
  117. [ halfspace>> ] map intersect-hyperplanes ;
  118. : face-translate ( face v -- face )
  119. [ translate ] curry change-halfspace ; inline
  120. : face-transform ( face m -- face )
  121. [ transform ] curry change-halfspace ; inline
  122. : face-orientation ( face -- x ) pv> swap halfspace>> nth sgn ;
  123. : backface? ( face -- face ? ) dup face-orientation 0 <= ;
  124. : pv-factor ( face -- f face )
  125. halfspace>> [ pv> swap nth [ * ] curry ] keep ; inline
  126. : suffix-touching-corner ( face corner -- face )
  127. [ suffix ] curry change-touching-corners ; inline
  128. : real-face? ( face -- ? )
  129. [ touching-corners>> length ]
  130. [ halfspace>> dimension ] bi >= ;
  131. : (add-to-adjacent-faces) ( face face -- face )
  132. over adjacent-faces>> 2dup member?
  133. [ 2drop ] [ swap suffix >>adjacent-faces ] if ;
  134. : add-to-adjacent-faces ( face face -- face )
  135. 2dup = [ drop ] [ (add-to-adjacent-faces) ] if ;
  136. : update-adjacent-faces ( faces corner -- )
  137. '[ [ _ suffix-touching-corner drop ] each ] keep
  138. 2 among [
  139. [ first ] keep second
  140. [ add-to-adjacent-faces drop ] 2keep
  141. swap add-to-adjacent-faces drop
  142. ] each ; inline
  143. : face-project-dim ( face -- x ) halfspace>> length 2 - ;
  144. : apply-light ( color light normal -- u )
  145. over direction>> v.
  146. neg dup 0 >
  147. [
  148. [ color>> swap ] dip
  149. [ * ] curry map v+
  150. [ 1 min ] map
  151. ]
  152. [ 2drop ]
  153. if
  154. ;
  155. : enlight-projection ( array face -- color )
  156. ! array = lights + ambient color
  157. [ [ third ] [ second ] [ first ] tri ]
  158. [ halfspace>> project-vector normalize ] bi*
  159. [ apply-light ] curry each
  160. v*
  161. ;
  162. : (intersection-into-face) ( face-init face-adja quot -- face )
  163. [
  164. [ [ pv-factor ] bi@
  165. roll
  166. [ map ] 2bi@
  167. v-
  168. ] 2keep
  169. [ touching-corners>> ] bi@
  170. [ swap [ = ] curry find nip f = ] curry find nip
  171. ] dip over
  172. [
  173. call
  174. dupd
  175. point-inside-halfspace? [ vneg ] unless
  176. <face>
  177. ] [ 3drop f ] if
  178. ; inline
  179. : intersection-into-face ( face-init face-adja -- face )
  180. [ [ project-vector ] bi@ ] (intersection-into-face) ;
  181. : intersection-into-silhouette-face ( face-init face-adja -- face )
  182. [ ] (intersection-into-face) ;
  183. : intersections-into-faces ( face -- faces )
  184. clone dup
  185. adjacent-faces>> [ intersection-into-face ] with map
  186. [ ] filter ;
  187. : (face-silhouette) ( face -- faces )
  188. clone dup adjacent-faces>>
  189. [ backface?
  190. [ intersection-into-silhouette-face ] [ 2drop f ] if
  191. ] with map
  192. [ ] filter
  193. ; inline
  194. : face-silhouette ( face -- faces )
  195. backface? [ drop f ] [ (face-silhouette) ] if ;
  196. ! --------------------------------
  197. ! solid
  198. ! -------------------------------------------------------------
  199. TUPLE: solid dimension silhouettes
  200. faces corners adjacencies-valid color name ;
  201. : <solid> ( -- tuple ) solid new ;
  202. : suffix-silhouettes ( solid silhouette -- solid )
  203. [ suffix ] curry change-silhouettes ;
  204. : suffix-face ( solid face -- solid )
  205. [ suffix ] curry change-faces ;
  206. : suffix-corner ( solid corner -- solid )
  207. [ suffix ] curry change-corners ;
  208. : erase-solid-corners ( solid -- solid ) f >>corners ;
  209. : erase-silhouettes ( solid -- solid )
  210. dup dimension>> f <array> >>silhouettes ;
  211. : filter-real-faces ( solid -- solid )
  212. [ [ real-face? ] filter ] change-faces ;
  213. : initiate-solid-from-face ( face -- solid )
  214. face-project-dim <solid> swap >>dimension ;
  215. : erase-old-adjacencies ( solid -- solid )
  216. erase-solid-corners
  217. [ dup [ erase-face-touching-corners
  218. erase-face-adjacent-faces drop ] each ]
  219. change-faces ;
  220. : point-inside-or-on-face? ( face v -- ? )
  221. [ halfspace>> ] dip point-inside-or-on-halfspace? ;
  222. : point-inside-face? ( face v -- ? )
  223. [ halfspace>> ] dip point-inside-halfspace? ;
  224. : point-inside-solid? ( solid point -- ? )
  225. [ faces>> ] dip [ point-inside-face? ] curry all? ; inline
  226. : point-inside-or-on-solid? ( solid point -- ? )
  227. [ faces>> ] dip
  228. [ point-inside-or-on-face? ] curry all? ; inline
  229. : unvalid-adjacencies ( solid -- solid )
  230. erase-old-adjacencies f >>adjacencies-valid
  231. erase-silhouettes ;
  232. : add-face ( solid face -- solid )
  233. suffix-face unvalid-adjacencies ;
  234. : cut-solid ( solid halfspace -- solid ) <face> add-face ;
  235. : slice-solid ( solid face -- solid1 solid2 )
  236. [ [ clone ] bi@ flip-face add-face
  237. [ "/outer/" append ] change-name ] 2keep
  238. add-face [ "/inner/" append ] change-name ;
  239. ! -------------
  240. : add-silhouette ( solid -- solid )
  241. dup
  242. ! find-adjacencies
  243. faces>> { }
  244. [ face-silhouette append ] reduce
  245. [ ] filter
  246. <solid>
  247. swap >>faces
  248. over dimension>> >>dimension
  249. over name>> " silhouette " append
  250. pv> number>string append
  251. >>name
  252. ! ensure-adjacencies
  253. suffix-silhouettes ; inline
  254. : find-silhouettes ( solid -- solid )
  255. { } >>silhouettes
  256. dup dimension>> [ [ add-silhouette ] with-pv ] each ;
  257. : ensure-silhouettes ( solid -- solid )
  258. dup silhouettes>> [ f = ] all?
  259. [ find-silhouettes ] when ;
  260. ! ------------
  261. : corner-added? ( solid corner -- ? )
  262. ! add corner to solid if it is inside solid
  263. [ ]
  264. [ point-inside-or-on-solid? ]
  265. [ swap corners>> member? not ]
  266. 2tri and
  267. [ suffix-corner drop t ] [ 2drop f ] if ;
  268. : process-corner ( solid faces corner -- )
  269. swapd
  270. [ corner-added? ] keep swap ! test if corner is inside solid
  271. [ update-adjacent-faces ]
  272. [ 2drop ]
  273. if ;
  274. : compute-intersection ( solid faces -- )
  275. dup faces-intersection
  276. dup f = [ 3drop ] [ process-corner ] if ;
  277. : test-faces-combinaisons ( solid n -- )
  278. [ dup faces>> ] dip among
  279. [ compute-intersection ] with each ;
  280. : compute-adjacencies ( solid -- solid )
  281. dup dimension>> [ >= ] curry
  282. [ keep swap ] curry MAX-FACE-PER-CORNER swap
  283. [ [ test-faces-combinaisons ] 2keep 1 - ] while drop ;
  284. : find-adjacencies ( solid -- solid )
  285. erase-old-adjacencies
  286. compute-adjacencies
  287. filter-real-faces
  288. t >>adjacencies-valid ;
  289. : ensure-adjacencies ( solid -- solid )
  290. dup adjacencies-valid>>
  291. [ find-adjacencies ] unless
  292. ensure-silhouettes
  293. ;
  294. : (non-empty-solid?) ( solid -- ? )
  295. [ dimension>> ] [ corners>> length ] bi < ;
  296. : non-empty-solid? ( solid -- ? )
  297. ensure-adjacencies (non-empty-solid?) ;
  298. : compare-corners-roughly ( corner corner -- ? )
  299. 2drop t ;
  300. ! : remove-inner-faces ( -- ) ;
  301. : face-project ( array face -- seq )
  302. backface?
  303. [ 2drop f ]
  304. [ [ enlight-projection ]
  305. [ initiate-solid-from-face ]
  306. [ intersections-into-faces ] tri
  307. >>faces
  308. swap >>color
  309. ] if ;
  310. : solid-project ( lights ambient solid -- solids )
  311. ensure-adjacencies
  312. [ color>> ] [ faces>> ] bi [ 3array ] dip
  313. [ face-project ] with map
  314. [ ] filter
  315. [ ensure-adjacencies ] map
  316. ;
  317. : (solid-move) ( solid v move -- solid )
  318. curry [ map ] curry
  319. [ dup faces>> ] dip call drop
  320. unvalid-adjacencies ; inline
  321. : solid-translate ( solid v -- solid )
  322. [ face-translate ] (solid-move) ;
  323. : solid-transform ( solid m -- solid )
  324. [ face-transform ] (solid-move) ;
  325. : find-corner-in-silhouette ( s1 s2 -- elt bool )
  326. pv> swap silhouettes>> nth
  327. swap corners>>
  328. [ point-inside-solid? ] with find swap ;
  329. : valid-face-for-order ( solid point -- face )
  330. [ point-inside-face? not ]
  331. [ drop face-orientation 0 = not ] 2bi and ;
  332. : check-orientation ( s1 s2 pt -- int )
  333. [ nip faces>> ] dip
  334. [ valid-face-for-order ] curry find swap
  335. [ face-orientation ] [ drop f ] if ;
  336. : (order-solid) ( s1 s2 -- int )
  337. 2dup find-corner-in-silhouette
  338. [ check-orientation ] [ 3drop f ] if ;
  339. : order-solid ( solid solid -- i )
  340. 2dup (order-solid)
  341. [ 2nip ]
  342. [ swap (order-solid)
  343. [ neg ] [ f ] if*
  344. ] if* ;
  345. : subtract ( solid1 solid2 -- solids )
  346. faces>> swap clone ensure-adjacencies ensure-silhouettes
  347. [ swap slice-solid drop ] curry map
  348. [ non-empty-solid? ] filter
  349. [ ensure-adjacencies ] map
  350. ; inline
  351. ! -------------------------------------------------------------
  352. ! space
  353. ! -------------------------------------------------------------
  354. TUPLE: space name dimension solids ambient-color lights ;
  355. : <space> ( -- space ) space new ;
  356. : suffix-solids ( space solid -- space )
  357. [ suffix ] curry change-solids ; inline
  358. : suffix-lights ( space light -- space )
  359. [ suffix ] curry change-lights ; inline
  360. : clear-space-solids ( space -- space ) f >>solids ;
  361. : space-ensure-solids ( space -- space )
  362. [ [ ensure-adjacencies ] map ] change-solids ;
  363. : eliminate-empty-solids ( space -- space )
  364. [ [ non-empty-solid? ] filter ] change-solids ;
  365. : projected-space ( space solids -- space )
  366. swap dimension>> 1 - <space>
  367. swap >>dimension swap >>solids ;
  368. : get-silhouette ( solid -- silhouette )
  369. silhouettes>> pv> swap nth ;
  370. : solid= ( solid solid -- ? ) [ corners>> ] same? ;
  371. : space-apply ( space m quot -- space )
  372. curry [ map ] curry [ dup solids>> ] dip
  373. [ call ] [ 2drop ] recover drop ; inline
  374. : space-transform ( space m -- space )
  375. [ solid-transform ] space-apply ;
  376. : space-translate ( space v -- space )
  377. [ solid-translate ] space-apply ;
  378. : describe-space ( space -- )
  379. solids>>
  380. [ [ corners>> [ pprint ] each ] [ name>> . ] bi ] each ;
  381. : clip-solid ( solid solid -- solids )
  382. [ ]
  383. [ solid= not ]
  384. [ order-solid -1 = ] 2tri
  385. and
  386. [ get-silhouette subtract ]
  387. [ drop 1array ]
  388. if
  389. ;
  390. : (solids-silhouette-subtract) ( solids solid -- solids )
  391. [ clip-solid append ] curry { } -rot each ; inline
  392. : solids-silhouette-subtract ( solids i solid -- solids )
  393. ! solids is an array of 1 solid arrays
  394. [ (solids-silhouette-subtract) ] curry map-but
  395. ; inline
  396. : remove-hidden-solids ( space -- space )
  397. ! We must include each solid in a sequence because
  398. ! during substration
  399. ! a solid can be divided in more than on solid
  400. [
  401. [ [ 1array ] map ]
  402. [ length ]
  403. [ ]
  404. tri
  405. [ solids-silhouette-subtract ] 2each
  406. { } [ append ] reduce
  407. ] change-solids
  408. eliminate-empty-solids ! TODO include into change-solids
  409. ;
  410. : space-project ( space i -- space )
  411. [
  412. [ clone
  413. remove-hidden-solids? [ remove-hidden-solids ] when
  414. dup
  415. [ solids>> ]
  416. [ lights>> ]
  417. [ ambient-color>> ] tri
  418. [ rot solid-project ] 2curry
  419. map
  420. [ append ] { } -rot each
  421. ! TODO project lights
  422. projected-space
  423. ! remove-inner-faces
  424. !
  425. eliminate-empty-solids
  426. ] with-pv
  427. ] [ 3drop <space> ] recover
  428. ; inline
  429. : middle-of-space ( space -- point )
  430. solids>> [ corners>> ] map concat
  431. [ [ ] [ v+ ] map-reduce ] [ length ] bi v/n
  432. ;
  433. ! -------------------------------------------------------------
  434. ! 3D rendering
  435. ! -------------------------------------------------------------
  436. : face-reference ( face -- halfspace point vect )
  437. [ halfspace>> ]
  438. [ touching-corners>> first ]
  439. [ touching-corners>> second ] tri
  440. over v-
  441. ;
  442. : theta ( v halfspace point vect -- v x )
  443. [ [ over ] dip v- ] dip
  444. [ cross dup norm >float ]
  445. [ v. >float ]
  446. 2bi
  447. fatan2
  448. -rot v.
  449. 0 < [ neg ] when
  450. ;
  451. : ordered-face-points ( face -- corners )
  452. [ touching-corners>> 1 head ]
  453. [ touching-corners>> 1 tail ]
  454. [ face-reference [ theta ] 3curry ] tri
  455. { } map>assoc sort-values keys
  456. append
  457. ; inline
  458. : point->GL ( point -- ) gl-vertex ;
  459. : points->GL ( array -- ) do-cycle [ point->GL ] each ;
  460. : face->GL ( face color -- )
  461. [ ordered-face-points ] dip
  462. [ first3 1.0 glColor4d GL_POLYGON
  463. [ [ point->GL ] each ] do-state ] curry
  464. [ 0 0 0 1 glColor4d GL_LINE_LOOP
  465. [ [ point->GL ] each ] do-state ]
  466. bi
  467. ; inline
  468. : solid->GL ( solid -- )
  469. [ faces>> ]
  470. [ color>> ] bi
  471. [ face->GL ] curry each ; inline
  472. : space->GL ( space -- )
  473. solids>>
  474. [ solid->GL ] each ;