1 ! Copyright (C) 2010 Erik Charlebois
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien.c-types alien.data arrays assocs grouping
4 hashtables kernel locals math math.parser sequences sequences.deep
5 splitting xml xml.data xml.traversal math.order namespaces
6 combinators images gpu.shaders io make game.models game.models.util
7 io.encodings.ascii game.models.loader specialized-arrays ;
8 QUALIFIED-WITH: alien.c-types c
9 SPECIALIZED-ARRAYS: c:float c:uint ;
10 IN: game.models.collada
12 SINGLETON: collada-models
13 "dae" ascii collada-models register-models-class
15 ERROR: missing-attr tag attr ;
16 ERROR: missing-child tag child-name ;
19 TUPLE: source semantic offset data ;
20 SYMBOLS: up-axis unit-ratio ;
22 : string>numbers ( string -- number-seq )
23 " \t\n" split harvest [ string>number ] map ;
25 : x/ ( tag child-name -- child-tag )
27 [ rot dup [ drop throw-missing-child ] unless 2nip ]
30 : x@ ( tag attr-name -- attr-value )
32 [ rot dup [ drop throw-missing-attr ] unless 2nip ]
35 : xt ( tag -- content ) children>string ;
37 : x* ( tag child-name quot -- seq )
38 [ tags-named ] dip map ; inline
40 SINGLETONS: x-up y-up z-up ;
41 UNION: rh-up x-up y-up z-up ;
43 GENERIC: >y-up-axis! ( seq from-axis -- seq )
54 [ 0 swap set-nth ] tri
56 M: y-up >y-up-axis! drop ;
67 [ 0 swap set-nth ] tri
70 : source>sequence ( source-tag up-axis scale -- sequence )
72 [ "float_array" x/ xt string>numbers [ * ] with map ]
73 [ nip "technique_common" x/ "accessor" x/ "stride" x@ string>number ] 2bi
75 [ swap over length 2 > [ >y-up-axis! ] [ drop ] if ] with map ;
77 : source>pair ( source-tag -- pair )
79 [ up-axis get unit-ratio get source>sequence ] bi 2array ;
81 : mesh>sources ( mesh-tag -- hashtable )
82 "source" [ source>pair ] x* >hashtable ;
84 : mesh>vertices ( mesh-tag -- pair )
90 [ "source" x@ ] bi 2array
94 :: collect-sources ( sources vertices inputs -- seq )
97 input "source" x@ rest vertices first =
99 vertices second [| vertex |
101 input "offset" x@ string>number
102 vertex second rest sources at source boa
106 input [ "semantic" x@ ]
107 [ "offset" x@ string>number ]
108 [ "source" x@ rest sources at ] tri source boa
112 : group-indices ( index-stride triangle-count indices -- grouped-indices )
113 dup length rot / group swap [ group ] curry map ;
115 : triangles>numbers ( triangles-tag -- number-seq )
116 "p" x/ children>string " \t\n" split [ string>number ] map ;
118 : largest-offset+1 ( source-seq -- largest-offset+1 )
119 [ offset>> ] [ max ] map-reduce 1 + ;
121 VERTEX-FORMAT: collada-vertex-format
122 { "POSITION" float-components 3 f }
123 { "NORMAL" float-components 3 f }
124 { "TEXCOORD" float-components 2 f } ;
126 : pack-attributes ( source-indices sources -- attributes )
130 [ data>> ] [ offset>> ] bi
131 rot = [ nth ] [ 2drop f ] if
132 ] 2with map sift flatten ,
134 ] V{ } make flatten ;
136 :: soa>aos ( triangles-indices sources -- attribute-buffer index-buffer )
137 [ triangles-indices [ [ sources pack-attributes , ] each ] each ]
138 V{ } V{ } H{ } <indexed-seq> make [ dseq>> ] [ iseq>> ] bi ;
140 : triangles>model ( sources vertices triangles-tag -- model )
141 [ "input" tags-named collect-sources ] keep swap
144 largest-offset+1 swap
145 [ "count" x@ string>number ] [ triangles>numbers ] bi
150 [ flatten c:float >c-array ]
151 [ flatten c:uint >c-array ]
152 bi* collada-vertex-format f model boa
155 : mesh>triangles ( sources vertices mesh-tag -- models )
156 "triangles" tags-named [ triangles>model ] 2with map ;
158 : mesh>models ( mesh-tag -- models )
160 { { up-axis y-up } { unit-ratio 1 } } [
165 [ mesh>triangles ] tri ;
168 M: collada-models stream>models
169 drop read-xml "mesh" deep-tags-named [ mesh>models ] map flatten ;