]> gitweb.factorcode.org Git - factor.git/commitdiff
Factored collada implementation a bit more and fixed some bugs
authorerikc <erikcharlebois@gmail.com>
Mon, 1 Feb 2010 00:56:26 +0000 (16:56 -0800)
committererikc <erikcharlebois@gmail.com>
Mon, 1 Feb 2010 00:56:26 +0000 (16:56 -0800)
basis/collada/collada-docs.factor [deleted file]
basis/collada/collada.factor [deleted file]
basis/collada/viewer/viewer.factor
extra/game/models/collada/authors.txt [new file with mode: 0644]
extra/game/models/collada/collada-docs.factor [new file with mode: 0644]
extra/game/models/collada/collada.factor [new file with mode: 0644]
extra/game/models/collada/summary.txt [new file with mode: 0644]

diff --git a/basis/collada/collada-docs.factor b/basis/collada/collada-docs.factor
deleted file mode 100644 (file)
index 6ce32ee..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-! Copyright (C) 2010 Erik Charlebois
-! See http://factorcode.org/license.txt for BSD license.
-USING: help.markup help.crossref help.stylesheet help.topics help.syntax
-definitions io prettyprint summary arrays math sequences vocabs strings
-see xml.data hashtables ;
-IN: collada
-
-ABOUT: "collada"
-
-ARTICLE: "collada" "Conversion of COLLADA assets"
-"The " { $vocab-link "collada" } " vocabulary implements words for converting COLLADA assets to data suitable for use with OpenGL. See the COLLADA documentation at " { $url "http://collada.org" } "." ;
-
-HELP: model
-{ $class-description "Tuple of a packed attribute buffer, index buffer and vertex format suitable for a single OpenGL draw call." } ;
-
-HELP: source
-{ $class-description "Tuple of a vertex attribute semantic, offset in triangle index buffer and float data for a single vertex attribute." } ;
-
-HELP: up-axis
-{ $description "Dynamically-scoped variable with the up axis of the tags being read." } ;
-
-HELP: unit-ratio
-{ $description "Scaling ratio for the coordinates of the tags being read." } ;
-
-HELP: missing-attr
-{ $description "An error thrown when an attribute is missing from a tag." } ;
-
-HELP: missing-child
-{ $description "An error thrown when a child is missing from a tag." } ;
-
-HELP: string>numbers ( string -- number-seq )
-{ $values { "string" string } { "number-seq" sequence } }
-{ $description "Splits a string on whitespace and converts the elements to a number sequence" } ;
-
-HELP: x-up { $class-description "Right-handed 3D coordinate system where X is up." } ;
-HELP: y-up { $class-description "Right-handed 3D coordinate system where Y is up." } ;
-HELP: z-up { $class-description "Right-handed 3D coordinate system where Z is up." } ;
-
-HELP: >y-up-axis!
-{ $values { "sequence" sequence } { "from-axis" rh-up } { "sequence" sequence } }
-{ $description "Destructively swizzles the first three elements of the input sequence to a right-handed 3D coordinate system where Y is up and returns the modified sequence." } ;
-
-HELP: source>seq
-{ $values { "source-tag" tag } { "up-axis" rh-up } { "scale" number } { "sequence" sequence } }
-{ $description "Convert the " { $emphasis "float_array" } " in a " { $emphasis "source tag" } " to a sequence of number sequences according to the element stride. The values are scaled according to " { $emphasis "scale" } " and swizzled from " { $emphasis "up-axis" } " so that the Y coordinate points up." } ;
-
-HELP: source>pair
-{ $values { "source-tag" tag } { "pair" pair } }
-{ $description "Convert the source tag to an id and number sequence pair." } ;
-
-HELP: mesh>sources
-{ $values { "mesh-tag" tag } { "hashtable" pair } }
-{ $description "Convert the mesh tag's source elements to a hashtable from id to number sequence." } ;
-
-HELP: mesh>vertices
-{ $values { "mesh-tag" tag } { "pair" pair } }
-{ $description "Convert the mesh tag's vertices element to a pair for further lookup in " { $link collect-sources } ". " } ;
-
-HELP: collect-sources
-{ $values { "sources" hashtable } { "vertices" pair } { "inputs" tag sequence } { "soures" sequence } }
-{ $description "Look up the sources for these " { $emphasis "input" } " elements and return a sequence of " { $link source } " tuples." } ;
-
-HELP: group-indices
-{ $values { "index-stride" number } { "triangle-count" number } { indices "sequence" } { "grouped-indices" sequence } }
-{ $description "Groups the index sequence by triangle and then groups each triangle's indices by vertex." } ;
-
-HELP: triangles>numbers
-{ $values { "triangles-tag" tag } { "number-seq" sequence } }
-{ $description "Converts the triangle data in a triangles tag from string form to a sequence of numbers." } ;
-
-HELP: largest-offset+1
-{ $values { "source-seq" sequence } { "largest-offset+1" number } }
-{ $description "Finds the largest offset in the sequence of " { $link source } " tuples and adds 1, which is the index stride for " { $link group-indices } "." } ;
-
-HELP: <model>
-{ $values { "attribute-buffer" sequence } { "index-buffer" sequence } { "sources" sequence } { "model" model } }
-{ $description "Converts the inputs to a form suitable for use with " { $vocab-link "gpu" } " and constructs a " { $link model } "." } ;
-
-HELP: soa>aos
-{ $values { "triangles-indices" sequence } { "sources" sequence } { "attribute-buffer" sequence } { "index-buffer" sequence } }
-{ $description "Swizzles the input sources from a structure of arrays form to an array of structures form and generates a new index buffer." } ;
-
-HELP: triangles>model
-{ $values { "sources" sequence } { "vertices" pair } { "triangles-tag" tag } { "model" model } }
-{ $description "Creates a " { $link model } " tuple from the given triangles tag, source set and vertices pair." } ;
-
-HELP: mesh>triangles
-{ $values { "souces" sequence } { "vertices" pair } { "mesh-tag" tag } { "models" sequence } }
-{ $description "Creates a sequence of models from the triangles in the mesh tag." } ;
-
-HELP: mesh>models
-{ $values { "mesh-tag" tag } { "models" sequence } }
-{ $description "Converts a triangle mesh to a set of models suitable for rendering with OpenGL." } ;
diff --git a/basis/collada/collada.factor b/basis/collada/collada.factor
deleted file mode 100644 (file)
index 30ad522..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-! Copyright (C) 2010 Erik Charlebois
-! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays assocs grouping hashtables kernel
-locals math math.parser sequences sequences.deep
-specialized-arrays.instances.alien.c-types.float
-specialized-arrays.instances.alien.c-types.uint splitting xml
-xml.data xml.traversal math.order
-namespaces combinators images gpu.shaders io ;
-IN: collada
-
-TUPLE: model attribute-buffer index-buffer vertex-format ;
-TUPLE: source semantic offset data ;
-
-SYMBOLS: up-axis unit-ratio ;
-
-ERROR: missing-attr tag attr ;
-ERROR: missing-child tag child-name ;
-
-: string>numbers ( string -- number-seq )
-    " \t\n" split [ string>number ] map ;
-
-: x/ ( tag child-name -- child-tag )
-    [ tag-named ]
-    [ rot dup [ drop missing-child ] unless 2nip ]
-    2bi ; inline
-
-: x@ ( tag attr-name -- attr-value )
-    [ attr ]
-    [ rot dup [ drop missing-attr ] unless 2nip ]
-    2bi ; inline
-
-: xt ( tag -- content ) children>string ;
-
-: x* ( tag child-name quot -- seq )
-    [ tags-named ] dip map ; inline
-
-SINGLETONS: x-up y-up z-up ;
-
-UNION: rh-up x-up y-up z-up ;
-
-GENERIC: >y-up-axis! ( seq from-axis -- seq )
-M: x-up >y-up-axis!
-    drop dup
-    [
-        [ 0 swap nth ]
-        [ 1 swap nth neg ]
-        [ 2 swap nth ] tri
-        swap -rot 
-    ] [
-        [ 2 swap set-nth ]
-        [ 1 swap set-nth ]
-        [ 0 swap set-nth ] tri
-    ] bi ;
-M: y-up >y-up-axis! drop ;
-M: z-up >y-up-axis!
-    drop dup
-    [
-        [ 0 swap nth ]
-        [ 1 swap nth neg ]
-        [ 2 swap nth ] tri
-        swap
-    ] [
-        [ 2 swap set-nth ]
-        [ 1 swap set-nth ]
-        [ 0 swap set-nth ] tri
-    ] bi ;
-
-: source>seq ( source-tag up-axis scale -- sequence )
-    rot
-    [ "float_array" x/ xt string>numbers [ * ] with map ]
-    [ nip "technique_common" x/ "accessor" x/ "stride" x@ string>number ] 2bi
-    <groups>
-    [ swap >y-up-axis! ] with map ;
-
-: source>pair ( source-tag -- pair )
-    [ "id" x@ ]
-    [ up-axis get unit-ratio get source>seq ] bi 2array ;
-
-: mesh>sources ( mesh-tag -- hashtable )
-    "source" [ source>pair ] x* >hashtable ;
-
-: mesh>vertices ( mesh-tag -- pair )
-    "vertices" x/
-    [ "id" x@ ]
-    [ "input"
-      [
-          [ "semantic" x@ ]
-          [ "source" x@ ] bi 2array
-      ] x*
-    ] bi 2array ;
-
-:: collect-sources ( sources vertices inputs -- sources )
-    inputs
-    [| input |
-        input "source" x@ rest vertices first =
-        [
-            vertices second [| vertex |
-                vertex first
-                input "offset" x@ string>number
-                vertex second rest sources at source boa
-            ] map
-        ]
-        [
-            input [ "semantic" x@ ]
-                  [ "offset" x@ string>number ]
-                  [ "source" x@ rest sources at ] tri source boa
-        ] if
-    ] map flatten ;
-
-: group-indices ( index-stride triangle-count indices -- grouped-indices )
-    dup length rot / <groups> swap [ <groups> ] curry map ;
-
-: triangles>numbers ( triangles-tag -- number-seq )
-    "p" x/ children>string " \t\n" split [ string>number ] map ;
-
-: largest-offset+1 ( source-seq -- largest-offset+1 )
-    [ offset>> ] [ max ] map-reduce 1 + ;
-
-: <model> ( attribute-buffer index-buffer sources -- model )
-    [ flatten >float-array ]
-    [ flatten >uint-array ]
-    [
-        [
-            {
-                [ semantic>> ]
-                [ drop float-components ]
-                [ data>> first length ]
-                [ drop f ]
-            } cleave vertex-attribute boa
-        ] map
-    ] tri* model boa ;
-
-:: soa>aos ( triangles-indices sources -- attribute-buffer index-buffer )
-    V{ } clone :> attribute-buffer
-    V{ } clone :> index-buffer
-    H{ } clone :> inverse-attribute-buffer
-    triangles-indices [
-        [
-            [| triangle-index triangle-offset |
-                triangle-index triangle-offset sources
-                [| index offset source |
-                    source offset>> offset = [
-                        index source data>> nth
-                    ] [ f ] if 
-                ] with with map sift flatten :> attributes
-                
-                attributes inverse-attribute-buffer at [
-                    index-buffer push
-                ] [
-                    attribute-buffer length
-                    [ attributes inverse-attribute-buffer set-at ]
-                    [ index-buffer push ] bi
-                    attributes attribute-buffer push
-                ] if*
-            ] each-index
-        ] each
-    ] each
-    attribute-buffer index-buffer ;
-
-: triangles>model ( sources vertices triangles-tag -- model )
-    [ "input" tags-named collect-sources ] keep swap
-    
-    [
-        largest-offset+1 swap
-        [ "count" x@ string>number ] [ triangles>numbers ] bi
-        group-indices
-    ]
-    [
-        [ soa>aos ] keep <model>
-    ] bi ;
-    
-: mesh>triangles ( sources vertices mesh-tag -- models )
-    "triangles" tags-named [ triangles>model ] with with map ;
-
-: mesh>models ( mesh-tag -- models )
-    [
-        { { up-axis z-up } { unit-ratio 0.5 } } [
-            mesh>sources
-        ] bind
-    ]
-    [ mesh>vertices ]
-    [ mesh>triangles ] tri ;
index 93d8e35b27433aafb4d8a35a1e1d0ef6205c4497..07fb09203fddcfcfc44fa4949cb0386b5b071944 100644 (file)
@@ -8,8 +8,9 @@ io io.encodings.ascii io.files io.files.temp kernel locals math
 math.matrices math.vectors.simd math.parser math.vectors
 method-chains namespaces sequences splitting threads ui ui.gadgets
 ui.gadgets.worlds ui.pixel-formats specialized-arrays
-specialized-vectors literals collada fry xml xml.traversal sequences.deep
+specialized-vectors literals game.models.collada fry xml xml.traversal sequences.deep
 
+math.bitwise
 opengl.gl
 prettyprint ;
 FROM: alien.c-types => float ;
@@ -23,18 +24,26 @@ uniform vec3 light_position;
 
 attribute vec3 POSITION;
 attribute vec3 NORMAL;
+attribute vec2 TEXCOORD;
+
+varying vec2 texit;
+varying vec3 norm;
 
 void main()
 {
     vec4 position = mv_matrix * vec4(POSITION, 1.0);
     gl_Position = p_matrix * position;
+    texit = TEXCOORD;
+    norm = NORMAL;
 }
 ;
 
 GLSL-SHADER: collada-fragment-shader fragment-shader
+varying vec2 texit;
+varying vec3 norm;
 void main()
 {
-    gl_FragColor = vec4(1, 1, 0, 1);
+    gl_FragColor = vec4(texit, 0, 1) + vec4(norm, 1);
 }
 ;
 
@@ -78,8 +87,9 @@ TUPLE: collada-world < wasd-world
     { collada collada-state } ;
 
 VERTEX-FORMAT: collada-vertex
-    { "POSITION" float-components 3 f }
-    { "NORMAL"   float-components 3 f } ;
+    { "POSITION"   float-components 3 f }
+    { "NORMAL" float-components 3 f }
+    { "TEXCOORD" float-components 2 f } ;
 
 VERTEX-FORMAT: debug-vertex
     { "POSITION" float-components 3 f }
@@ -112,8 +122,8 @@ VERTEX-FORMAT: debug-vertex
     
 : <collada-state> ( -- collada-state )
     collada-state new
-    #! "C:/Users/erikc/Downloads/mech.dae"
-    "/Users/erikc/Documents/mech.dae"
+    "C:/Users/erikc/Downloads/test2.dae"
+    #! "/Users/erikc/Documents/mech.dae"
     file>xml "mesh" deep-tags-named [ mesh>models ] map flatten >>models ;
 
 M: collada-world begin-game-world
@@ -152,10 +162,15 @@ M: collada-world begin-game-world
       { 0 0 0 } { 0 0 1 } { 0 0 1 } } draw-lines ;
           
 : draw-collada ( world -- )
-    GL_COLOR_BUFFER_BIT glClear
+    0 0 0 0 glClearColor 
+    1 glClearDepth
+    HEX: ffffffff glClearStencil
+    { GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT GL_STENCIL_BUFFER_BIT } flags glClear
 
     [
-        triangle-lines dup t <triangle-state> set-gpu-state
+        #! triangle-lines dup t <triangle-state> set-gpu-state
+        face-ccw cull-back <triangle-cull-state> set-gpu-state
+        cmp-less <depth-state> set-gpu-state
         [ collada>> vertex-arrays>> ]
         [ collada>> index-vectors>> ]
         [ <collada-uniforms> ]
@@ -170,6 +185,7 @@ M: collada-world begin-game-world
         ] curry 2each
     ]
     [
+        cmp-always <depth-state> set-gpu-state
         draw-axes
     ]
     bi ;
@@ -177,7 +193,7 @@ M: collada-world begin-game-world
 M: collada-world draw-world*
     draw-collada ;
 
-M: collada-world wasd-movement-speed drop 1/16. ;
+M: collada-world wasd-movement-speed drop 1/4. ;
 M: collada-world wasd-near-plane drop 1/32. ;
 M: collada-world wasd-far-plane drop 1024.0 ;
 
diff --git a/extra/game/models/collada/authors.txt b/extra/game/models/collada/authors.txt
new file mode 100644 (file)
index 0000000..6f03a12
--- /dev/null
@@ -0,0 +1 @@
+Erik Charlebois
diff --git a/extra/game/models/collada/collada-docs.factor b/extra/game/models/collada/collada-docs.factor
new file mode 100644 (file)
index 0000000..d5f727e
--- /dev/null
@@ -0,0 +1,98 @@
+! Copyright (C) 2010 Erik Charlebois
+! See http://factorcode.org/license.txt for BSD license.
+USING: help.markup help.crossref help.stylesheet help.topics help.syntax
+definitions io prettyprint summary arrays math sequences vocabs strings
+see xml.data hashtables assocs ;
+IN: game.models.collada
+
+ABOUT: "game.models.collada"
+
+ARTICLE: "game.models.collada" "Conversion of COLLADA assets"
+"The " { $vocab-link "game.models.collada" } " vocabulary implements words for converting COLLADA assets to data suitable for use with OpenGL. See the COLLADA documentation at " { $url "http://collada.org" } "." ;
+
+HELP: model
+{ $class-description "Tuple of a packed attribute buffer, index buffer and vertex format suitable for a single OpenGL draw call." } ;
+
+HELP: source
+{ $class-description "Tuple of a vertex attribute semantic, offset in triangle index buffer and float data for a single vertex attribute." } ;
+
+HELP: up-axis
+{ $description "Dynamically-scoped variable with the up axis of the tags being read." } ;
+
+HELP: unit-ratio
+{ $description "Scaling ratio for the coordinates of the tags being read." } ;
+
+HELP: indexed-seq
+{ $class-description "A sequence described by a sequence of unique elements and a sequence of indices. The sequence can only be appended to. An associative map is used as a reverse lookup table when appending." } ;
+
+HELP: <indexed-seq>
+{ $values { "dseq-exemplar" sequence } { "iseq-examplar" sequence } { "rassoc-examplar" assoc } }
+{ $class-description "Construct an " { $link indexed-seq } " using the given examplars for the underlying data structures." } ;
+
+HELP: string>numbers ( string -- number-seq )
+{ $values { "string" string } { "number-seq" sequence } }
+{ $description "Splits a string on whitespace and converts the elements to a number sequence" } ;
+
+HELP: x-up { $class-description "Right-handed 3D coordinate system where X is up." } ;
+HELP: y-up { $class-description "Right-handed 3D coordinate system where Y is up." } ;
+HELP: z-up { $class-description "Right-handed 3D coordinate system where Z is up." } ;
+
+HELP: >y-up-axis!
+{ $values { "seq" sequence } { "from-axis" rh-up } { "seq" sequence } }
+{ $description "Destructively swizzles the first three elements of the input sequence to a right-handed 3D coordinate system where Y is up and returns the modified sequence." } ;
+
+HELP: source>seq
+{ $values { "source-tag" tag } { "up-axis" rh-up } { "scale" number } { "sequence" sequence } }
+{ $description "Convert the " { $emphasis "float_array" } " in a " { $emphasis "source tag" } " to a sequence of number sequences according to the element stride. The values are scaled according to " { $emphasis "scale" } " and swizzled from " { $emphasis "up-axis" } " so that the Y coordinate points up." } ;
+
+HELP: source>pair
+{ $values { "source-tag" tag } { "pair" pair } }
+{ $description "Convert the source tag to an id and number sequence pair." } ;
+
+HELP: mesh>sources
+{ $values { "mesh-tag" tag } { "hashtable" pair } }
+{ $description "Convert the mesh tag's source elements to a hashtable from id to number sequence." } ;
+
+HELP: mesh>vertices
+{ $values { "mesh-tag" tag } { "pair" pair } }
+{ $description "Convert the mesh tag's vertices element to a pair for further lookup in " { $link collect-sources } ". " } ;
+
+HELP: collect-sources
+{ $values { "sources" hashtable } { "vertices" pair } { "inputs" tag sequence } { "sources" sequence } }
+{ $description "Look up the sources for these " { $emphasis "input" } " elements and return a sequence of " { $link source } " tuples." } ;
+
+HELP: group-indices
+{ $values { "index-stride" number } { "triangle-count" number } { "indices" sequence } { "grouped-indices" sequence } }
+{ $description "Groups the index sequence by triangle and then groups each triangle's indices by vertex." } ;
+
+HELP: triangles>numbers
+{ $values { "triangles-tag" tag } { "number-seq" sequence } }
+{ $description "Converts the triangle data in a triangles tag from string form to a sequence of numbers." } ;
+
+HELP: largest-offset+1
+{ $values { "source-seq" sequence } { "largest-offset+1" number } }
+{ $description "Finds the largest offset in the sequence of " { $link source } " tuples and adds 1, which is the index stride for " { $link group-indices } "." } ;
+
+HELP: <model>
+{ $values { "attribute-buffer" sequence } { "index-buffer" sequence } { "sources" sequence } { "model" model } }
+{ $description "Converts the inputs to a form suitable for use with " { $vocab-link "gpu" } " and constructs a " { $link model } "." } ;
+
+HELP: pack-attributes
+{ $values { "source-indices" sequence } { "sources" sequence } { "attributes" sequence } }
+{ $description "Packs the attributes for a single vertex into a sequence from a set of source data streams." } ;
+
+HELP: soa>aos
+{ $values { "triangles-indices" sequence } { "sources" sequence } { "attribute-buffer" sequence } { "index-buffer" sequence } }
+{ $description "Swizzles the input sources from a structure of arrays form to an array of structures form and generates a new index buffer." } ;
+
+HELP: triangles>model
+{ $values { "sources" sequence } { "vertices" pair } { "triangles-tag" tag } { "model" model } }
+{ $description "Creates a " { $link model } " tuple from the given triangles tag, source set and vertices pair." } ;
+
+HELP: mesh>triangles
+{ $values { "sources" sequence } { "vertices" pair } { "mesh-tag" tag } { "models" sequence } }
+{ $description "Creates a sequence of models from the triangles in the mesh tag." } ;
+
+HELP: mesh>models
+{ $values { "mesh-tag" tag } { "models" sequence } }
+{ $description "Converts a triangle mesh to a set of models suitable for rendering with OpenGL." } ;
diff --git a/extra/game/models/collada/collada.factor b/extra/game/models/collada/collada.factor
new file mode 100644 (file)
index 0000000..6c5601f
--- /dev/null
@@ -0,0 +1,211 @@
+! Copyright (C) 2010 Erik Charlebois
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors arrays assocs grouping hashtables kernel
+locals math math.parser sequences sequences.deep
+specialized-arrays.instances.alien.c-types.float
+specialized-arrays.instances.alien.c-types.uint splitting xml
+xml.data xml.traversal math.order
+namespaces combinators images gpu.shaders io make ;
+IN: game.models.collada
+
+TUPLE: model attribute-buffer index-buffer vertex-format ;
+TUPLE: source semantic offset data ;
+
+SYMBOLS: up-axis unit-ratio ;
+
+ERROR: missing-attr tag attr ;
+ERROR: missing-child tag child-name ;
+
+TUPLE: indexed-seq dseq iseq rassoc ;
+INSTANCE: indexed-seq sequence
+
+M: indexed-seq length
+    iseq>> length ; inline
+
+M: indexed-seq nth
+    [ iseq>> nth ] keep dseq>> nth ; inline
+
+M:: indexed-seq set-nth ( elt n seq -- )
+    seq dseq>>   :> dseq
+    seq iseq>>   :> iseq
+    seq rassoc>> :> rassoc
+    seq length n = not [ seq immutable ] when
+    elt rassoc at
+    [
+        iseq push
+    ]
+    [
+        dseq length
+        [ elt rassoc set-at ]
+        [ iseq push ] bi
+        elt dseq push
+    ] if* ; inline
+
+: <indexed-seq> ( dseq-examplar iseq-exampler rassoc-examplar -- indexed-seq )
+    indexed-seq new
+    swap clone >>rassoc
+    swap clone >>iseq
+    swap clone >>dseq ;
+
+M: indexed-seq new-resizable
+    [ dseq>> ] [ iseq>> ] [ rassoc>> ] tri <indexed-seq>
+    dup -rot
+    [ [ dseq>> new-resizable ] keep (>>dseq) ]
+    [ [ iseq>> new-resizable ] keep (>>iseq) ]
+    [ [ rassoc>> clone nip ] keep (>>rassoc) ]
+    2tri ;
+
+
+: string>numbers ( string -- number-seq )
+    " \t\n" split [ "" = ] trim [ string>number ] map ;
+
+: x/ ( tag child-name -- child-tag )
+    [ tag-named ]
+    [ rot dup [ drop missing-child ] unless 2nip ]
+    2bi ; inline
+
+: x@ ( tag attr-name -- attr-value )
+    [ attr ]
+    [ rot dup [ drop missing-attr ] unless 2nip ]
+    2bi ; inline
+
+: xt ( tag -- content ) children>string ;
+
+: x* ( tag child-name quot -- seq )
+    [ tags-named ] dip map ; inline
+
+SINGLETONS: x-up y-up z-up ;
+
+UNION: rh-up x-up y-up z-up ;
+
+GENERIC: >y-up-axis! ( seq from-axis -- seq )
+M: x-up >y-up-axis!
+    drop dup
+    [
+        [ 0 swap nth ]
+        [ 1 swap nth neg ]
+        [ 2 swap nth ] tri
+        swap -rot 
+    ] [
+        [ 2 swap set-nth ]
+        [ 1 swap set-nth ]
+        [ 0 swap set-nth ] tri
+    ] bi ;
+M: y-up >y-up-axis! drop ;
+M: z-up >y-up-axis!
+    drop dup
+    [
+        [ 0 swap nth ]
+        [ 1 swap nth neg ]
+        [ 2 swap nth ] tri
+        swap
+    ] [
+        [ 2 swap set-nth ]
+        [ 1 swap set-nth ]
+        [ 0 swap set-nth ] tri
+    ] bi ;
+
+: source>seq ( source-tag up-axis scale -- sequence )
+    rot
+    [ "float_array" x/ xt string>numbers [ * ] with map ]
+    [ nip "technique_common" x/ "accessor" x/ "stride" x@ string>number ] 2bi
+    group
+    [ swap over length 2 > [ >y-up-axis! ] [ drop ] if ] with map ;
+
+: source>pair ( source-tag -- pair )
+    [ "id" x@ ]
+    [ up-axis get unit-ratio get source>seq ] bi 2array ;
+
+: mesh>sources ( mesh-tag -- hashtable )
+    "source" [ source>pair ] x* >hashtable ;
+
+: mesh>vertices ( mesh-tag -- pair )
+    "vertices" x/
+    [ "id" x@ ]
+    [ "input"
+      [
+          [ "semantic" x@ ]
+          [ "source" x@ ] bi 2array
+      ] x*
+    ] bi 2array ;
+
+:: collect-sources ( sources vertices inputs -- sources )
+    inputs
+    [| input |
+        input "source" x@ rest vertices first =
+        [
+            vertices second [| vertex |
+                vertex first
+                input "offset" x@ string>number
+                vertex second rest sources at source boa
+            ] map
+        ]
+        [
+            input [ "semantic" x@ ]
+                  [ "offset" x@ string>number ]
+                  [ "source" x@ rest sources at ] tri source boa
+        ] if
+    ] map flatten ;
+
+: group-indices ( index-stride triangle-count indices -- grouped-indices )
+    dup length rot / group swap [ group ] curry map ;
+
+: triangles>numbers ( triangles-tag -- number-seq )
+    "p" x/ children>string " \t\n" split [ string>number ] map ;
+
+: largest-offset+1 ( source-seq -- largest-offset+1 )
+    [ offset>> ] [ max ] map-reduce 1 + ;
+
+: <model> ( attribute-buffer index-buffer sources -- model )
+    [ flatten >float-array ]
+    [ flatten >uint-array ]
+    [
+        [
+            {
+                [ semantic>> ]
+                [ drop float-components ]
+                [ data>> first length ]
+                [ drop f ]
+            } cleave vertex-attribute boa
+        ] map
+    ] tri* model boa ;
+
+: pack-attributes ( source-indices sources -- attributes )
+    [
+        [
+            [
+                [ data>> ] [ offset>> ] bi
+                rot = [ nth ] [ 2drop f ] if 
+            ] with with map sift flatten ,
+        ] curry each-index
+    ] V{ } make flatten ;
+
+:: soa>aos ( triangles-indices sources -- attribute-buffer index-buffer )
+    [ triangles-indices [ [
+        sources pack-attributes ,
+    ] each ] each ]
+    V{ } V{ } H{ } <indexed-seq> make [ dseq>> ] [ iseq>> ] bi ;
+
+: triangles>model ( sources vertices triangles-tag -- model )
+    [ "input" tags-named collect-sources ] keep swap
+    
+    [
+        largest-offset+1 swap
+        [ "count" x@ string>number ] [ triangles>numbers ] bi
+        group-indices
+    ]
+    [
+        [ soa>aos ] keep <model>
+    ] bi ;
+    
+: mesh>triangles ( sources vertices mesh-tag -- models )
+    "triangles" tags-named [ triangles>model ] with with map ;
+
+: mesh>models ( mesh-tag -- models )
+    [
+        { { up-axis y-up } { unit-ratio 0.5 } } [
+            mesh>sources
+        ] bind
+    ]
+    [ mesh>vertices ]
+    [ mesh>triangles ] tri ;
diff --git a/extra/game/models/collada/summary.txt b/extra/game/models/collada/summary.txt
new file mode 100644 (file)
index 0000000..fd45b22
--- /dev/null
@@ -0,0 +1 @@
+Conversion of COLLADA geometry assets to OpenGL vertex and index buffers