Browse Source

Merge remote-tracking branch 'timknip/master' into dev

Mr.doob 14 years ago
parent
commit
a22e1f2ece

File diff suppressed because it is too large
+ 64 - 0
examples/models/monster.dae


BIN
examples/models/monster.jpg


+ 619 - 0
examples/models/skin_and_morph.dae

@@ -0,0 +1,619 @@
+<?xml version="1.0" encoding="utf-8"?>
+<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1">
+ <asset>
+   <contributor>
+     <author>gcorson</author>
+     <authoring_tool>Maya8.5 | ColladaMaya v3.03</authoring_tool>
+     <comments>Collada Maya Export Options:
+bakeTransforms=0;exportPolygonMeshes=1;bakeLighting=0;isSampling=0;
+curveConstrainSampling=0;removeStaticCurves=1;exportCameraAsLookat=0;
+exportLights=1;exportCameras=1;exportJointsAndSkin=1;
+exportAnimations=1;exportTriangles=0;exportInvisibleNodes=0;
+exportNormals=1;exportTexCoords=1;
+exportVertexColors=1;exportVertexColorsAnimation=0;exportTangents=0;
+exportTexTangents=0;exportConstraints=1;exportPhysics=1;exportXRefs=1;
+dereferenceXRefs=0;cameraXFov=0;cameraYFov=1</comments>
+     <source_data>
+file:///C:/Documents%20and%20Settings/gcorson/Desktop/Crystal%20Content/AmandaCrush/untitled
+     </source_data>
+   </contributor>
+   <created>2007-04-04T23:08:51Z</created>
+   <modified>2007-06-21T18:50:45Z</modified>
+   <unit meter="0.01" name="centimeter"/>
+   <up_axis>Y_UP</up_axis>
+ </asset>
+ <library_materials>
+   <material id="lambert1" name="lambert2">
+     <instance_effect url="#lambert1-fx"/>
+   </material>
+ </library_materials>
+ <library_effects>
+   <effect id="lambert1-fx">
+     <profile_COMMON>
+       <technique sid="common">
+         <lambert>
+           <emission>
+             <color>0 0 0 1</color>
+           </emission>
+           <ambient>
+             <color>0 0 0 1</color>
+           </ambient>
+           <diffuse>
+             <color>0.9 0.5 0.5 1</color>
+           </diffuse>
+           <transparent opaque="RGB_ZERO">
+             <color>0 0 0 1</color>
+           </transparent>
+           <transparency>
+             <float>1</float>
+           </transparency>
+           <index_of_refraction>
+             <float>1</float>
+           </index_of_refraction>
+         </lambert>
+       </technique>
+     </profile_COMMON>
+   </effect>
+ </library_effects>
+ <library_geometries>
+   <!-- 
+*******************************************************************************************
+This is a pretty standard mesh for the same as used in the skinning example.  It's a 6 
+sided cylinder divided into 6 sections with a total of 42 vertices.  It is used as the
+base mesh (source) in the morph controller.
+******************************************************************************************* 
+    -->   
+   <geometry id="pCylinderShape1" name="pCylinderShape1">
+     <mesh>
+       <source id="pCylinderShape1-positions" name="position">
+         <float_array id="pCylinderShape1-positions-array" count="126">20 -90 -34.641
+-20 -90 -34.641 -40 -90 -0.000005 -20 -90 34.641 20 -90 34.641 40 -90 0 20 -60 -34.641
+-20 -60 -34.641 -40 -60 -0.000005 -20 -60 34.641 20 -60 34.641 40 -60 0 20 -30 -34.641
+-20 -30 -34.641 -40 -30 -0.000005 -20 -30 34.641 20 -30 34.641 40 -30 0 20 0 -34.641
+-20 0 -34.641 -40 0 -0.000005 -20 0 34.641 20 0 34.641 40 0 0 20 30 -34.641 -20 30 -34.641
+-40 30 -0.000005 -20 30 34.641 20 30 34.641 40 30 0 20 60 -34.641 -20 60 -34.641
+-40 60 -0.000005 -20 60 34.641 20 60 34.641 40 60 0 20 90 -34.641 -20 90 -34.641
+-40 90 -0.000005 -20 90 34.641 20 90 34.641 40 90 0</float_array>
+         <technique_common>
+           <accessor source="#pCylinderShape1-positions-array" count="42" stride="3">
+             <param name="X" type="float"/>
+             <param name="Y" type="float"/>
+             <param name="Z" type="float"/>
+           </accessor>
+         </technique_common>
+       </source>
+       <source id="pCylinderShape1-normals" name="normal">
+         <float_array id="pCylinderShape1-normals-array" count="468">0 0 -1 0 0 -1
+0 0 -1 0 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025
+0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1
+0 0 1 0 0 1 0.866026 0 0.5 0.866026 0 0.5 0.866025 0 0.5 0.866025 0 0.5 0.866026
+0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0 0 -1 0 0 -1 0 0 -1 0
+0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026
+0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0 0 1 0 0 1 0.866025
+0 0.5 0.866025 0 0.5 0.866025 0 0.5 0.866025 0 0.5 0.866026 0 -0.5 0.866026
+0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0 0 -1 0 0 -1 0 0 -1 0 0 -1 -0.866025
+0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026
+0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0 0 1 0 0 1 0.866025 0 0.5 0.866025
+0 0.5 0.866025 0 0.5 0.866025 0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026
+0 -0.5 0.866026 0 -0.5 0 0 -1 0 0 -1 0 0 -1 0 0 -1 -0.866025 0 -0.5 -0.866025
+0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026
+0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0 0 1 0 0 1 0.866025 0 0.5 0.866025 0 0.5 0.866025
+0 0.5 0.866025 0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026
+0 -0.5 0 0 -1 0 0 -1 0 0 -1 0 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025
+0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026
+0 0.5 0 0 1 0 0 1 0 0 1 0 0 1 0.866025 0 0.5 0.866025 0 0.5 0.866025 0 0.5 0.866025
+0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0 0 -1 0 0 -1
+0 0 -1 0 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025
+0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 0
+0 1 0 0 1 0 0 1 0 0 1 0.866025 0 0.5 0.866025 0 0.5 0.866026 0 0.5 0.866026
+0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0
+-1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0</float_array>
+         <technique_common>
+           <accessor source="#pCylinderShape1-normals-array" count="156" stride="3">
+             <param name="X" type="float"/>
+             <param name="Y" type="float"/>
+             <param name="Z" type="float"/>
+           </accessor>
+         </technique_common>
+       </source>
+       <source id="pCylinderShape1-map1" name="map1">
+         <float_array id="pCylinderShape1-map1-array" count="122">0.578125 0.020933
+0.421875 0.020933 0.34375 0.15625 0.421875 0.291566 0.578125 0.291566 0.65625 0.15625
+0.375 0.3125 0.416667 0.3125 0.458333 0.3125 0.5 0.3125 0.541667 0.3125 0.583333
+0.3125 0.625 0.3125 0.375 0.375157 0.416667 0.375157 0.458333 0.375157 0.5 0.375157
+0.541667 0.375157 0.583333 0.375157 0.625 0.375157 0.375 0.437813 0.416667 0.437813
+0.458333 0.437813 0.5 0.437813 0.541667 0.437813 0.583333 0.437813 0.625 0.437813
+0.375 0.50047 0.416667 0.50047 0.458333 0.50047 0.5 0.50047 0.541667 0.50047 0.583333
+0.50047 0.625 0.50047 0.375 0.563127 0.416667 0.563127 0.458333 0.563127 0.5 0.563127
+0.541667 0.563127 0.583333 0.563127 0.625 0.563127 0.375 0.625783 0.416667 0.625783
+0.458333 0.625783 0.5 0.625783 0.541667 0.625783 0.583333 0.625783 0.625 0.625783
+0.375 0.68844 0.416667 0.68844 0.458333 0.68844 0.5 0.68844 0.541667 0.68844 0.583333
+0.68844 0.625 0.68844 0.578125 0.708434 0.421875 0.708434 0.34375 0.84375 0.421875
+0.979066 0.578125 0.979066 0.65625 0.84375</float_array>
+         <technique_common>
+           <accessor source="#pCylinderShape1-map1-array" count="61" stride="2">
+             <param name="S" type="float"/>
+             <param name="T" type="float"/>
+           </accessor>
+         </technique_common>
+       </source>
+       <vertices id="pCylinderShape1-vertices">
+         <input semantic="POSITION" source="#pCylinderShape1-positions"/>
+       </vertices>
+       <polylist material="lambert2SG" count="38">
+         <input semantic="VERTEX" source="#pCylinderShape1-vertices" offset="0"/>
+         <input semantic="NORMAL" source="#pCylinderShape1-normals" offset="1"/>
+         <input semantic="TEXCOORD" source="#pCylinderShape1-map1" offset="2" set="0"/>
+         <vcount>4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 6 6</vcount>
+         <p>0 0 6 1 1 7 7 2 14 6 3 13 1 4 7 2 5 8 8 6 15 7 7 14 2 8 8 3 9 9 9 10
+ 16 8 11 15 3 12 9 4 13 10 10 14 17 9 15 16 4 16 10 5 17 11 11 18 18 10 19 17 5
+ 20 11 0 21 12 6 22 19 11 23 18 6 24 13 7 25 14 13 26 21 12 27 20 7 28 14 8 29 15 14
+ 30 22 13 31 21 8 32 15 9 33 16 15 34 23 14 35 22 9 36 16 10 37 17 16 38 24 15
+ 39 23 10 40 17 11 41 18 17 42 25 16 43 24 11 44 18 6 45 19 12 46 26 17 47 25 12
+ 48 20 13 49 21 19 50 28 18 51 27 13 52 21 14 53 22 20 54 29 19 55 28 14 56 22 15
+ 57 23 21 58 30 20 59 29 15 60 23 16 61 24 22 62 31 21 63 30 16 64 24 17 65 25 23
+ 66 32 22 67 31 17 68 25 12 69 26 18 70 33 23 71 32 18 72 27 19 73 28 25 74 35 24
+ 75 34 19 76 28 20 77 29 26 78 36 25 79 35 20 80 29 21 81 30 27 82 37 26 83 36 21
+ 84 30 22 85 31 28 86 38 27 87 37 22 88 31 23 89 32 29 90 39 28 91 38 23 92 32 18
+ 93 33 24 94 40 29 95 39 24 96 34 25 97 35 31 98 42 30 99 41 25 100 35 26 101 36 32
+ 102 43 31 103 42 26 104 36 27 105 37 33 106 44 32 107 43 27 108 37 28 109 38 34
+ 110 45 33 111 44 28 112 38 29 113 39 35 114 46 34 115 45 29 116 39 24 117 40 30
+ 118 47 35 119 46 30 120 41 31 121 42 37 122 49 36 123 48 31 124 42 32 125 43 38
+ 126 50 37 127 49 32 128 43 33 129 44 39 130 51 38 131 50 33 132 44 34 133 45 40
+ 134 52 39 135 51 34 136 45 35 137 46 41 138 53 40 139 52 35 140 46 30 141 47 36
+ 142 54 41 143 53 0 144 0 5 145 5 4 146 4 3 147 3 2 148 2 1 149 1 36 150 59 37
+ 151 58 38 152 57 39 153 56 40 154 55 41 155 60</p>
+       </polylist>
+     </mesh>
+   </geometry>
+   <!-- 
+*******************************************************************************************
+This mesh is the same as the one above, but one of the rings of verticies has been moved 
+outwards to create a bulge in the middle of the cylinder.  This geometry is used as the
+morph target (aka deformer or blend shape) in the morph controller.
+
+A morph can operate on ANY or ALL of the sources so you could morph positions, UVs and 
+normals all at the same time.  The sources to be morphed have to be referenced by <input>
+tags inside the <vertices> tag in both the morph target and the base mesh.  In this example
+only the positions are referenced by the <vertices> tag so they are all this morph will effect.
+
+Since only the positions are being morphed, everything but the target__pCylinderShape1-positions
+source and the <vertices> tag could be deleted from this <geometry> and it the morph
+should still work.  The DCC tool should get all the other information from the base mesh, so
+there is no need to duplicate it here.
+
+This extra information may still be exported by some DCC tools for a variety of reasons.
+The only time it is actually REQUIRED is if the morph target geometry is also instantiated in
+the scene by having an <instance_geometry> tag point directly to it's geometry tag.
+
+Due to a bug in the ColladaMaya Maya expects the polylist information to be present in the 
+morph target or the morph will not be instantiated.
+******************************************************************************************* 
+    -->   
+   <geometry id="target__pCylinderShape1" name="target__pCylinderShape1">
+     <mesh>
+       <source id="target__pCylinderShape1-positions" name="position">
+         <float_array id="target__pCylinderShape1-positions-array" count="126">20 -90 -34.641
+-20 -90 -34.641 -40 -90 -0.000005 -20 -90 34.641 20 -90 34.641 40 -90 0 20 -60 -34.641
+-20 -60 -34.641 -40 -60 -0.000005 -20 -60 34.641 20 -60 34.641 40 -60 0 20 -30 -34.641
+-20 -30 -34.641 -40 -30 -0.000005 -20 -30 34.641 20 -30 34.641 40 -30 0 20 0 -34.641
+-20 0 -34.641 -40 0 -0.000005 -20 0 34.641 20 0 34.641 40 0 0 32.6396 30 -69.7557
+-32.6396 30 -69.7557 -65.2792 30 -0.00001 -32.6396 30 69.7557 32.6396 30 69.7557
+65.2792 30 0 20 60 -34.641 -20 60 -34.641 -40 60 -0.000005 -20 60 34.641 20 60 34.641
+40 60 0 20 90 -34.641 -20 90 -34.641 -40 90 -0.000005 -20 90 34.641 20 90 34.641
+40 90 0</float_array>
+         <technique_common>
+           <accessor source="#target__pCylinderShape1-positions-array" count="42" stride="3">
+             <param name="X" type="float"/>
+             <param name="Y" type="float"/>
+             <param name="Z" type="float"/>
+           </accessor>
+         </technique_common>
+       </source>
+       <source id="target__pCylinderShape1-normals" name="normal">
+         <float_array id="target__pCylinderShape1-normals-array" count="468">0 0 -1
+0 0 -1 0 0 -1 0 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025
+0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1
+0 0 1 0 0 1 0.866026 0 0.5 0.866026 0 0.5 0.866025 0 0.5 0.866025 0 0.5 0.866026
+0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0 0 -1 0 0 -1 0 0 -1 0 0 -1
+-0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026
+0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0 0 1 0 0 1
+0.866025 0 0.5 0.866025 0 0.5 0.866025 0 0.5 0.866025 0 0.5 0.866026 0 -0.5 0.866026
+0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0 0 -1 0 0 -1 0 0 -1 0 0 -1 -0.866025
+0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026
+0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0 0 1 0 0 1 0.866025 0 0.5 0.866025
+0 0.5 0.866025 0 0.5 0.866025 0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026
+0 -0.5 0.866026 0 -0.5 0 0 -1 0 0 -1 0 0 -1 0 0 -1 -0.866025 0 -0.5 -0.866025
+0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026
+0 0.5 -0.866026 0 0.5 0 0 1 0 0 1 0 0 1 0 0 1 0.866025 0 0.5 0.866025 0 0.5 0.866025
+0 0.5 0.866025 0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026
+0 -0.5 0 0 -1 0 0 -1 0 0 -1 0 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025
+0 -0.5 -0.866025 0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026
+0 0.5 0 0 1 0 0 1 0 0 1 0 0 1 0.866025 0 0.5 0.866025 0 0.5 0.866025 0 0.5 0.866025
+0 0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0 0 -1 0
+0 -1 0 0 -1 0 0 -1 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025 0 -0.5 -0.866025
+0 -0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 -0.866026 0 0.5 0 0 1 0
+0 1 0 0 1 0 0 1 0.866025 0 0.5 0.866025 0 0.5 0.866026 0 0.5 0.866026 0 0.5 0.866026
+0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0.866026 0 -0.5 0 -1 0 0 -1 0 0 -1 0 0 -1 0 0
+-1 0 0 -1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0 0 1 0</float_array>
+         <technique_common>
+           <accessor source="#target__pCylinderShape1-normals-array" count="156" stride="3">
+             <param name="X" type="float"/>
+             <param name="Y" type="float"/>
+             <param name="Z" type="float"/>
+           </accessor>
+         </technique_common>
+       </source>
+       <source id="target__pCylinderShape1-map1" name="map1">
+         <float_array id="target__pCylinderShape1-map1-array" count="122">0.578125 0.020933
+0.421875 0.020933 0.34375 0.15625 0.421875 0.291566 0.578125 0.291566 0.65625 0.15625 0.375
+0.3125 0.416667 0.3125 0.458333 0.3125 0.5 0.3125 0.541667 0.3125 0.583333 0.3125 0.625
+0.3125 0.375 0.375157 0.416667 0.375157 0.458333 0.375157 0.5 0.375157 0.541667 0.375157
+0.583333 0.375157 0.625 0.375157 0.375 0.437813 0.416667 0.437813 0.458333 0.437813 0.5
+0.437813 0.541667 0.437813 0.583333 0.437813 0.625 0.437813 0.375 0.50047 0.416667 0.50047
+0.458333 0.50047 0.5 0.50047 0.541667 0.50047 0.583333 0.50047 0.625 0.50047 0.375
+0.563127 0.416667 0.563127 0.458333 0.563127 0.5 0.563127 0.541667 0.563127 0.583333
+0.563127 0.625 0.563127 0.375 0.625783 0.416667 0.625783 0.458333 0.625783 0.5 0.625783
+0.541667 0.625783 0.583333 0.625783 0.625 0.625783 0.375 0.68844 0.416667 0.68844
+0.458333 0.68844 0.5 0.68844 0.541667 0.68844 0.583333 0.68844 0.625 0.68844 0.578125
+0.708434 0.421875 0.708434 0.34375 0.84375 0.421875 0.979066 0.578125 0.979066 0.65625
+0.84375</float_array>
+         <technique_common>
+           <accessor source="#target__pCylinderShape1-map1-array" count="61" stride="2">
+             <param name="S" type="float"/>
+             <param name="T" type="float"/>
+           </accessor>
+         </technique_common>
+       </source>
+       <vertices id="target__pCylinderShape1-vertices">
+         <input semantic="POSITION" source="#target__pCylinderShape1-positions"/>
+       </vertices>
+       <polylist material="target__lambert2SG" count="38">
+         <input semantic="VERTEX" source="#target__pCylinderShape1-vertices" offset="0"/>
+         <input semantic="NORMAL" source="#target__pCylinderShape1-normals" offset="1"/>
+         <input semantic="TEXCOORD" source="#target__pCylinderShape1-map1" offset="2" set="0"/>
+         <vcount>4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 6 6</vcount>
+         <p>0 0 6 1 1 7 7 2 14 6 3 13 1 4 7 2 5 8 8 6 15 7 7 14 2 8 8 3 9 9 9 10 16 8 11
+ 15 3 12 9 4 13 10 10 14 17 9 15 16 4 16 10 5 17 11 11 18 18 10 19 17 5 20 11 0 21 12 6
+ 22 19 11 23 18 6 24 13 7 25 14 13 26 21 12 27 20 7 28 14 8 29 15 14 30 22 13 31 21 8
+ 32 15 9 33 16 15 34 23 14 35 22 9 36 16 10 37 17 16 38 24 15 39 23 10 40 17 11 41 18 17
+ 42 25 16 43 24 11 44 18 6 45 19 12 46 26 17 47 25 12 48 20 13 49 21 19 50 28 18
+ 51 27 13 52 21 14 53 22 20 54 29 19 55 28 14 56 22 15 57 23 21 58 30 20 59 29 15
+ 60 23 16 61 24 22 62 31 21 63 30 16 64 24 17 65 25 23 66 32 22 67 31 17 68 25 12
+ 69 26 18 70 33 23 71 32 18 72 27 19 73 28 25 74 35 24 75 34 19 76 28 20 77 29 26
+ 78 36 25 79 35 20 80 29 21 81 30 27 82 37 26 83 36 21 84 30 22 85 31 28 86 38 27
+ 87 37 22 88 31 23 89 32 29 90 39 28 91 38 23 92 32 18 93 33 24 94 40 29 95 39 24
+ 96 34 25 97 35 31 98 42 30 99 41 25 100 35 26 101 36 32 102 43 31 103 42 26 104 36 27
+ 105 37 33 106 44 32 107 43 27 108 37 28 109 38 34 110 45 33 111 44 28 112 38 29
+ 113 39 35 114 46 34 115 45 29 116 39 24 117 40 30 118 47 35 119 46 30 120 41 31
+ 121 42 37 122 49 36 123 48 31 124 42 32 125 43 38 126 50 37 127 49 32 128 43 33
+ 129 44 39 130 51 38 131 50 33 132 44 34 133 45 40 134 52 39 135 51 34 136 45 35
+ 137 46 41 138 53 40 139 52 35 140 46 30 141 47 36 142 54 41 143 53 0 144 0 5
+ 145 5 4 146 4 3 147 3 2 148 2 1 149 1 36 150 59 37 151 58 38 152 57 39 153 56 40
+ 154 55 41 155 60</p>
+       </polylist>
+     </mesh>
+   </geometry>
+ </library_geometries>
+ <library_controllers>
+    <!--
+*******************************************************************************************
+This controller defines a morph with pCylinderShape1 as the source and 
+target_pCylinderShape1 as the morph target (deformer)
+*******************************************************************************************
+    -->
+  <controller id="pCylinderShape1-morph" name="blendShape1">
+     <morph method="NORMALIZED" source="#pCylinderShape1">
+    <!--
+*******************************************************************************************
+This source lists all the morph targets that will be used by this controller.  In this
+case there is just one, but there could be as many as you like.  Multiple targets are 
+commonly used to apply facial expressions to characters.  There would a "happy" morph,
+a "sad" one, an excited one...etc. Which could be mixed so you could make an expression
+that was half sad, half excited...etc.
+*******************************************************************************************
+    -->
+       <source id="pCylinderShape1-morph-targets">
+         <IDREF_array id="pCylinderShape1-morph-targets-array" count="1">target__pCylinderShape1</IDREF_array>
+         <technique_common>
+           <accessor source="#pCylinderShape1-morph-targets-array" count="1" stride="1">
+             <param name="MORPH_TARGET" type="IDREF"/>
+           </accessor>
+         </technique_common>
+       </source>
+    <!--
+*******************************************************************************************
+This source contains the weights to be applied to each morph target (in this case just one)
+A weight of 1 means the morph is fully applied.  This can be animated.
+*******************************************************************************************
+    -->
+       <source id="pCylinderShape1-morph-morph_weights">
+         <float_array id="pCylinderShape1-morph-morph_weights-array" count="1">1</float_array>
+         <technique_common>
+           <accessor source="#pCylinderShape1-morph-morph_weights-array" count="1" stride="1">
+             <param name="MORPH_WEIGHT" type="float"/>
+           </accessor>
+         </technique_common>
+       </source>
+       <!--
+*******************************************************************************************
+The inputs in the targets tag point to the sources containing the list of morph targets and
+the list of corrisponding weights.
+*******************************************************************************************
+        -->
+       <targets>
+         <input semantic="MORPH_TARGET" source="#pCylinderShape1-morph-targets"/>
+         <input semantic="MORPH_WEIGHT" source="#pCylinderShape1-morph-morph_weights"/>
+       </targets>
+     </morph>
+   </controller>
+   <!--
+*******************************************************************************************
+This controller defines how to skin the geometry that comes out of the morph controller.
+*******************************************************************************************
+    -->
+   <controller id="pCylinderShape1-morph-skin" name="skinCluster1">
+   	<!--
+*******************************************************************************************
+A regular skin controller would point at a geometry we wanted to skin.  In this case we are 
+taking the output of a morph controller (which is geometry) and skinning that.
+*******************************************************************************************
+    	-->
+     <skin source="#pCylinderShape1-morph">
+       <!--
+*******************************************************************************************
+The bind shape matrix describes how to transform the pCylinderShape1-morph geometry into the
+right coordinate system for use with the joints.  In this case we do an +90 Y transform because
+the geometry was initially a 180 unit long cylinder with 0,0,0 at it's center.
+This moves it so 0,0,0 is at the base of the cylinder.
+*******************************************************************************************
+        -->
+       <bind_shape_matrix>
+         1 0 0 0
+         0 1 0 90 
+         0 0 1 0 
+         0 0 0 1
+       </bind_shape_matrix>
+       <!--
+*******************************************************************************************
+This source contains a list of the SIDs of the 7 joints that will influence the skin.  You
+can also use an IDREF_Array here but use of SIDs is prefered because they allow a controller
+to be used several times with different skeletons.  Applications MUST be able to import either
+IDREF_Array or Name_array tags.  And MUST search the correct namespace for the ID or SID
+*******************************************************************************************
+        -->
+       <source id="pCylinderShape1-morph-skin-joints">
+         <Name_array id="pCylinderShape1-morph-skin-joints-array" count="7">
+joint1 joint2 joint3 joint4 joint5 joint6 joint7</Name_array>
+         <technique_common>
+           <accessor source="#pCylinderShape1-morph-skin-joints-array" count="7" stride="1">
+             <param name="JOINT" type="Name"/>
+           </accessor>
+         </technique_common>
+       </source>
+       <!--
+*******************************************************************************************
+This source defines the inverse bind matrix for each joint, these are used to bring 
+coordinates being skinned into the same space as each joint.  Note that in this case the
+joints begin at 0,0,0 and move up 30 units for each joint, so the inverse bind matrices
+are the opposite of that.
+*******************************************************************************************
+        -->
+       <source id="pCylinderShape1-morph-skin-bind_poses">
+         <float_array id="pCylinderShape1-morph-skin-bind_poses-array" count="112">
+           1 0 0 0
+           0 1 0 0 
+           0 0 1 0 
+           0 0 0 1 
+
+           1 0 0 0 
+           0 1 0 -30 
+           0 0 1 0 
+           0 0 0 1 
+
+           1 0 0 0 
+           0 1 0 -60 
+           0 0 1 0 
+           0 0 0 1 
+
+           1 0 0 0 
+           0 1 0 -90 
+           0 0 1 0 
+           0 0 0 1 
+
+           1 0 0 0 
+           0 1 0 -120 
+           0 0 1 0 
+           0 0 0 1 
+
+           1 0 0 0 
+           0 1 0 -150 
+           0 0 1 0 
+           0 0 0 1 
+
+           1 0 0 0 
+           0 1 0 -180 
+           0 0 1 0 
+           0 0 0 1
+         </float_array>
+         <technique_common>
+           <accessor source="#pCylinderShape1-morph-skin-bind_poses-array" count="7" stride="16">
+             <param name="TRANSFORM" type="float4x4"/>
+           </accessor>
+         </technique_common>
+       </source>
+       <!--
+*******************************************************************************************
+This source defines a weight for each vertex and each joint.  The weight defines how much
+a particular joint will contribute to moving a particular vertex's position.  This allows
+several joints to influence vertices by different amounts, giving a nice smooth bend.
+
+Since there are 42 vertices and 7 joints there should be at most 294 weights.  In this case
+the skinning algorithm was told that each vertex should be effected by the 5 nearest joints
+so we have 5 weights per vertex giving a total of 210.  Maya has thrown in an extra weight
+of 1 at the beginning giving us a total of 211.
+
+Weights 1-6 will be applied to the first vertex, you can see how they work.  The first weight
+represents the closest joint to the vertex and has the largest value, the remaining 4 weights
+get smaller and smaller as the associated joint gets farther from the vertex.
+*******************************************************************************************
+        -->
+       <source id="pCylinderShape1-morph-skin-weights">
+         <float_array id="pCylinderShape1-morph-skin-weights-array" count="211">
+1 0.648726 0.265718 0.061417 0.01765 0.006487 0.648726 0.265718 0.061417 0.01765 0.006487
+0.648726 0.265718 0.061417 0.01765 0.006487 0.648726 0.265718 0.061417 0.01765 0.006487
+0.648726 0.265718 0.061417 0.01765 0.006487 0.648726 0.265718 0.061417 0.01765 0.006487
+0.395025 0.395025 0.161802 0.037398 0.010747 0.395025 0.395025 0.161802 0.037398 0.010747
+0.395025 0.395025 0.161802 0.037398 0.010747 0.395025 0.395025 0.161802 0.037398 0.010747
+0.395025 0.395025 0.161802 0.037398 0.010747 0.395025 0.395025 0.161802 0.037398 0.010747
+0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491
+0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491
+0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491
+0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569
+0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569
+0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569
+0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569 0.032491
+0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569
+0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569
+0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569
+0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569
+0.032491 0.140569 0.343186 0.343186 0.140569 0.032491 0.140569 0.343186 0.343186 0.140569
+0.010747 0.037398 0.161802 0.395025 0.395025 0.010747 0.037398 0.161802 0.395025 0.395025
+0.010747 0.037398 0.161802 0.395025 0.395025 0.010747 0.037398 0.161802 0.395025 0.395025
+0.010747 0.037398 0.161802 0.395025 0.395025 0.010747 0.037398 0.161802 0.395025 0.395025</float_array>
+         <technique_common>
+           <accessor source="#pCylinderShape1-morph-skin-weights-array" count="211" stride="1">
+             <param name="WEIGHT" type="float"/>
+           </accessor>
+         </technique_common>
+       </source>
+       <!--
+*******************************************************************************************
+The joints tag connects the source containing the name of each joint with the source 
+containing the inverse bind matrices for each joint.
+*******************************************************************************************
+        -->
+       <joints>
+         <input semantic="JOINT" source="#pCylinderShape1-morph-skin-joints"/>
+         <input semantic="INV_BIND_MATRIX" source="#pCylinderShape1-morph-skin-bind_poses"/>
+       </joints>
+       <!--
+*******************************************************************************************
+The vertex_weights tag associates the weights and joints from the previously defined
+sources with the vertices in the geometry being skinned.  Each entry in this list matches
+a vertex in the original geometry, so the count here should be the same as the count
+in the geometry being skinned.
+
+Each weight/joint pair is referred to as an "influence", a vertex can have any number of
+influences applied to it.  The <vcount> value for a vertex defines the number of influences 
+on that vertex.  In this case every vertex has 5 influences.  The values in the <v> array
+are the indices of the joint and weight that make up that influence.
+*******************************************************************************************
+       -->
+      <vertex_weights count="42">
+         <input semantic="JOINT" source="#pCylinderShape1-morph-skin-joints" offset="0"/>
+         <input semantic="WEIGHT" source="#pCylinderShape1-morph-skin-weights" offset="1"/>
+         <vcount>5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 </vcount>
+         <v>0 1 1 2 2 3 3 4 4 5 0 6 1 7 2 8 3 9 4 10 0 11 1 12 2 13 3 14 4 15 0 16 1
+17 2 18 3 19 4 20 0 21 1 22 2 23 3 24 4 25 0 26 1 27 2 28 3 29 4 30 0 31 1 32 2 33 3
+34 4 35 0 36 1 37 2 38 3 39 4 40 0 41 1 42 2 43 3 44 4 45 0 46 1 47 2 48 3 49 4 50 0
+51 1 52 2 53 3 54 4 55 0 56 1 57 2 58 3 59 4 60 0 61 1 62 2 63 3 64 4 65 0 66 1 67 2
+68 3 69 4 70 0 71 1 72 2 73 3 74 4 75 0 76 1 77 2 78 3 79 4 80 0 81 1 82 2 83 3 84 4
+85 0 86 1 87 2 88 3 89 4 90 0 91 1 92 2 93 3 94 4 95 0 96 1 97 2 98 3 99 4 100 0 101 1
+102 2 103 3 104 4 105 0 106 1 107 2 108 3 109 4 110 0 111 1 112 2 113 3 114 4 115 0
+116 1 117 2 118 3 119 4 120 2 121 3 122 4 123 5 124 6 125 2 126 3 127 4 128 5 129 6
+130 1 131 2 132 3 133 4 134 5 135 1 136 2 137 3 138 4 139 5 140 1 141 2 142 3 143 4
+144 5 145 1 146 2 147 3 148 4 149 5 150 2 151 3 152 4 153 5 154 6 155 2 156 3 157 4
+158 5 159 6 160 2 161 3 162 4 163 5 164 6 165 2 166 3 167 4 168 5 169 6 170 2 171 3
+172 4 173 5 174 6 175 2 176 3 177 4 178 5 179 6 180 2 181 3 182 4 183 5 184 6 185 2
+186 3 187 4 188 5 189 6 190 2 191 3 192 4 193 5 194 6 195 2 196 3 197 4 198 5 199 6
+200 2 201 3 202 4 203 5 204 6 205 2 206 3 207 4 208 5 209 6 210</v>
+       </vertex_weights>
+     </skin>
+   </controller>
+ </library_controllers>
+ <library_visual_scenes>
+   <visual_scene id="VisualSceneNode" name="untitled">
+     <!--
+*******************************************************************************************
+This is the node hierarchy that represents the skeleton of the skinned object.
+The first node has an ID to act as a starting point for SID searches, the rest
+of the nodes in the hierarchy only need SIDs.  It is preferable to use SIDs to
+identify the joints of the skeleton because it allows the skin controller to be
+used several times with different skeletons.  For example we could have a second
+joint hierarchy using the same SIDs but with a different id (like skeleton2_root)
+on the first node and different transforms.  
+
+In this example the root joint of the skeleton is 20 units above the ground.  
+All the other joints are 30 units apart in the Y direction.  A Z rotation has been
+added to some of the joints to cause the skinned/morphed cylinder to gradually bend so
+you can see the skinning effect.
+*******************************************************************************************
+      -->   
+     <node id="skeleton_root" name="joint1" sid="joint1" type="JOINT">
+       <translate sid="translate">0 20 0</translate>
+       <!-- 
+*******************************************************************************************
+Some people try to put the instance_controller here.  This will not work correctly for
+a skin because the skinning process has already transformed all the vertices using the
+full transform in the joints that the skin controller references. This means the data
+coming out of the instance_controller is effectively in world space.  If we put the 
+instance_controller here, the geometry coming out of it would be transformed (again) by 
+this node, moving it up an additional 20 units. 
+*******************************************************************************************
+        -->   
+       <node name="joint2" sid="joint2" type="JOINT">
+         <translate>0 30 0</translate>
+         <node name="joint3" sid="joint3" type="JOINT">
+           <translate>0 30 0</translate>
+           <rotate>0 0 1 17.972</rotate>
+           <node name="joint4" sid="joint4" type="JOINT">
+             <translate>0 30 0</translate>
+             <rotate>0 0 1 16.4036</rotate>
+             <node name="joint5" sid="joint5" type="JOINT">
+               <translate>0 30 0</translate>
+               <rotate>0 0 1 21.1126</rotate>
+               <node name="joint6" sid="joint6" type="JOINT">
+                 <translate>0 30 0</translate>
+                 <rotate>0 0 1 16.007</rotate>
+                 <node name="joint7" sid="joint7" type="JOINT">
+                   <translate>0 30 0</translate>
+                 </node>
+               </node>
+             </node>
+           </node>
+         </node>
+       </node>
+     </node>
+     <!--
+*******************************************************************************************
+This node is where the skinned/morphed geometry is instantiated.  The geometry that comes out
+of a skin controller has already been transformed by the joints referenced in the skin
+which puts the geometry in world space.  This is why we are instantiating the skin at
+the root of the hierarchy rather than up in the "skeleton_root" node
+*******************************************************************************************
+       --> 
+    <node id="pCylinder1" name="pCylinder1" type="NODE">
+       <instance_controller url="#pCylinderShape1-morph-skin">
+         <!--
+*******************************************************************************************
+The skeleton tag tells the controller where it should start searching for any SIDs found
+in the skin.  This allows the same controller to be re-used with different joint hierarchies.
+If the controller uses an IDREF_Array then the skeleton tag is not required because IDs are 
+global.
+*******************************************************************************************
+          -->
+         <skeleton>#skeleton_root</skeleton>
+         <bind_material>
+           <technique_common>
+             <instance_material symbol="lambert2SG" target="#lambert1"/>
+           </technique_common>
+         </bind_material>
+       </instance_controller>
+     </node>
+   </visual_scene>
+ </library_visual_scenes>
+ <scene>
+   <instance_visual_scene url="#VisualSceneNode"/>
+ </scene>
+</COLLADA>

+ 237 - 0
examples/webgl_collada.html

@@ -0,0 +1,237 @@
+<!DOCTYPE HTML>
+<html lang="en">
+	<head>
+		<title>three.js webgl - collada</title>
+		<meta charset="utf-8">
+		<style type="text/css">
+			body {
+				font-family: Monospace;
+				background-color: #ffffff;
+				margin: 0px;
+				overflow: hidden;
+			}
+			#log { color:#fff; position:absolute; top:50px; text-align:left; display:block; z-index:100; pointer-events:none; }
+		</style>
+	</head>
+	<body>
+		<pre id="log"></pre>
+
+		<script type="text/javascript" src="../build/Three.js"></script>
+
+		<script type="text/javascript" src="js/Detector.js"></script>
+		<script type="text/javascript" src="js/RequestAnimationFrame.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
+		<script type="text/javascript" src="../src/extras/collada/dae.js"></script>
+		
+		<script type="text/javascript">
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var container, stats;
+
+			var camera, scene, renderer, objects;
+			var particleLight, pointLight;
+			var dae;
+			
+			DAE.load('./models/monster.dae', colladaReady);
+			
+			function colladaReady(collada) {
+				dae = collada.scene;
+				dae.scale.x = dae.scale.y = dae.scale.z = 0.002;
+				dae.updateMatrix();
+
+				init();
+				animate();
+			}
+			
+			function init() {
+					
+				container = document.createElement('div');
+				document.body.appendChild(container);
+
+				camera = new THREE.Camera( 45, window.innerWidth / window.innerHeight, 1, 2000 );
+				camera.position.x = 2;
+				camera.position.y = 2;
+				camera.position.z = 3;
+
+				scene = new THREE.Scene();
+
+				// Grid
+
+				var line_material = new THREE.LineBasicMaterial( { color: 0x0, opacity: 0.2 } ),
+					geometry = new THREE.Geometry(),
+					floor = -0.04, step = 1, size = 14;
+
+				for ( var i = 0; i <= size / step * 2; i ++ ) {
+
+					geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( - size, floor, i * step - size ) ) );
+					geometry.vertices.push( new THREE.Vertex( new THREE.Vector3(   size, floor, i * step - size ) ) );
+
+					geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( i * step - size, floor, -size ) ) );
+					geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( i * step - size, floor,  size ) ) );
+
+				}
+
+				var line = new THREE.Line( geometry, line_material, THREE.LinePieces );
+				scene.addObject( line );
+
+				// Materials
+
+				var generatedTexture = new THREE.Texture( generateTexture() );
+				generatedTexture.needsUpdate = true;
+
+				var materials = [];
+				materials.push( new THREE.MeshLambertMaterial( { map: generatedTexture } ) );
+				materials.push( new THREE.MeshLambertMaterial( { color: 0xdddddd, shading: THREE.FlatShading } ) );
+				materials.push( new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0xdddddd, specular: 0x009900, shininess: 30, shading: THREE.FlatShading } ) );
+				materials.push( new THREE.MeshNormalMaterial( ) );
+				materials.push( new THREE.MeshBasicMaterial( { color: 0x665500, blending: THREE.AdditiveBlending } ) );
+				//materials.push( new THREE.MeshBasicMaterial( { color: 0xff0000, blending: THREE.SubtractiveBlending } ) );
+
+				materials.push( new THREE.MeshLambertMaterial( { color: 0xdddddd, shading: THREE.SmoothShading } ) );
+				materials.push( new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0xdddddd, specular: 0x009900, shininess: 30, shading: THREE.SmoothShading } ) );
+				materials.push( new THREE.MeshNormalMaterial( { shading: THREE.SmoothShading } ) );
+				materials.push( new THREE.MeshBasicMaterial( { color: 0xffaa00, wireframe: true } ) );
+
+				materials.push( new THREE.MeshDepthMaterial() );
+				materials.push( new THREE.MeshBasicMaterial( { map: generatedTexture } ) );
+
+				// Spheres geometry
+
+				var geometry_smooth = new THREE.SphereGeometry( 70, 32, 16 );
+				var geometry_flat = new THREE.SphereGeometry( 70, 32, 16 );
+				var geometry_pieces = new THREE.SphereGeometry( 70, 32, 16 ); // Extra geometry to be broken down for MeshFaceMaterial
+
+				for ( var i = 0, l = geometry_pieces.faces.length; i < l; i ++ ) {
+
+					var face = geometry_pieces.faces[ i ];
+					if ( Math.random() > 0.7 ) face.materials = [ materials[ Math.floor( Math.random() * materials.length )  ] ];
+
+				}
+
+				materials.push( new THREE.MeshFaceMaterial() );
+
+				objects = [];
+
+				var sphere, geometry, material;
+
+				for ( var i = 0, l = materials.length; i < l; i ++ ) {
+
+					material = materials[ i ];
+
+					geometry = material instanceof THREE.MeshFaceMaterial ? geometry_pieces :
+							   ( material.shading == THREE.FlatShading ? geometry_flat : geometry_smooth );
+
+					sphere = new THREE.Mesh( geometry, material );
+
+					sphere.position.x = ( i % 4 ) * 200 - 400;
+					sphere.position.z = Math.floor( i / 4 ) * 200 - 200;
+
+					sphere.rotation.x = Math.random() * 200 - 100;
+					sphere.rotation.y = Math.random() * 200 - 100;
+					sphere.rotation.z = Math.random() * 200 - 100;
+
+					objects.push( sphere );
+
+					//scene.addObject( sphere );
+
+				}
+				
+				//dae.rotation.x = -Math.PI/2;
+				scene.addObject(dae);
+				//var wall = dae_geometries['wall-geometry'][0];
+		
+				//var dae = new THREE.Mesh( wall, materials[3] );
+				//dae.scale.x = dae.scale.y = dae.scale.z = 100.0;				
+				//scene.addObject(dae);
+
+				particleLight = new THREE.Mesh( new THREE.SphereGeometry( 4, 8, 8 ), new THREE.MeshBasicMaterial( { color: 0xffffff } ) );
+				scene.addObject( particleLight );
+
+				// Lights
+
+				scene.addLight( new THREE.AmbientLight( 0x202020 ) );
+
+				var directionalLight = new THREE.DirectionalLight(/*Math.random() * 0xffffff*/0xcccccc);
+				directionalLight.position.x = Math.random() - 0.5;
+				directionalLight.position.y = Math.random() - 0.5;
+				directionalLight.position.z = Math.random() - 0.5;
+				directionalLight.position.normalize();
+				scene.addLight( directionalLight );
+
+				pointLight = new THREE.PointLight( 0xdddddd, 0.6 );
+				scene.addLight( pointLight );
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				container.appendChild( renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+			}
+
+			function generateTexture() {
+
+				var canvas = document.createElement( 'canvas' );
+				canvas.width = 256;
+				canvas.height = 256;
+
+				var context = canvas.getContext( '2d' );
+				var image = context.getImageData( 0, 0, 256, 256 );
+
+				var x = 0, y = 0;
+
+				for ( var i = 0, j = 0, l = image.data.length; i < l; i += 4, j ++ ) {
+
+					x = j % 256;
+					y = x == 0 ? y + 1 : y;
+
+					image.data[ i + 2 ] = Math.floor( x ^ y );
+					image.data[ i + 3 ] = 255;
+
+				}
+
+				context.putImageData( image, 0, 0 );
+
+				return canvas;
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+
+				var timer = new Date().getTime() * 0.0005;
+
+				camera.position.x = Math.cos( timer ) * 10;
+				camera.position.y = 2;
+				camera.position.z = Math.sin( timer ) * 10;
+
+				particleLight.position.x = Math.sin( timer * 4 ) * 300;
+				particleLight.position.y = Math.cos( timer * 5 ) * 400;
+				particleLight.position.z = Math.cos( timer * 4 ) * 300;
+
+				pointLight.position.x = particleLight.position.x;
+				pointLight.position.y = particleLight.position.y;
+				pointLight.position.z = particleLight.position.z;
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 1688 - 0
src/extras/collada/dae.js

@@ -0,0 +1,1688 @@
+/**
+ * @author Tim Knip / http://www.floorplanner.com/ / tim at floorplanner.com
+ */
+
+var DAE = (function() {
+	var COLLADA = null;
+	var scene = null;
+	var daeScene;
+ 	var sources = {};
+	var images = {};
+	var animations = {};
+	var controllers = {};
+	var geometries = {};
+	var materials = {};
+	var effects = {};
+	var visualScenes;
+	var readyCallbackFunc = null;
+	var baseUrl;
+	
+	function load(url, readyCallback) {
+		if (document.implementation && document.implementation.createDocument) {
+			var namespaceURL = "http://www.collada.org/2005/11/COLLADASchema";
+			var rootTagName = "COLLADA";
+
+			var xmldoc = document.implementation.createDocument(namespaceURL, rootTagName, null);
+			var me = this;
+			url += "?rnd=" + Math.random();
+
+			var req = new XMLHttpRequest();
+
+			if(req.overrideMimeType) {
+				// need this? yes... if extension is other then *.xml :-S
+				req.overrideMimeType("text/xml");
+			}
+
+			req.onreadystatechange = function() {
+				if(req.readyState == 4) {
+					if(req.status == 0 || req.status == 200) {
+						
+						readyCallbackFunc = readyCallback;
+						parse(req.responseXML, undefined, url);
+					}
+				}
+			}
+			req.open("GET", url, true); 
+			req.send(null);
+		} else {
+			alert("Don't know how to parse XML!");
+		}
+	}
+	
+	function parse(doc, callBack, url) {
+		COLLADA = doc;
+		callBack = callBack || readyCallbackFunc;
+		if (url !== undefined) {
+			var parts = url.split('/');
+			parts.pop();
+			baseUrl = parts.join('/') + '/';
+		}
+		images = parseLib("//dae:library_images/dae:image", _Image, "image");
+		materials = parseLib("//dae:library_materials/dae:material", Material, "material");
+		effects = parseLib("//dae:library_effects/dae:effect", Effect, "effect");
+		geometries = parseLib("//dae:library_geometries/dae:geometry", Geometry, "geometry");
+		controllers = parseLib("//dae:library_controllers/dae:controller", Controller, "controller");
+		animations = parseLib("//dae:library_animations/dae:animation", Animation, "animation");
+		visualScenes = parseLib(".//dae:library_visual_scenes/dae:visual_scene", VisualScene, "visual_scene");
+		
+		daeScene = parseScene();
+		scene = new THREE.Object3D();
+		for (var i = 0; i < daeScene.nodes.length; i++) {
+			scene.addChild(createSceneGraph(daeScene.nodes[i]));
+		}
+
+		createAnimations();
+
+		var result = {
+			scene: scene, 
+			dae: {
+				images: images,
+				materials: materials,
+				effects: effects,
+				geometries: geometries,
+				controllers: controllers,
+				animations: animations,
+				visualScenes: visualScenes,
+				scene: daeScene
+			}
+		};
+		
+		if (callBack) {
+			callBack(result);
+		}
+		return result;
+	}
+	
+	function parseLib(q, classSpec, prefix) {
+		var elements = COLLADA.evaluate(q, 
+			COLLADA, 
+			_nsResolver, 
+			XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
+			null);
+		var lib = {};
+		var element = elements.iterateNext();
+		var i = 0;
+		while (element) {
+			var daeElement = (new classSpec()).parse(element);
+			if (daeElement.id.length == 0) daeElement.id = prefix + (i++); 
+			lib[daeElement.id] = daeElement;
+			element = elements.iterateNext();
+		}
+		return lib;
+	}
+	
+	function parseScene() {
+		var sceneElement = COLLADA.evaluate(".//dae:scene/dae:instance_visual_scene", 
+			COLLADA, 
+			_nsResolver, 
+			XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
+			null).iterateNext();
+		
+		
+		if (sceneElement) {
+			var url = sceneElement.getAttribute('url').replace(/^#/, '');
+			return visualScenes[url];
+		} else {
+			return null;
+		}
+	}
+	
+	function createAnimations() {
+		for (animation_id in animations) {
+			createAnimation(animations[animation_id]);
+		}
+	}
+	
+	function createAnimation(animation) {
+		
+		for (var i = 0; i < animation.channel.length; i++) {
+			var channel = animation.channel[i];
+			var sampler = animation.sampler[i];
+			
+			var parts = channel.target.split("/");
+			var id = parts.shift();
+			var node = daeScene.getChildById(id, true);
+			var object = scene.getChildByName(id, true);
+			
+			if (!node || !object) {
+				console.error("Dae::createAnimation : could not find node with id=" + id);
+				continue;
+			}
+			
+			if (parts.length > 1) {
+				console.log("Dae::createAnimation : can only handle simple paths [" + channel.target + "]");
+				continue;
+			}
+			var sid = parts.shift();
+			var dotSyntax = (sid.indexOf(".") >= 0);
+			var arrSyntax = (sid.indexOf("(") >= 0);
+			var arrIndices;
+			var member;
+			
+			if (dotSyntax) {
+				parts = sid.split(".");
+				sid = parts.shift();
+				member = parts.shift();
+			} else if (arrSyntax) {
+				arrIndices = sid.split("(");
+				sid = arrIndices.shift();
+				for (var j = 0; j < arrIndices.length; j++) {
+					arrIndices[j] = parseInt(arrIndices[j].replace(/\)/, ''));
+				}
+			}
+			var transform = node.getTransformBySid(sid);
+			
+			sampler.create();
+			switch (transform.type) {
+				case 'matrix':
+					//console.log(sampler.output[0]);
+					break;
+				default:
+					break;
+			}
+		}
+	}
+	
+	function createSceneGraph(node) {
+		var obj = new THREE.Object3D();
+		var skinned = false;
+		var i;
+		
+		obj.name = node.id || "";
+		obj.matrixAutoUpdate = false;
+		obj.matrix = node.matrix;
+
+		// FIXME: controllers
+		for (i =0; i < node.controllers.length; i++) {
+			var controller = controllers[node.controllers[i].url];
+			switch (controller.type) {
+				case 'skin':
+					if (geometries[controller.skin.source]) {
+						var inst_geom = new InstanceGeometry();
+						inst_geom.url = controller.skin.source;
+						inst_geom.instance_material = node.controllers[i].instance_material;
+						node.geometries.push(inst_geom);
+						skinned = true;
+					} else if (controllers[controller.skin.source]) {
+						var second = controllers[controller.skin.source];
+						if (second.morph && geometries[second.morph.source]) {
+							var inst_geom = new InstanceGeometry();
+							inst_geom.url = second.morph.source;
+							inst_geom.instance_material = node.controllers[i].instance_material;
+							node.geometries.push(inst_geom);
+						}
+					}
+					break;
+				case 'morph': // unsupported
+					if (geometries[controller.morph.source]) {
+						var inst_geom = new InstanceGeometry();
+						inst_geom.url = controller.morph.source;
+						inst_geom.instance_material = node.controllers[i].instance_material;
+						node.geometries.push(inst_geom);
+					}
+					console.log("DAE: morph-controller partially supported.")
+				default:
+					break;
+			}
+		}
+		
+		// geometries
+		for (i = 0; i < node.geometries.length; i++) {
+			var instance_geometry = node.geometries[i];
+			var instance_materials = instance_geometry.instance_material;
+			var geometry = geometries[instance_geometry.url];
+			var shaders = {};
+			
+			// collect materials for this geometry instance
+			if (instance_materials) {
+				for (j = 0; j < instance_materials.length; j++) {
+					var inst_material = instance_materials[j];
+					var target = inst_material.target;
+					var symbol = inst_material.symbol;
+					var effect_id = materials[target].instance_effect.url;
+					var effect = effects[effect_id];
+					shaders[symbol] = effect;
+				}
+			}
+
+			if (geometry) {
+				if (!geometry.mesh || !geometry.mesh.primitives)
+					continue;
+					
+				if (obj.name.length == 0) {
+					obj.name = geometry.id;
+				}
+				
+				var primitives = geometry.mesh.primitives;
+				for (j = 0; j < primitives.length; j++) {
+					var symbol = primitives[j].material;
+					var effect = shaders[symbol];
+					var shader = effect.shader;
+					var ambient = shader.ambient ? shader.ambient.color : 0x505050;
+					var diffuse = shader.diffuse ? shader.diffuse.color : 0xff0000;
+					var specular = shader.specular ? shader.specular.color : null;
+					var transparency = shader.transparency;
+					var use_transparency = (transparency !== undefined && transparency < 1.0);
+					var opacity = use_transparency ? transparency : 1.0;
+					var texture;
+					
+					if (shader.diffuse && shader.diffuse.isTexture() && effect.sampler && effect.surface) {
+						if (effect.sampler.source == effect.surface.sid) {
+							var image = images[effect.surface.init_from];
+							if (image) {
+								texture = THREE.ImageUtils.loadTexture(baseUrl + image.init_from);
+							}
+						}
+					}
+					var mat = new THREE.MeshLambertMaterial( { 
+						map: texture,
+						color: diffuse.getHex(), 
+						opacity: opacity, 
+						transparent: use_transparency,
+						shading: THREE.SmoothShading } );
+					
+					if (shader.type != 'lambert' && shader.shininess && specular && ambient) {
+						mat = new THREE.MeshPhongMaterial( { 
+							map: texture,
+							ambient: ambient.getHex(), 
+							color: diffuse.getHex(), 
+							specular: specular.getHex(), 
+							shininess: shader.shininess, 
+							shading: THREE.SmoothShading,
+							opacity: opacity,
+							transparent: use_transparency } )
+					}
+					if (Math.abs(primitives[j].geometry.boundingBox.z[0]) < 0.01) {
+						obj.matrix.n34 += Math.random() * 0.001;
+					}
+					if (skinned) {
+						obj.addChild(new THREE.SkinnedMesh( primitives[j].geometry, mat ));
+					} else {
+						obj.addChild(new THREE.Mesh( primitives[j].geometry, mat ));
+					}
+				}
+			}
+		}
+		
+		for (i = 0; i < node.nodes.length; i++) {
+			obj.addChild(createSceneGraph(node.nodes[i]));
+		}
+		
+		return obj;
+	}
+	
+	function getLibraryNode(id) {
+		return COLLADA.evaluate(".//dae:library_nodes//dae:node[@id='"+id+"']", 
+			COLLADA, 
+			_nsResolver, 
+			XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
+			null).iterateNext();
+	}
+	
+	function _Image() {
+		this.id = "";
+		this.init_from = "";
+	}
+	_Image.prototype.parse = function(element) {
+		this.id = element.getAttribute('id');
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeName == 'init_from') {
+				this.init_from = child.textContent;
+			}
+		}
+		return this;
+	}
+	
+	function Controller() {
+		this.id = "";
+		this.name = "";
+		this.type = "";
+		this.skin = null;
+		this.morph = null;
+	}
+	Controller.prototype.parse = function(element) {
+		this.id = element.getAttribute('id');
+		this.name = element.getAttribute('name');
+		this.type = "none";
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			switch (child.nodeName) {
+				case 'skin':
+					this.skin = (new Skin()).parse(child);
+					this.type = child.nodeName;
+					break;
+				case 'morph':
+					this.morph = (new Morph()).parse(child);
+					this.type = child.nodeName;
+					break;
+				default:
+					break;
+			}
+		}
+		return this;
+	}
+	function Morph() {
+		this.method;
+		this.source;
+		this.targets;
+		this.weights;
+	}
+	Morph.prototype.parse = function(element) {
+		var sources = {};
+		var inputs = [];
+		var i;
+		this.method = element.getAttribute('method');
+		this.source = element.getAttribute('source').replace(/^#/, '');
+		for (i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'source':
+					var source = (new Source()).parse(child);
+					sources[source.id] = source;
+					break;
+				case 'targets':
+					inputs = this.parseInputs(child);
+					break;
+				default:
+					console.log(child.nodeName);
+					break;
+			}
+		}
+		for (i = 0; i < inputs.length; i++) {
+			var input = inputs[i];
+			var source = sources[input.source];
+			switch (input.semantic) {
+				case 'MORPH_TARGET':
+					this.targets = source.read();
+					break;
+				case 'MORPH_WEIGHT':
+					this.weights = source.read();
+					break;
+				default:
+					break;
+			}
+		}
+		return this;
+	}
+	Morph.prototype.parseInputs = function(element) {
+		var inputs = [];
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'input':
+					inputs.push((new Input()).parse(child));
+					break;
+				default:
+					break;
+			}
+		}
+		return inputs;
+	}
+	
+	function Skin() {
+		this.source = "";
+		this.bindShapeMatrix = null;
+		this.invBindMatrices = [];
+		this.joints = [];
+		this.weights = [];
+	}
+	Skin.prototype.parse = function(element) {
+		var sources = {};
+		var joints, weights;
+		this.source = element.getAttribute('source').replace(/^#/, '');
+		this.invBindMatrices = [];
+		this.joints = [];
+		this.weights = [];
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'bind_shape_matrix':
+					this.bindShapeMatrix = new THREE.Matrix4(_floats(child.textContent));
+					break;
+				case 'source':
+					var src = new Source().parse(child);
+					sources[src.id] = src;
+					break;
+				case 'joints':
+					joints = child;
+					break;
+				case 'vertex_weights':
+					weights = child;
+					break;
+				default:
+					console.log(child.nodeName);
+					break;
+			}
+		}
+		this.parseJoints(joints, sources);
+		this.parseWeights(weights, sources);
+		return this;
+	}
+	Skin.prototype.parseJoints = function(element, sources) {
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'input':
+					var input = (new Input()).parse(child);
+					var source = sources[input.source];
+					if (input.semantic == 'JOINT') {
+						this.joints = source.read();
+					} else if (input.semantic == 'INV_BIND_MATRIX') {
+						this.invBindMatrices = source.read();
+					}
+					break;
+				default:
+					break;
+			}
+		}
+	}
+	Skin.prototype.parseWeights = function(element, sources) {
+		var v, vcount, inputs = [];
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'input':
+					inputs.push((new Input()).parse(child));
+					break;
+				case 'v':
+					v = _ints(child.textContent);
+					break;
+				case 'vcount':
+					vcount = _ints(child.textContent);
+					break;
+				default:
+					break;
+			}
+		}
+		var index = 0;
+		
+		for (var i = 0; i < vcount.length; i++) {
+			var numBones = vcount[i];
+			var vertex_weights = [];
+			for (var j = 0; j < numBones; j++) {
+				var influence = {};
+				for (var k = 0; k < inputs.length; k++) {
+					var input = inputs[k];
+					var value = v[index + input.offset];
+					switch (input.semantic) {
+						case 'JOINT':
+							influence.joint = this.joints[value];
+							break;
+						case 'WEIGHT':
+							influence.weight = sources[input.source].data[value];
+							break;
+						default:
+							break;
+					}
+				}
+				vertex_weights.push(influence);
+				index += inputs.length;
+			}
+			this.weights.push(vertex_weights);
+		}
+	}
+	
+	function VisualScene() {
+		this.id = "";
+		this.name = "";
+		this.nodes = [];
+		this.scene = new THREE.Object3D();
+	}
+	VisualScene.prototype.getChildById = function(id, recursive) {
+		for (var i = 0; i < this.nodes.length; i++) {
+			var node = this.nodes[i].getChildById(id, recursive);
+			if (node) {
+				return node;
+			}
+		}
+		return null;
+	}
+	VisualScene.prototype.parse = function(element) {
+		this.id = element.getAttribute('id');
+		this.name = element.getAttribute('name');
+		this.nodes = [];
+		
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'node':
+					this.nodes.push((new Node()).parse(child));
+					break;
+				default:
+					break;
+			}
+		}
+		
+		return this;
+	}
+	
+	function Node() {
+		this.id = "";
+		this.name = "";
+		this.sid = "";
+		this.nodes = [];
+		this.controllers = [];
+		this.transforms = [];
+		this.geometries = [];
+		this.matrix = new THREE.Matrix4();
+	}
+	Node.prototype.getChildById = function(id, recursive) {
+		if (this.id == id) {
+			return this;
+		}
+		if (recursive) {
+			for (var i = 0; i < this.nodes.length; i++) {
+				var n = this.nodes[i].getChildById(id, recursive);
+				if (n) {
+					return n;
+				}
+			}
+		}
+		return null;
+	}
+	Node.prototype.getTransformBySid = function(sid) {
+		for (var i = 0; i < this.transforms.length; i++) {
+			if (this.transforms[i].sid == sid) return this.transforms[i];
+		}
+		return null;
+	}
+	Node.prototype.parse = function(element) {
+		var url;
+		
+		this.id = element.getAttribute('id');
+		this.sid = element.getAttribute('sid');
+		this.name = element.getAttribute('name');
+		this.type = element.getAttribute('type');
+		this.type = this.type == 'JOINT' ? this.type : 'NODE';
+		this.nodes = [];
+		this.transforms = [];
+		this.geometries = [];
+		this.controllers = [];
+		this.matrix = new THREE.Matrix4();
+
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'node':
+					this.nodes.push((new Node()).parse(child));
+					break;
+				case 'instance_camera':
+					break;
+				case 'instance_controller':
+					this.controllers.push((new InstanceController()).parse(child));
+					break;
+				case 'instance_geometry':
+					this.geometries.push((new InstanceGeometry()).parse(child));
+					break;
+				case 'instance_light':
+					break;
+				case 'instance_node':
+					url = child.getAttribute('url').replace(/^#/, '');
+					var iNode = getLibraryNode(url);
+					if (iNode) {
+						this.nodes.push((new Node()).parse(iNode));
+					}
+					break;
+				case 'rotate':
+				case 'translate':
+				case 'scale':
+				case 'matrix':
+				case 'lookat':
+				case 'skew':
+					this.transforms.push((new Transform()).parse(child));
+					break;
+				case 'extra':
+					break;
+				default:
+					console.log(child.nodeName);
+					break;
+			}
+		}
+		this.updateMatrix();
+		return this;
+	}
+	Node.prototype.updateMatrix = function() {
+		this.matrix.identity();
+		for (var i = 0; i < this.transforms.length; i++) {
+			this.matrix.multiply(this.matrix, this.transforms[i].matrix);
+		}
+	}
+	function Transform() {
+		this.sid = "";
+		this.type = "";
+		this.data = [];
+		this.matrix = new THREE.Matrix4();
+	}
+	Transform.prototype.parse = function(element) {
+		this.sid = element.getAttribute('sid');
+		this.type = element.nodeName;
+		this.data = _floats(element.textContent);
+		this.updateMatrix();
+		return this;
+	}
+	Transform.prototype.updateMatrix = function() {
+		var angle = 0;
+		
+		this.matrix.identity();
+		
+		switch (this.type) {
+			case 'matrix':
+				this.matrix.set(
+					this.data[0], this.data[1], this.data[2], this.data[3],
+					this.data[4], this.data[5], this.data[6], this.data[7],
+					this.data[8], this.data[9], this.data[10], this.data[11],
+					this.data[12], this.data[13], this.data[14], this.data[15]
+					);
+				break;
+			case 'translate':
+				this.matrix.setTranslation(this.data[0], this.data[1], this.data[2]);
+				break;
+			case 'rotate':
+				angle = this.data[3] * (Math.PI / 180.0);
+				this.matrix.setRotationAxis(new THREE.Vector3(this.data[0], this.data[1], this.data[2]), angle);
+				break;
+			case 'scale':
+				this.matrix.setScale(this.data[0], this.data[1], this.data[2]);
+				break;
+			default:
+				break;
+		}
+		return this.matrix;
+	}
+
+	function InstanceController() {
+		this.url = "";
+		this.skeleton = [];
+		this.instance_material = [];
+	}
+	InstanceController.prototype.parse = function(element) {
+		this.url = element.getAttribute('url').replace(/^#/, '');
+		this.skeleton = [];
+		this.instance_material = [];
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			
+			switch (child.nodeName) {
+				case 'skeleton':
+					this.skeleton.push(child.textContent.replace(/^#/, ''));
+					break;
+				case 'bind_material':
+					var instances = COLLADA.evaluate(".//dae:instance_material", 
+						child, 
+						_nsResolver, 
+						XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
+						null);
+					if (instances) {
+						var instance = instances.iterateNext();
+						while (instance) {
+							this.instance_material.push((new InstanceMaterial()).parse(instance));
+							instance = instances.iterateNext();	
+						}
+					}
+					break;
+				case 'extra':
+					break;
+				default:
+					break;
+			}
+		}
+		return this;
+	}
+		
+	function InstanceMaterial() {
+		this.symbol = "";
+		this.target = "";
+	}
+	InstanceMaterial.prototype.parse = function(element) {
+		this.symbol = element.getAttribute('symbol');
+		this.target = element.getAttribute('target').replace(/^#/, '');
+		return this;
+	}
+	
+	function InstanceGeometry() {
+		this.url = "";
+		this.instance_material = [];
+	}
+	InstanceGeometry.prototype.parse = function(element) {
+		this.url = element.getAttribute('url').replace(/^#/, '');
+		this.instance_material = [];
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			if (child.nodeName == 'bind_material') {
+				var instances = COLLADA.evaluate(".//dae:instance_material", 
+					child, 
+					_nsResolver, 
+					XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
+					null);
+				if (instances) {
+					var instance = instances.iterateNext();
+					while (instance) {
+						this.instance_material.push((new InstanceMaterial()).parse(instance));
+						instance = instances.iterateNext();	
+					}
+				}
+				break;
+			}
+		}
+		return this;
+	}
+	
+	function Geometry() {
+		this.id = "";
+		this.mesh = null;
+	}
+	Geometry.prototype.parse = function(element) {
+		this.id = element.getAttribute('id');
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			switch (child.nodeName) {
+				case 'mesh':
+					this.mesh = (new Mesh(this)).parse(child);
+					break;
+				default:
+					break;
+			}
+		}
+		return this;
+	}
+	
+	function Mesh(geometry) {
+		this.geometry = geometry.id;
+		this.primitives = [];
+		this.vertices = null;
+	}
+	Mesh.prototype.parse = function(element) {
+		this.primitives = [];
+		var i;
+		for (i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			switch (child.nodeName) {
+				case 'source':
+					_source(child);
+					break;
+				case 'vertices':
+					this.vertices = (new Vertices()).parse(child);
+					break;
+				case 'triangles':
+					this.primitives.push((new Triangles().parse(child)));
+					break;
+				case 'polygons':
+					console.warn('polygon holes not yet supported!');
+				case 'polylist':
+					this.primitives.push((new Polylist().parse(child)));
+					break;
+				default:
+					break;
+			}
+		}
+		for (i = 0; i < this.primitives.length; i++) {
+			primitive = this.primitives[i];
+			primitive.setVertices(this.vertices);
+			primitive.create();
+		}
+		return this;
+	}
+	
+	function Polylist() {
+	}
+	Polylist.prototype = new Triangles();
+	Polylist.prototype.constructor = Polylist;
+	Polylist.prototype.create = function() {
+		var p = this.p, inputs = this.inputs, num_inputs = this.inputs.length;
+		var idx = 0, input;
+		var i, j, k, v, n, t;
+		var texture_sets = [];
+		var polygons = [];
+		
+		for (j = 0; j < inputs.length; j++) {
+			input = inputs[j];
+			if (input.semantic == 'TEXCOORD') {
+				texture_sets.push(input.set);
+			}
+		}
+		
+		for (i = 0; i < this.vcount.length; i++) {
+			var num_verts = this.vcount[i]
+			var vs = [], ns = [], ts = [];
+			for (j = 0; j < num_verts; j++) {
+				for (k = 0; k < num_inputs; k++) {
+					input = inputs[k];
+					source = sources[input.source];
+					index = p[idx + input.offset];
+					numParams = source.accessor.params.length;
+					idx32 = index * numParams;
+					switch (input.semantic) {
+						case 'VERTEX':
+							v = new THREE.Vertex(new THREE.Vector3(source.data[idx32+0], source.data[idx32+1], source.data[idx32+2]));
+							v.daeId = vs.length;
+							vs.push(v);
+							break;
+						case 'NORMAL':
+							n = new THREE.Vector3(source.data[idx32+0], source.data[idx32+1], source.data[idx32+2]);
+							n.daeId = ns.length;
+							ns.push(n);
+							break;
+						case 'TEXCOORD':
+							if (ts[input.set] == undefined) ts[input.set] = [];
+							t = new THREE.UV(source.data[idx32+0], source.data[idx32+1]);
+							t.daeId = ts[input.set].length;
+							ts[input.set].push(t);
+							break;
+						default:
+							break;
+					}
+				}
+				idx += num_inputs;
+			}
+			polygons.push([vs, ns, ts])
+		}
+		
+		this.geometry = new THREE.Geometry();
+		this.triangulate(polygons, texture_sets);
+	}
+	Polylist.prototype.triangulate = function(polygons, texture_sets) {
+		var i, j, k;
+		
+		function clone(v) {
+			var x = v.position.x;
+			var y = v.position.y;
+			var z = v.position.z;
+			return new THREE.Vertex(new THREE.Vector3(x, y, z));
+		}
+		for (i = 0; i < polygons.length; i++) {
+			var polygon = polygons[i];
+			var v = polygon[0];
+			var n = polygon[1];
+			var t = polygon[2];
+			var uvs = [];
+			for (j = 0; j < texture_sets.length; j++) {
+				uvs.push(t[texture_sets[j]]);
+			}
+			var has_uv = (uvs.length > 0 && uvs[0].length > 0);
+			if (v.length < 3) continue;
+			var va = v[0];
+			var na = n[0];
+			for (j = 1; j < v.length - 1; j++) {
+				var vb = v[j];
+				var vc = v[j+1];
+				var nb = n[j];
+				var nc = n[j+1];
+
+				var c = this.geometry.vertices.length;
+				this.geometry.vertices.push(va, vb, vc);
+				this.geometry.faces.push( new THREE.Face3(c+0, c+1, c+2, [na, nb, nc] ) );
+				if (has_uv) {
+					for (k = 0; k < uvs.length; k++) {
+						this.geometry.faceVertexUvs[ k ].push( [uvs[k][0], uvs[k][j], uvs[k][j+1]] );
+					}
+				}
+			}
+		}
+		this.geometry.material = this.material;
+		this.geometry.computeCentroids();
+		this.geometry.computeFaceNormals();
+		this.geometry.computeVertexNormals();
+		this.geometry.computeBoundingBox();
+	}
+	
+	function Triangles() {
+		this.material = "";
+		this.count = 0;
+		this.inputs = [];
+		this.vcount;
+		this.p = [];
+		this.aabb = new AABB();
+		this.geometry = new THREE.Geometry();
+	}
+	Triangles.prototype.create = function() {
+		var i = 0, j, k, p = this.p, inputs = this.inputs, input, index;
+		var v, n, t;
+		var texture_sets = [];
+		
+		for (j = 0; j < inputs.length; j++) {
+			input = inputs[j];
+			if (input.semantic == 'TEXCOORD') {
+				texture_sets.push(input.set);
+			}
+		}
+		
+		this.geometry = new THREE.Geometry();
+
+		while (i < p.length) {
+			vs = [];
+			ns = [];
+			ts = {};
+			for (j = 0; j < 3; j++) {
+				for (k = 0; k < inputs.length; k++) {
+					input = inputs[k];
+					source = sources[input.source];
+					index = p[i + (j*inputs.length) + input.offset];
+					numParams = source.accessor.params.length;
+					idx32 = index * numParams;
+					switch (input.semantic) {
+						case 'VERTEX':
+							v = new THREE.Vertex(new THREE.Vector3(source.data[idx32+0], source.data[idx32+1], source.data[idx32+2]));
+							v.daeId = vs.length;
+							vs.push(v);
+							
+							break;
+						case 'NORMAL':
+							n = new THREE.Vector3(source.data[idx32+0], source.data[idx32+1], source.data[idx32+2]);
+							n.daeId = ns.length;
+							ns.push(n);
+							break;
+						case 'TEXCOORD':
+							if (ts[input.set] == undefined) ts[input.set] = [];
+							t = new THREE.UV(source.data[idx32+0], source.data[idx32+1]);
+							t.daeId = ts[input.set].length;
+							ts[input.set].push(t);
+							break;
+						default:
+							break;
+					}
+				}
+			}
+			var has_v = (vs.length == 3);
+			var has_t = (texture_sets.length > 0 && ts[texture_sets[0]].length == 3);
+			if (has_v) {
+				var c = this.geometry.vertices.length;
+				this.geometry.vertices.push(vs[0], vs[1], vs[2]);
+				
+				this.geometry.faces.push( new THREE.Face3(c+0, c+1, c+2, ns ) );
+				if (has_t) {
+					for (k = 0; k < texture_sets.length; k++) {
+						this.geometry.faceVertexUvs[ k ].push( ts[texture_sets[k]] );
+					}
+				}
+			}
+			i += 3 * inputs.length;
+		}
+		this.geometry.material = this.material;
+		this.geometry.computeCentroids();
+		this.geometry.computeFaceNormals();
+		this.geometry.computeVertexNormals();
+		this.geometry.computeBoundingBox();	
+	}
+	Triangles.prototype.setVertices = function(vertices) {
+		for (var i = 0; i < this.inputs.length; i++) {
+			if (this.inputs[i].source == vertices.id) {
+				this.inputs[i].source = vertices.input['POSITION'].source;
+			}
+		}
+	}
+	Triangles.prototype.parse = function(element) {
+		this.inputs = [];
+		this.material = element.getAttribute('material');
+		this.count = _attr_as_int(element, 'count', 0);
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			switch (child.nodeName) {
+				case 'input':
+					this.inputs.push((new Input()).parse(element.childNodes[i]));
+					break;
+				case 'vcount':
+					this.vcount = _ints(child.textContent);
+					break;
+				case 'p':
+					this.p = _ints(child.textContent);
+					break;
+				default:
+					break;
+			}
+		}
+		return this;
+	}
+	Triangles.prototype.calcNormals = function(v, n) {
+		var i;
+		var v0 = [0, 0, 0];
+		var v1 = [0, 0, 0];
+		var v2 = [0, 0, 0];
+		var n0 = [0, 0, 0];
+		for (i = 0; i < v.length; i += 9) {
+			v0[0] = v[i+0]; v0[1] = v[i+1]; v0[2] = v[i+2];
+			v1[0] = v[i+3]; v1[1] = v[i+4]; v1[2] = v[i+5];
+			v2[0] = v[i+6]; v2[1] = v[i+7]; v2[2] = v[i+8];
+			// sub
+			v1[0] = v1[0] - v0[0];
+			v1[1] = v1[1] - v0[1];
+			v1[2] = v1[2] - v0[2];
+			v2[0] = v2[0] - v0[0];
+			v2[1] = v2[1] - v0[1];
+			v2[2] = v2[2] - v0[2];
+			// cross
+			n0[0] = v1[1] * v2[2] - v1[2] * v2[1];
+			n0[1] = v1[2] * v2[0] - v1[0] * v2[2];
+			n0[2] = v1[0] * v2[1] - v1[1] * v2[0];
+			// normalize
+			length = 1.0 / Math.sqrt(n0[0]*n0[0]+n0[1]*n0[1]+n0[2]*n0[2]);
+			if (length == 0) length = 1.0;
+			n[i+0] = n[i+3] = n[i+6] = n0[0] * length;
+			n[i+1] = n[i+4] = n[i+7] = n0[1] * length;
+			n[i+2] = n[i+5] = n[i+8] = n0[2] * length;
+		}
+	}
+	
+	function AABB() {
+		this.minx = 0;	this.miny = 0;	this.minz = 0;
+		this.maxx = 0;	this.maxy = 0;	this.maxz = 0;
+	}
+	AABB.prototype.reset = function() {
+		this.minx = this.miny = this.minz = Number.MAX_VALUE;
+		this.maxx = this.maxy = this.maxz = Number.MIN_VALUE;
+		return this;
+	}
+	AABB.prototype.setTriangles = function(positions) {
+		this.reset();
+		for (var i = 0; i < positions.length; i += 3) {
+			this.minx = Math.min(this.minx, positions[i+0]); 
+			this.miny = Math.min(this.miny, positions[i+1]);
+			this.minz = Math.min(this.minz, positions[i+2]);
+			this.maxx = Math.max(this.maxx, positions[i+0]);
+			this.maxy = Math.max(this.maxy, positions[i+1]);
+			this.maxz = Math.max(this.maxz, positions[i+2]);
+		}
+		return this;
+	}
+	AABB.prototype.centerX = function() { return this.minx + (this.sizeX() / 2); }
+	AABB.prototype.centerY = function() { return this.miny + (this.sizeY() / 2); }
+	AABB.prototype.centerZ = function() { return this.minz + (this.sizeZ() / 2); }
+	AABB.prototype.sizeX = function() { return this.maxx - this.minx; }
+	AABB.prototype.sizeY = function() { return this.maxy - this.miny; }
+	AABB.prototype.sizeZ = function() { return this.maxz - this.minz; }
+	
+	function Accessor() {
+		this.source = "";
+		this.count = 0;
+		this.stride = 0;
+		this.params = [];
+	}
+	Accessor.prototype.parse = function(element) {
+		this.params = [];
+		this.source = element.getAttribute('source');
+		this.count = _attr_as_int(element, 'count', 0);
+		this.stride = _attr_as_int(element, 'stride', 0);
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeName == 'param') {
+				var param = {};
+				param['name'] = child.getAttribute('name');
+				param['type'] = child.getAttribute('type');
+				this.params.push(param);
+			}
+		}
+		return this;
+	}
+	
+	function Vertices() {
+		this.input = {};
+	}
+	Vertices.prototype.parse = function(element) {
+		this.id = element.getAttribute('id');
+		for (var i = 0; i < element.childNodes.length; i++) {
+			if (element.childNodes[i].nodeName == 'input') {
+				input = (new Input()).parse(element.childNodes[i]);
+				this.input[input.semantic] = input;
+			}
+		}
+		return this;
+	}
+	
+	function Input() {
+		this.semantic = "";
+		this.offset = 0;
+		this.source = "";
+		this.set = 0;
+	}
+	Input.prototype.parse = function(element) {
+		this.semantic = element.getAttribute('semantic');
+		this.source = element.getAttribute('source').replace(/^#/, '');
+		this.set = _attr_as_int(element, 'set', -1);
+		this.offset = _attr_as_int(element, 'offset', 0);
+		if (this.semantic == 'TEXCOORD' && this.set < 0) {
+			this.set = 0;
+		}
+		return this;
+	}
+	
+	function Source(id) {
+		this.id = id;
+		this.type = null;
+	}
+	Source.prototype.parse = function(element) {
+		this.id = element.getAttribute('id');
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			switch (child.nodeName) {
+				case 'bool_array':
+					this.data = _bools(child.textContent);
+					this.type = child.nodeName;
+					break;
+				case 'float_array':
+					this.data = _floats(child.textContent);
+					this.type = child.nodeName;
+					break;
+				case 'int_array':
+					this.data = _ints(child.textContent);
+					this.type = child.nodeName;
+					break;
+				case 'IDREF_array':
+				case 'Name_array':
+					this.data = _strings(child.textContent);
+					this.type = child.nodeName;
+					break;
+				case 'technique_common':
+					for (var j = 0; j < child.childNodes.length; j++) {
+						if (child.childNodes[j].nodeName == 'accessor') {
+							this.accessor = (new Accessor()).parse(child.childNodes[j]);
+							break;
+						}
+					}
+					break;
+				default:
+					//console.log(child.nodeName);
+					break;
+			}
+		}
+		return this;
+	}
+	Source.prototype.read = function() {
+		var result = [];
+		//for (var i = 0; i < this.accessor.params.length; i++) {
+			var param = this.accessor.params[0];
+			//console.log(param.name + " " + param.type);
+			switch (param.type) {
+				case 'IDREF':
+				case 'Name':
+				case 'float':
+					return this.data;
+				case 'float4x4':
+					for (var j = 0; j < this.data.length; j += 16) {
+						result.push(new THREE.Matrix4(this.data.slice(j, j+16)));
+					}
+					break;
+				default:
+					console.log('Dae::Source:read dont know how to read ' + param.type);
+					break;
+			}
+		//}
+		return result;
+	}
+	function Material() {
+		this.id = "";
+		this.name = "";
+		this.instance_effect = null;
+	}
+	Material.prototype.parse = function(element) {
+		this.id = element.getAttribute('id');
+		this.name = element.getAttribute('name');
+		for (var i = 0; i < element.childNodes.length; i++) {
+			if (element.childNodes[i].nodeName == 'instance_effect') {
+				this.instance_effect = (new InstanceEffect()).parse(element.childNodes[i]);
+				break;
+			}
+		}
+		return this;
+	}
+	
+	function ColorOrTexture() {
+		this.color = new THREE.Color(0);
+		this.color.setRGB(Math.random(), Math.random(), Math.random());
+		this.color.a = 1.0;
+		this.texture = null;
+		this.texcoord = null;
+	}
+	ColorOrTexture.prototype.isColor = function() {
+		return (this.texture == null);
+	}
+	ColorOrTexture.prototype.isTexture = function() {
+		return (this.texture != null);
+	}
+	ColorOrTexture.prototype.parse = function(element) {
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'color':
+					var rgba = _floats(child.textContent);
+					this.color = new THREE.Color(0);
+					this.color.setRGB(rgba[0], rgba[1], rgba[2]);
+					this.color.a = rgba[3];
+					break;
+				case 'texture':
+					this.texture = child.getAttribute('texture');
+					this.texcoord = child.getAttribute('texcoord');
+					break;
+				default:
+					break;
+			}
+		}
+		return this;
+	}
+	
+	function Shader(type) {
+		this.type = type;
+	}
+	Shader.prototype.parse = function(element) {
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'ambient':
+				case 'emission':
+				case 'diffuse':
+				case 'specular':
+				case 'transparent':
+					this[child.nodeName] = (new ColorOrTexture()).parse(child);
+					break;
+				case 'shininess':
+				case 'reflectivity':
+				case 'transparency':
+					var f = evaluateXPath(child, ".//dae:float");
+					if (f.length > 0)
+						this[child.nodeName] = parseFloat(f[0].textContent);
+					break;
+				default:
+					break;
+			}
+		}
+		return this;
+	}
+	
+	function Surface(effect) {
+		this.effect = effect;
+		this.init_from;
+		this.format;
+	}
+	Surface.prototype.parse = function(element) {
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'init_from':
+					this.init_from = child.textContent;
+					break;
+				case 'format':
+					this.format = child.textContent;
+					break;
+				default:
+					console.log("unhandled Surface prop: " + child.nodeName);
+					break;
+			}
+		}
+		return this;
+	}
+	function Sampler2D(effect) {
+		this.effect = effect;
+		this.source;
+		this.wrap_s;
+		this.wrap_t;
+		this.minfilter;
+		this.magfilter;
+		this.mipfilter;
+	}
+	Sampler2D.prototype.parse = function(element) {
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'source':
+					this.source = child.textContent;
+					break;
+				case 'minfilter':
+					this.minfilter = child.textContent;
+					break;
+				case 'magfilter':
+					this.magfilter = child.textContent;
+					break;
+				case 'mipfilter':
+					this.mipfilter = child.textContent;
+					break;
+				case 'wrap_s':
+					this.wrap_s = child.textContent;
+					break;
+				case 'wrap_t':
+					this.wrap_t = child.textContent;
+					break;
+				default:
+					console.log("unhandled Sampler2D prop: " + child.nodeName);
+					break;
+			}
+		}
+		return this;
+	}
+	
+	function Effect() {
+		this.id = "";
+		this.name = "";
+		this.shader = null;
+		this.surface;
+		this.sampler;
+	}
+	Effect.prototype.parse = function(element) {
+		this.id = element.getAttribute('id');
+		this.name = element.getAttribute('name');
+		
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'profile_COMMON':
+					this.parseProfileCOMMON(child);
+					break;
+				default:
+					break;
+			}
+		}
+		return this;
+	}
+	Effect.prototype.parseNewparam = function(element) {
+		var sid = element.getAttribute('sid');
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'surface':
+					this.surface = (new Surface(this)).parse(child);
+					this.surface.sid = sid;
+					break;
+				case 'sampler2D':
+					this.sampler = (new Sampler2D(this)).parse(child);
+					this.sampler.sid = sid;
+					break;
+				default:
+					console.log(child.nodeName);
+					break;
+			}
+		}
+	}
+	Effect.prototype.parseProfileCOMMON = function(element) {
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'profile_COMMON':
+					this.parseProfileCOMMON(child);
+					break;
+				case 'technique':
+					this.parseTechnique(child);
+					break;
+				case 'newparam':
+					this.parseNewparam(child);
+					break;
+				default:
+					console.log(child.nodeName);
+					break;
+			}
+		}
+	}
+	Effect.prototype.parseTechnique= function(element) {
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'lambert':
+				case 'blinn':
+				case 'phong':
+					this.shader = (new Shader(child.nodeName)).parse(child);
+					break;
+				default:
+					break;
+			}
+		}
+	}
+	
+	function InstanceEffect() {
+		this.url = "";
+	}
+	InstanceEffect.prototype.parse = function(element) {
+		this.url = element.getAttribute('url').replace(/^#/, '');
+		return this;
+	}
+
+	function Animation() {
+		this.id = "";
+		this.name = "";
+		this.source = {};
+		this.sampler = [];
+		this.channel = [];
+	}
+	Animation.prototype.parse = function(element) {
+		this.id = element.getAttribute('id');
+		this.name = element.getAttribute('name');
+		this.source = {};
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'source':
+					var src = (new Source()).parse(child);
+					this.source[src.id] = src;
+					break;
+				case 'sampler':
+					this.sampler.push((new Sampler(this)).parse(child));
+					break;
+				case 'channel':
+					this.channel.push((new Channel(this)).parse(child));
+					break;
+				default:
+					break;
+			}
+		}
+		return this;
+	}
+	function Channel(animation) {
+		this.animation = animation;
+		this.source = "";
+		this.target = "";
+	}
+	Channel.prototype.parse = function(element) {
+		this.source = element.getAttribute('source').replace(/^#/, '');
+		this.target = element.getAttribute('target');
+		return this;
+	}	
+	function Sampler(animation) {
+		this.id = "";
+		this.animation = animation;
+		this.inputs = [];
+		this.input;
+		this.output;
+		this.interpolation;
+	}
+	Sampler.prototype.parse = function(element) {
+		this.id = element.getAttribute('id');
+		this.inputs = [];
+		for (var i = 0; i < element.childNodes.length; i++) {
+			var child = element.childNodes[i];
+			if (child.nodeType != 1) continue;
+			switch (child.nodeName) {
+				case 'input':
+					this.inputs.push((new Input()).parse(child));
+					break;
+				default:
+					break;
+			}
+		}
+		return this;
+	}
+	Sampler.prototype.create = function() {
+		for (var i = 0; i < this.inputs.length; i++) {
+			var input = this.inputs[i];
+			var source = this.animation.source[input.source];
+			switch (input.semantic) {
+				case 'INPUT':
+					this.input = source.read();
+					break;
+				case 'OUTPUT':
+					this.output = source.read();
+					break;
+				case 'INTERPOLATION':
+					this.interpolation = source.read();
+					break;
+				default:
+					console.log(input.semantic);
+					break;
+			}
+		}
+	}
+	
+	function _source(element) {
+		var id = element.getAttribute('id');
+		if (sources[id] != undefined) {
+			return sources[id];
+		}
+		sources[id] = (new Source(id)).parse(element);
+		return sources[id];
+	}
+	
+	function _nsResolver (nsPrefix) {
+		if (nsPrefix == "dae") {
+			return "http://www.collada.org/2005/11/COLLADASchema";
+		}
+		return null;
+	}
+	
+	function _bools ( str ) {
+		var raw = _strings(str);
+		var data = [];
+		var i;
+		for (i = 0; i < raw.length; i++) {
+			data.push((raw[i] == 'true' || raw[i] == '1') ? true : false);
+		}
+		return data;
+	}
+	
+	function _floats ( str ) {
+		var raw = _strings(str);
+		var data = [];
+		var i;
+		for (i = 0; i < raw.length; i++) {
+			data.push( parseFloat(raw[i]) );
+		}
+		return data;
+	}
+
+	function _ints ( str ) {
+		var raw = _strings(str);
+		var data = [];
+		var i;
+		for (i = 0; i < raw.length; i++) {
+			data.push( parseInt(raw[i], 10) );
+		}
+		return data;
+	}
+	
+	function _strings ( str ) {
+		return _trimString(str).split(/\s+/);
+	}
+
+	function _trimString ( str ) {
+		return str.replace(/^\s+/, "").replace(/\s+$/, "");
+	}
+
+	function _attr_as_float ( element, name, defaultValue ) {
+		if ( element.hasAttribute(name) ) {
+			return parseFloat(element.getAttribute(name));
+		} else {
+			return defaultValue;
+		}
+	}
+
+	function _attr_as_int ( element, name, defaultValue ) {
+		if ( element.hasAttribute(name) ) {
+			return parseInt(element.getAttribute(name), 10);
+		} else {
+			return defaultValue;
+		}
+	}
+
+	function _attr_as_string ( element, name, defaultValue ) {
+		if ( element.hasAttribute(name) ) {
+			return element.getAttribute(name);
+		} else {
+			return defaultValue;
+		}
+	}
+	
+	function _format_float(f, num) {
+		if (f === undefined) {
+			var s = '0.';
+			while (s.length < num + 2) {
+				s += '0';
+			}
+			return s;
+		}
+		var parts = f.toString().split('.');
+		num = num || 2;
+		parts[1] = parts.length > 1 ? parts[1].substr(0, num) : "0";
+		while(parts[1].length < num) {
+			parts[1] += '0';
+		}
+		return parts.join('.');
+	}
+	
+	function _hash_vertex(v, n, t0, t1, precision) {
+		precision = precision || 2;
+		var s = v instanceof THREE.Vertex ? _hash_vector3(v.position, precision) : _hash_vector3(v, precision);
+		if (n === undefined) {
+			s += '_0.00,0.00,0.00';
+		} else {
+			s += '_' + _hash_vector3(n, precision);
+		}
+		if (t0 === undefined) {
+			s += '_0.00,0.00';
+		} else {
+			s += '_' + _hash_uv(t0, precision);
+		}
+		if (t1 === undefined) {
+			s += '_0.00,0.00';
+		} else {
+			s += '_' + _hash_uv(t1, precision);
+		}
+		return s;
+	}
+	
+	function _hash_uv(uv, num) {
+		var s = '';
+		s += _format_float(uv.u, num) + ',';
+		s += _format_float(uv.v, num);
+		return s;
+	}
+	
+	function _hash_vector3(vec, num) {
+		var s = '';
+		s += _format_float(vec.x, num) + ',';
+		s += _format_float(vec.y, num) + ',';
+		s += _format_float(vec.z, num);
+		return s;
+	}
+	
+	function evaluateXPath(node, query) {
+		var instances = COLLADA.evaluate(query, 
+			node, 
+			_nsResolver, 
+			XPathResult.ORDERED_NODE_ITERATOR_TYPE, 
+			null);
+		var inst = instances.iterateNext();
+		var result = [];
+		while (inst) {
+			result.push(inst);
+			inst = instances.iterateNext();
+		} 
+		return result;
+	}
+	return {
+		load: load,
+		geometries : geometries
+	};
+})();
+

Some files were not shown because too many files changed in this diff