]> gitweb.factorcode.org Git - factor.git/blob - extra/game/models/collada/collada.factor
specialized-arrays: performed some cleanup.
[factor.git] / extra / game / models / collada / collada.factor
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
11
12 SINGLETON: collada-models
13 "dae" ascii collada-models register-models-class
14
15 ERROR: missing-attr tag attr ;
16 ERROR: missing-child tag child-name ;
17
18 <PRIVATE
19 TUPLE: source semantic offset data ;
20 SYMBOLS: up-axis unit-ratio ;
21
22 : string>numbers ( string -- number-seq )
23     " \t\n" split harvest [ string>number ] map ;
24
25 : string>floats ( string -- float-seq )
26     " \t\n" split harvest [ string>number ] map ;
27
28 : x/ ( tag child-name -- child-tag )
29     [ tag-named ]
30     [ rot dup [ drop missing-child ] unless 2nip ]
31     2bi ; inline
32
33 : x@ ( tag attr-name -- attr-value )
34     [ attr ]
35     [ rot dup [ drop missing-attr ] unless 2nip ]
36     2bi ; inline
37
38 : xt ( tag -- content ) children>string ;
39
40 : x* ( tag child-name quot -- seq )
41     [ tags-named ] dip map ; inline
42
43 SINGLETONS: x-up y-up z-up ;
44 UNION: rh-up x-up y-up z-up ;
45
46 GENERIC: >y-up-axis! ( seq from-axis -- seq )
47 M: x-up >y-up-axis!
48     drop dup
49     [
50         [ 0 swap nth ]
51         [ 1 swap nth neg ]
52         [ 2 swap nth ] tri
53         swap -rot 
54     ] [
55         [ 2 swap set-nth ]
56         [ 1 swap set-nth ]
57         [ 0 swap set-nth ] tri
58     ] bi ;
59 M: y-up >y-up-axis! drop ;
60 M: z-up >y-up-axis!
61     drop dup
62     [
63         [ 0 swap nth ]
64         [ 1 swap nth neg ]
65         [ 2 swap nth ] tri
66         swap
67     ] [
68         [ 2 swap set-nth ]
69         [ 1 swap set-nth ]
70         [ 0 swap set-nth ] tri
71     ] bi ;
72
73 : source>seq ( source-tag up-axis scale -- sequence )
74     rot
75     [ "float_array" x/ xt string>floats [ * ] with map ]
76     [ nip "technique_common" x/ "accessor" x/ "stride" x@ string>number ] 2bi
77     group
78     [ swap over length 2 > [ >y-up-axis! ] [ drop ] if ] with map ;
79
80 : source>pair ( source-tag -- pair )
81     [ "id" x@ ]
82     [ up-axis get unit-ratio get source>seq ] bi 2array ;
83
84 : mesh>sources ( mesh-tag -- hashtable )
85     "source" [ source>pair ] x* >hashtable ;
86
87 : mesh>vertices ( mesh-tag -- pair )
88     "vertices" x/
89     [ "id" x@ ]
90     [ "input"
91       [
92           [ "semantic" x@ ]
93           [ "source" x@ ] bi 2array
94       ] x*
95     ] bi 2array ;
96
97 :: collect-sources ( sources vertices inputs -- seq )
98     inputs
99     [| input |
100         input "source" x@ rest vertices first =
101         [
102             vertices second [| vertex |
103                 vertex first
104                 input "offset" x@ string>number
105                 vertex second rest sources at source boa
106             ] map
107         ]
108         [
109             input [ "semantic" x@ ]
110                   [ "offset" x@ string>number ]
111                   [ "source" x@ rest sources at ] tri source boa
112         ] if
113     ] map flatten ;
114
115 : group-indices ( index-stride triangle-count indices -- grouped-indices )
116     dup length rot / group swap [ group ] curry map ;
117
118 : triangles>numbers ( triangles-tag -- number-seq )
119     "p" x/ children>string " \t\n" split [ string>number ] map ;
120
121 : largest-offset+1 ( source-seq -- largest-offset+1 )
122     [ offset>> ] [ max ] map-reduce 1 + ;
123
124 VERTEX-FORMAT: collada-vertex-format
125     { "POSITION" float-components 3 f }
126     { "NORMAL" float-components 3 f }
127     { "TEXCOORD" float-components 2 f } ;
128
129 : pack-attributes ( source-indices sources -- attributes )
130     [
131         [
132             [
133                 [ data>> ] [ offset>> ] bi
134                 rot = [ nth ] [ 2drop f ] if 
135             ] with with map sift flatten ,
136         ] curry each-index
137     ] V{ } make flatten ;
138
139 :: soa>aos ( triangles-indices sources -- attribute-buffer index-buffer )
140     [ triangles-indices [ [ sources pack-attributes , ] each ] each ]
141     V{ } V{ } H{ } <indexed-seq> make [ dseq>> ] [ iseq>> ] bi ;
142
143 : triangles>model ( sources vertices triangles-tag -- model )
144     [ "input" tags-named collect-sources ] keep swap
145     
146     [
147         largest-offset+1 swap
148         [ "count" x@ string>number ] [ triangles>numbers ] bi
149         group-indices
150     ]
151     [
152         soa>aos 
153         [ flatten c:float >c-array ]
154         [ flatten c:uint >c-array ]
155         bi* collada-vertex-format f model boa
156     ] bi ;
157     
158 : mesh>triangles ( sources vertices mesh-tag -- models )
159     "triangles" tags-named [ triangles>model ] with with map ;
160
161 : mesh>models ( mesh-tag -- models )
162     [
163         { { up-axis y-up } { unit-ratio 1 } } [
164             mesh>sources
165         ] bind
166     ]
167     [ mesh>vertices ]
168     [ mesh>triangles ] tri ;
169 PRIVATE>
170
171 M: collada-models stream>models
172     drop read-xml "mesh" deep-tags-named [ mesh>models ] map flatten ;