Roi Atalla avatar Roi Atalla committed 4d371ad

Removed extraneous file and added Scene.java, no clue why that was ever removed.

Comments (0)

Files changed (3)

.idea/workspace.xml

 <?xml version="1.0" encoding="UTF-8"?>
 <project version="4">
   <component name="ChangeListManager">
-    <list default="true" id="3bd3582b-975a-4915-888d-8e2c52d85938" name="Default" comment="Updated GL32 and GLProgram to fix core/compatibility issues.">
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.concrete649_small.dds" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.dsc_1621_small.dds" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.rough645_small.dds" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.seamless_rock1_small.dds" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.wood4_rotate.dds" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/Example17_1.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/binders/StateBinder.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/binders/TextureBinder.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/binders/UniformBlockBinder.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/binders/UniformFloatBinder.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/binders/UniformIntBinder.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/binders/UniformMat4Binder.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/binders/UniformVec2Binder.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/binders/UniformVec3Binder.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/binders/UniformVec4Binder.java" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.LitTexture.frag" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.LitTexture.vert" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.LongBar.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.ShortBar.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.UnitCube.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.UnitDiorama.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.UnitPlane.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.UnitSphere.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.Unlit.frag" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.Unlit.vert" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.scene.xml" />
-      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/scene.xml" />
-      <change type="DELETED" beforePath="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/Scene.java" afterPath="" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/ra4king/opengl/GLProgram.java" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/GLProgram.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example3/LightEnv.java" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter16/example3/LightEnv.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/ra4king/opengl/util/math/Matrix4.java" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/math/Matrix4.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/ra4king/opengl/util/Mesh.java" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/Mesh.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/src/com/ra4king/opengl/util/Utils.java" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/Utils.java" />
-      <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/libraries/XPP3.xml" afterPath="$PROJECT_DIR$/.idea/libraries/XPP3.xml" />
+    <list default="true" id="3bd3582b-975a-4915-888d-8e2c52d85938" name="Default" comment="Removed extraneous file and added Scene.java, no clue why that was ever removed.">
+      <change type="NEW" beforePath="" afterPath="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/Scene.java" />
+      <change type="DELETED" beforePath="E:\Roi Atalla\Documents\Programming Files\Java Files\Personal Projects\OpenGL\src\com\ra4king\opengl\arcsynthesis\gl33\chapter17\scene.xml" afterPath="" />
       <change type="MODIFICATION" beforePath="$PROJECT_DIR$/.idea/workspace.xml" afterPath="$PROJECT_DIR$/.idea/workspace.xml" />
     </list>
     <ignored path="OpenGL.iws" />
     <file path="/a.xml" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1361850040520" ignored="false" />
     <file path="/a.html" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1361850041808" ignored="false" />
     <file path="/a.groovy" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1361850042481" ignored="false" />
-    <file path="/Dummy.txt" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1369635409189" ignored="false" />
+    <file path="/Dummy.txt" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1369898175488" ignored="false" />
     <file path="/Example12_1.java" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1362027020824" ignored="false" />
     <file path="/example12.1.DiffuseSpecular.frag" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1361702005810" ignored="false" />
     <file path="/LightManager.java" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1362461124226" ignored="false" />
     <file path="/sample.java" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1367460530818" ignored="false" />
-    <file path="/Scene.java" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1369895928286" ignored="false" />
+    <file path="/Scene.java" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1369898191272" ignored="false" />
     <file path="$PROJECT_DIR$/bin/com/ra4king/opengl/arcsynthesis/gl33/chapter8/example1/example8.1.Ship.xml" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1361777249769" ignored="false" />
     <file path="$PROJECT_DIR$/bin/com/ra4king/opengl/arcsynthesis/gl33/chapter8/example2/example8.2.Ship.xml" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1361777249770" ignored="false" />
     <file path="$PROJECT_DIR$/bin/com/ra4king/opengl/arcsynthesis/gl33/chapter9/example2/example9.2.UnitCylinder.xml" changelist="3bd3582b-975a-4915-888d-8e2c52d85938" time="1361777249770" ignored="false" />
     <favorites_list name="OpenGL" />
   </component>
   <component name="FileEditorManager">
-    <leaf />
+    <leaf>
+      <file leaf-file-name="Scene.java" pinned="false" current="true" current-in-tab="true">
+        <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/Scene.java">
+          <provider selected="true" editor-type-id="text-editor">
+            <state line="322" column="16" selection-start="12231" selection-end="12231" vertical-scroll-proportion="0.5032258">
+              <folding>
+                <element signature="imports" expanded="true" />
+              </folding>
+            </state>
+          </provider>
+        </entry>
+      </file>
+    </leaf>
   </component>
   <component name="FindManager">
     <FindUsagesManager>
         <option value="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter13/example2/example13.2.UnitCube.xml" />
         <option value="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter14/example1/example14.1.UnitCube.xml" />
         <option value="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter14/example3/example14.3.UnitCube.xml" />
-        <option value="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/Scene.java" />
         <option value="$PROJECT_DIR$/src/com/ra4king/opengl/util/Utils.java" />
         <option value="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/Example17_1.java" />
         <option value="$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/example1/example17.1.UnitSphere.xml" />
+        <option value="$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/Scene.java" />
       </list>
     </option>
   </component>
               <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
             </PATH_ELEMENT>
           </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="src" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="src" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="opengl" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="src" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="opengl" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="util" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="src" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="opengl" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="util" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="scene" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="src" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="opengl" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="arcsynthesis" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="gl33" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="chapter17" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="src" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="opengl" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="arcsynthesis" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="gl33" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="chapter17" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="example1" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="src" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="opengl" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="arcsynthesis" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="gl33" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
-          <PATH>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="OpenGL" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="src" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="opengl" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-            <PATH_ELEMENT>
-              <option name="myItemId" value="arcsynthesis" />
-              <option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
-            </PATH_ELEMENT>
-          </PATH>
         </subPane>
       </pane>
     </panes>
       <created>1369251774995</created>
       <updated>1369251774995</updated>
     </task>
-    <option name="localTasksCounter" value="39" />
+    <task id="LOCAL-00039" summary="Example 17.1 fully ported and functional">
+      <created>1369898069520</created>
+      <updated>1369898069520</updated>
+    </task>
+    <option name="localTasksCounter" value="40" />
     <servers />
   </component>
   <component name="TodoView" selected-index="4">
   </component>
   <component name="ToolWindowManager">
     <frame x="1912" y="-8" width="1936" height="1096" extended-state="6" />
-    <editor active="false" />
+    <editor active="true" />
     <layout>
       <window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.23723404" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
       <window_info id="JetGradle" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32977587" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
       <window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
+      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.58528787" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.21748401" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
       <window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.29317698" sideWeight="0.51387405" order="9" side_tool="true" content_ui="tabs" />
       <window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.18366013" sideWeight="0.14915694" order="2" side_tool="true" content_ui="tabs" />
       <window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.29104477" sideWeight="0.5" order="11" side_tool="false" content_ui="tabs" />
       <window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.23240939" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
-      <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.14605543" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
+      <window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.14605543" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
       <window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.18366013" sideWeight="0.17250325" order="1" side_tool="true" content_ui="tabs" />
       <window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32977587" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
       <window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" weight="0.36819637" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
-      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.20170757" sideWeight="0.6791045" order="0" side_tool="true" content_ui="combo" x="2394" y="136" width="397" height="768" />
-      <window_info id="Run" active="true" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.32089552" sideWeight="0.4823906" order="2" side_tool="false" content_ui="tabs" />
+      <window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.20170757" sideWeight="0.85394454" order="0" side_tool="true" content_ui="combo" x="2394" y="136" width="397" height="768" />
+      <window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32089552" sideWeight="0.4823906" order="2" side_tool="false" content_ui="tabs" />
       <window_info id="Documentation" active="true" anchor="right" auto_hide="false" internal_type="SLIDING" type="FLOATING" visible="true" weight="0.32977587" sideWeight="0.80490404" order="4" side_tool="false" content_ui="combo" x="2005" y="108" width="1736" height="896" />
       <window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
       <window_info id="Problems" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.32978722" sideWeight="0.5" order="8" side_tool="false" content_ui="tabs" />
       <window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
       <window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.2497332" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
-      <window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.58528787" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
       <window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
       <window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.39978677" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
     </layout>
     <option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="false" />
     <option name="FORCE_NON_EMPTY_COMMENT" value="false" />
     <option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="false" />
-    <option name="LAST_COMMIT_MESSAGE" value="Updated GL32 and GLProgram to fix core/compatibility issues." />
+    <option name="LAST_COMMIT_MESSAGE" value="Removed extraneous file and added Scene.java, no clue why that was ever removed." />
     <option name="MAKE_NEW_CHANGELIST_ACTIVE" value="false" />
     <option name="OPTIMIZE_IMPORTS_BEFORE_PROJECT_COMMIT" value="true" />
     <option name="CHECK_FILES_UP_TO_DATE_BEFORE_COMMIT" value="false" />
     <option name="UPDATE_FILTER_BY_SCOPE" value="false" />
     <option name="SHOW_FILE_HISTORY_AS_TREE" value="false" />
     <option name="FILE_HISTORY_SPLITTER_PROPORTION" value="0.6" />
-    <MESSAGE value="Example 14.1 fully ported." />
-    <MESSAGE value="Example 14.2 fully ported." />
     <MESSAGE value="Using DDS Loader from https://github.com/integeruser/gltut-lwjgl." />
     <MESSAGE value="Added REAMDE file." />
     <MESSAGE value="Fixed README file." />
     <MESSAGE value="Update configurations." />
     <MESSAGE value="Ported the first 3 chapters to OpenGL 3.2." />
     <MESSAGE value="Updated GL32 and GLProgram to fix core/compatibility issues." />
+    <MESSAGE value="Example 17.1 fully ported and functional" />
+    <MESSAGE value="Removed extraneous file and added Scene.java, no clue why that was ever removed." />
   </component>
   <component name="XDebuggerManager">
     <breakpoint-manager>
     <option name="FILTER_TARGETS" value="false" />
   </component>
   <component name="editorHistoryManager">
-    <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter13/example2/example13.2.UnitCube.xml">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="101" column="13" selection-start="1605" selection-end="1605" vertical-scroll-proportion="0.68421054">
-          <folding />
-        </state>
-      </provider>
-    </entry>
     <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/arcsynthesis/gl33/chapter13/example1/example13.1.UnitCube.xml">
       <provider selected="true" editor-type-id="text-editor">
         <state line="104" column="15" selection-start="1632" selection-end="1632" vertical-scroll-proportion="0.7518797">
         </state>
       </provider>
     </entry>
-    <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/Scene.java">
-      <provider selected="true" editor-type-id="text-editor">
-        <state line="345" column="16" selection-start="12972" selection-end="12972" vertical-scroll-proportion="0.8121469">
-          <folding>
-            <element signature="imports" expanded="true" />
-          </folding>
-        </state>
-      </provider>
-    </entry>
     <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/util/math/Vector2.java">
       <provider selected="true" editor-type-id="text-editor">
         <state line="19" column="0" selection-start="306" selection-end="306" vertical-scroll-proportion="0.289548">
         </state>
       </provider>
     </entry>
+    <entry file="file://$PROJECT_DIR$/src/com/ra4king/opengl/util/scene/Scene.java">
+      <provider selected="true" editor-type-id="text-editor">
+        <state line="322" column="16" selection-start="12231" selection-end="12231" vertical-scroll-proportion="0.5032258">
+          <folding>
+            <element signature="imports" expanded="true" />
+          </folding>
+        </state>
+      </provider>
+    </entry>
   </component>
   <component name="hg4idea.settings">
     <option name="CHECK_INCOMING_OUTGOING" value="true" />

src/com/ra4king/opengl/arcsynthesis/gl33/chapter17/scene.xml

-<?xml version="1.0" encoding="UTF-8"?>
-<?oxygen RNGSchema="../../Documents/sceneFormat.rnc" type="compact"?>
-<scene xmlns="http://www.arcsynthesis.com/gltut/scene">
-	<mesh xml:id="m_sphere" file="UnitSphere.xml" />
-	<mesh xml:id="m_cube" file="UnitCube.xml" />
-	<mesh xml:id="m_shortBar" file="ShortBar.xml" />
-	<mesh xml:id="m_longBar" file="LongBar.xml" />
-	<mesh xml:id="m_diorama" file="UnitDiorama.xml" />
-	<mesh xml:id="m_floor" file="UnitPlane.xml" />
-	<texture xml:id="t_stone" file="seamless_rock1_small.dds" srgb="true" />
-	<texture xml:id="t_concrete_wall" file="concrete649_small.dds" srgb="true" />
-	<texture xml:id="t_sandy_ground" file="dsc_1621_small.dds" srgb="true" />
-	<texture xml:id="t_stone_pillar" file="rough645_small.dds" srgb="true" />
-	<texture xml:id="t_wood_pillar" file="wood4_rotate.dds" srgb="true" />
-	<prog
-	xml:id="p_unlit"
-	vert="Unlit.vert"
-	frag="Unlit.frag"
-	model-to-camera="modelToCameraMatrix">
-		<block name="Projection" binding="0" />
-	</prog>
-	<prog
-	xml:id="p_lit"
-	vert="litTexture.vert"
-	frag="litTexture.frag"
-	model-to-camera="modelToCameraMatrix"
-	normal-model-to-camera="normalModelToCameraMatrix">
-		<block name="Projection" binding="0" />
-		<block name="Light" binding="1" />
-		<sampler name="diffuseColorTex" unit="0" />
-	</prog>
-	<node
-	name="cube"
-	mesh="m_cube"
-	prog="p_lit"
-	pos="0 1 0"
-	orient="0.0 0.0 0.0 1.0"
-	scale="3">
-		<texture name="t_stone" unit="0" sampler="anisotropic" />
-	</node>
-	<node
-	name="rightBar"
-	mesh="m_shortBar"
-	prog="p_lit"
-	pos="13 -2 0"
-	orient="0.0 0.0 0.0 1.0"
-	scale="3">
-		<texture name="t_stone" unit="0" sampler="anisotropic" />
-	</node>
-	<node
-	name="leaningBar"
-	mesh="m_longBar"
-	prog="p_lit"
-	pos="3 -7 -10"
-	orient="0.64278 0 0 0.76604"
-	scale="5">
-		<texture name="t_wood_pillar" unit="0" sampler="anisotropic" />
-	</node>
-	<node
-	name="spinBar"
-	mesh="m_longBar"
-	prog="p_lit"
-	pos="-7 0 8"
-	orient="-0.148446 0.554035 0.212003 0.791242"
-	scale="4">
-		<texture name="t_stone_pillar" unit="0" sampler="anisotropic" />
-	</node>
-	<!--
-		<node
-			name="diorama"
-			mesh="m_diorama"
-			prog="p_lit"
-			pos="0 -10 0"
-			scale="47">
-			<texture name="t_concrete_wall" unit="0" sampler="anisotropic"/>
-		</node>
-		<node
-			name="floor"
-			mesh="m_floor"
-			prog="p_lit"
-			pos="0 -33.5 0"
-			scale="47">
-			<texture name="t_sandy_ground" unit="0" sampler="anisotropic"/>
-		</node>
-	-->
-</scene>

src/com/ra4king/opengl/util/scene/Scene.java

+package com.ra4king.opengl.util.scene;
+
+import static org.lwjgl.opengl.EXTTextureFilterAnisotropic.*;
+import static org.lwjgl.opengl.GL11.*;
+import static org.lwjgl.opengl.GL12.*;
+import static org.lwjgl.opengl.GL13.*;
+import static org.lwjgl.opengl.GL14.*;
+import static org.lwjgl.opengl.GL20.*;
+import static org.lwjgl.opengl.GL31.*;
+import static org.lwjgl.opengl.GL33.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import com.ra4king.opengl.util.Mesh;
+import com.ra4king.opengl.util.ShaderProgram;
+import com.ra4king.opengl.util.Utils;
+import com.ra4king.opengl.util.math.Matrix3;
+import com.ra4king.opengl.util.math.Matrix4;
+import com.ra4king.opengl.util.math.Quaternion;
+import com.ra4king.opengl.util.math.Vector3;
+import com.ra4king.opengl.util.scene.Scene.SceneNode.Variant;
+import com.ra4king.opengl.util.scene.binders.StateBinder;
+
+import rosick.jglsdk.glimg.DdsLoader;
+import rosick.jglsdk.glimg.ImageSet;
+import rosick.jglsdk.glimg.TextureGenerator;
+import rosick.jglsdk.glimg.TextureGenerator.ForcedConvertFlags;
+
+/**
+ * @author ra4king
+ */
+public class Scene {
+	private HashMap<String,Mesh> meshes;
+	private HashMap<String,SceneTexture> textures;
+	private HashMap<String,SceneProgram> programs;
+	private HashMap<String,SceneNode> nodes;
+	
+	public Scene(URL url, Class<?> clazz, String prefix) throws IOException, XmlPullParserException {
+		meshes = new HashMap<>();
+		textures = new HashMap<>();
+		programs = new HashMap<>();
+		nodes = new HashMap<>();
+		
+		try(InputStream is = url.openStream()) {
+			XmlPullParser xml = XmlPullParserFactory.newInstance().newPullParser();
+			xml.setInput(is, "UTF-8");
+			
+			xml.next();
+			xml.require(XmlPullParser.START_TAG, null, "scene");
+			
+			xml.nextTag();
+			xml.require(XmlPullParser.START_TAG, null, "mesh");
+			
+			int count = 0;
+			do {
+				String id = xml.getAttributeValue(null, "xml:id");
+				String file = xml.getAttributeValue(null, "file");
+				
+				throwIfNull(id, "id", "mesh " + count);
+				throwIfNull(file, "file", "mesh " + count);
+				
+				if(meshes.containsKey(id))
+					throw new IllegalArgumentException("Mesh named '" + id + "' already exists.");
+				
+				try {
+					meshes.put(id, new Mesh(clazz.getResource(prefix + file)));
+				} catch(Exception exc) {
+					throw new IllegalArgumentException("Invalid mesh file for '" + id + "'.", exc);
+				}
+				
+				xml.next();
+				xml.require(XmlPullParser.END_TAG, null, "mesh");
+				
+				count++;
+			} while(xml.nextTag() == XmlPullParser.START_TAG && xml.getName().equals("mesh"));
+			
+			xml.require(XmlPullParser.START_TAG, null, "texture");
+			
+			count = 0;
+			do {
+				String id = xml.getAttributeValue(null, "xml:id");
+				String file = xml.getAttributeValue(null, "file");
+				
+				throwIfNull(id, "id", "texture " + count);
+				throwIfNull(file, "file", "texture " + count);
+				
+				String s = xml.getAttributeValue(null, "srgb");
+				throwIfNull(s, "srgb", "texture " + count);
+				
+				boolean srgb;
+				try {
+					srgb = Boolean.parseBoolean(s);
+				} catch(Exception exc) {
+					throw new IllegalArgumentException("srgb should be only true or false, invalid value at texture " + count + ".");
+				}
+				
+				if(textures.containsKey(id))
+					throw new IllegalArgumentException("Texture named '" + id + "' already exists.");
+				
+				try {
+					textures.put(id, new SceneTexture(clazz.getResourceAsStream(prefix + file), srgb ? ForcedConvertFlags.FORCE_SRGB_COLORSPACE_FMT : 0));
+				} catch(Exception exc) {
+					throw new IllegalArgumentException("Texture named '" + id + "' is invalid.", exc);
+				}
+				
+				xml.next();
+				xml.require(XmlPullParser.END_TAG, null, "texture");
+				
+				count++;
+			} while(xml.nextTag() == XmlPullParser.START_TAG && xml.getName().equals("texture"));
+			
+			xml.require(XmlPullParser.START_TAG, null, "prog");
+			
+			count = 0;
+			do {
+				String id = xml.getAttributeValue(null, "xml:id");
+				String vertexFile = xml.getAttributeValue(null, "vert");
+				String fragmentFile = xml.getAttributeValue(null, "frag");
+				String modelMatrix = xml.getAttributeValue(null, "model-to-camera");
+				
+				throwIfNull(id, "id", "prog " + count);
+				throwIfNull(vertexFile, "vert", "prog " + count);
+				throwIfNull(fragmentFile, "frag", "prog " + count);
+				throwIfNull(modelMatrix, "model-to-camera", "prog " + count);
+				
+				String normalModelMatrix = xml.getAttributeValue(null, "normal-model-to-camera");
+				String invNormalModelMatrix = xml.getAttributeValue(null, "normal-camera-to-model");
+				String geometryFile = xml.getAttributeValue(null, "geom");
+				
+				if(programs.containsKey(id))
+					throw new IllegalArgumentException("Program named '" + id + "' already exists.");
+				
+				ShaderProgram program;
+				try {
+					if(geometryFile != null)
+						program = new ShaderProgram(Utils.readFully(clazz.getResourceAsStream(prefix + vertexFile)),
+								Utils.readFully(clazz.getResourceAsStream(prefix + geometryFile)),
+								Utils.readFully(clazz.getResourceAsStream(prefix + fragmentFile)));
+					else
+						program = new ShaderProgram(Utils.readFully(clazz.getResourceAsStream(prefix + vertexFile)),
+								Utils.readFully(clazz.getResourceAsStream(prefix + fragmentFile)));
+				} catch(Exception exc) {
+					throw new IllegalArgumentException("Invalid shaders for program " + id, exc);
+				}
+				
+				int matrixLocation = glGetUniformLocation(program.getProgram(), modelMatrix);
+				if(matrixLocation == -1)
+					throw new IllegalArgumentException("Program shader '" + id + "' does not have a matrix uniform.");
+				
+				int normalMatrixLocation = -1;
+				if(normalModelMatrix != null) {
+					normalMatrixLocation = glGetUniformLocation(program.getProgram(), normalModelMatrix);
+					if(normalMatrixLocation == -1)
+						throw new IllegalArgumentException("Program shader '" + id + "' does not have a normal matrix uniform.");
+				}
+				
+				int invNormalMatrixLocation = -1;
+				if(invNormalModelMatrix != null) {
+					invNormalMatrixLocation = glGetUniformLocation(program.getProgram(), invNormalModelMatrix);
+					if(normalMatrixLocation == -1)
+						throw new IllegalArgumentException("Program shader '" + id + "' does not have a inverse normal matrix uniform.");
+				}
+				
+				programs.put(id, new SceneProgram(program, matrixLocation, normalMatrixLocation, invNormalMatrixLocation));
+				
+				ArrayList<String> blocks = new ArrayList<>();
+				ArrayList<String> samplers = new ArrayList<>();
+				
+				while(xml.nextTag() == XmlPullParser.START_TAG) {
+					switch(xml.getName()) {
+						case "block": {
+							String name = xml.getAttributeValue(null, "name");
+							String binding = xml.getAttributeValue(null, "binding");
+							
+							throwIfNull(name, "name", "block in program '" + id + "'");
+							throwIfNull(binding, "binding", "block in program '" + id + "'");
+							
+							if(blocks.contains(name))
+								throw new IllegalArgumentException("Block '" + name + "' is used more than once in program '" + id + "'.");
+							
+							blocks.add(name);
+							
+							int blockIndex = glGetUniformBlockIndex(program.getProgram(), name);
+							if(blockIndex == GL_INVALID_INDEX)
+								throw new IllegalArgumentException("Block '" + name + "' cannot be found in program '" + id + "'.");
+							
+							int bindPoint;
+							try {
+								bindPoint = Integer.parseInt(binding);
+							} catch(Exception exc) {
+								throw new IllegalArgumentException("Binding in block '" + name + "' is invalid value; must be integer.");
+							}
+							
+							glUniformBlockBinding(program.getProgram(), blockIndex, bindPoint);
+							
+							xml.next();
+							xml.require(XmlPullParser.END_TAG, null, "block");
+							
+							break;
+						}
+						case "sampler": {
+							String name = xml.getAttributeValue(null, "name");
+							String texUnit = xml.getAttributeValue(null, "unit");
+							
+							throwIfNull(name, "name", "sampler in program '" + id + "'");
+							throwIfNull(texUnit, "unit", "sampler in program '" + id + "'");
+							
+							if(samplers.contains(name))
+								throw new IllegalArgumentException("Sampler '" + name + "' is used more than once in program '" + id + "'.");
+							
+							samplers.add(name);
+							
+							int samplerLocation = glGetUniformLocation(program.getProgram(), name);
+							if(samplerLocation == -1)
+								throw new IllegalArgumentException("Sampler '" + name + "' cannot be found in program '" + id + "'.");
+							
+							int textureUnit;
+							try {
+								textureUnit = Integer.parseInt(texUnit);
+							} catch(Exception exc) {
+								throw new IllegalArgumentException("Texture unit in sampler '" + name + "' is invalid value; must be integer.");
+							}
+							
+							program.begin();
+							glUniform1i(samplerLocation, textureUnit);
+							program.end();
+							
+							xml.next();
+							xml.require(XmlPullParser.END_TAG, null, "sampler");
+							
+							break;
+						}
+						default:
+							throw new IllegalArgumentException("Invalid element in program '" + id + "'.");
+					}
+				}
+				
+				xml.require(XmlPullParser.END_TAG, null, "prog");
+				
+				count++;
+			} while(xml.nextTag() == XmlPullParser.START_TAG && xml.getName().equals("prog"));
+			
+			xml.require(XmlPullParser.START_TAG, null, "node");
+			
+			count = 0;
+			do {
+				String name = xml.getAttributeValue(null, "name");
+				String mesh = xml.getAttributeValue(null, "mesh");
+				
+				throwIfNull(name, "name", "node " + count);
+				throwIfNull(mesh, "mesh", "node " + count);
+				
+				String prog = xml.getAttributeValue(null, "prog");
+				String position = xml.getAttributeValue(null, "pos");
+				String orient = xml.getAttributeValue(null, "orient");
+				String scale = xml.getAttributeValue(null, "scale");
+				
+				throwIfNull(position, "pos", "node " + count);
+				
+				if(nodes.containsKey(name))
+					throw new IllegalArgumentException("Node named '" + name + "' already exists.");
+				
+				if(!meshes.containsKey(mesh))
+					throw new IllegalArgumentException("Mesh named '" + mesh + "' in node '" + name + "' does not exist.");
+				
+				if(prog != null) {
+					if(!programs.containsKey(prog))
+						throw new IllegalArgumentException("Program named '" + prog + "' in node '" + name + "' does not exist.");
+				}
+				
+				Vector3 nodePos;
+				try {
+					nodePos = Utils.parseVector3(position);
+				} catch(Exception exc) {
+					throw new IllegalArgumentException("Invalid Vector3 for position in node '" + name + "'.");
+				}
+				
+				ArrayList<TextureBinding> texBindings = readNodeTextures(name, xml);
+				
+				HashMap<String, Variant> variants = new HashMap<>();
+				
+				int variantCount = 0;
+				while(xml.getName().equals("variant")) {
+					String variantName = xml.getAttributeValue(null, "name");
+					String variantProg = xml.getAttributeValue(null, "prog");
+					String variantBase = xml.getAttributeValue(null, "base");
+					
+					throwIfNull(variantName, "name", "variant " + variantCount + " in node '" + name + "'");
+					if(variantProg == null && variantBase == null)
+						throw new IllegalArgumentException("Variant " + variantCount + " missing base or program in node '" + name + "'.");
+					if(variantProg != null && variantBase != null)
+						throw new IllegalArgumentException("Variant " + variantCount + " cannot have both base and program in node '" + name + "'.");
+					
+					if(variants.containsKey(variantName))
+						throw new IllegalArgumentException("Variant named '" + variantName + "' already exists in node '" + name + "'.");
+					
+					ArrayList<TextureBinding> variantTexBindings = readNodeTextures(variantName, xml);
+					
+					Variant variant;
+					if(prog != null) {
+						if(!programs.containsKey(prog))
+							throw new IllegalArgumentException("Program named '" + prog + "' in variant '" + variantName + "' in node '" + name + "' does not exist.");
+						
+						variant = new Variant(programs.get(prog), variantTexBindings);
+					}
+					else
+						variant = new Variant(null, variantTexBindings);
+					
+					variants.put(name, variant);
+					
+					xml.require(XmlPullParser.END_TAG, null, "variant");
+					
+					xml.nextTag();
+				}
+				
+				SceneNode node = new SceneNode(meshes.get(mesh), programs.get(prog), nodePos, texBindings, variants);
+				nodes.put(name, node);
+				
+				if(orient != null) {
+					try {
+						node.setOrient(Utils.parseQuaternion(orient));
+					} catch(Exception exc) {
+						throw new IllegalArgumentException("Invalid quaternion for orient at node '" + node + "'.", exc);
+					}
+				}
+				
+				if(scale != null) {
+					try {
+						node.setScale(Utils.parseVector3(scale));
+					} catch(Exception exc) {
+						try {
+							node.setScale(new Vector3(Float.parseFloat(scale)));
+						} catch(Exception exc2) {
+							throw new IllegalArgumentException("Invalid Vector3 or float for scale at node '" + node + "'.");
+						}
+					}
+				}
+				
+				xml.require(XmlPullParser.END_TAG, null, "node");
+				
+				count++;
+			} while(xml.nextTag() == XmlPullParser.START_TAG && xml.getName().equals("node"));
+		}
+	}
+	
+	private ArrayList<TextureBinding> readNodeTextures(String name, XmlPullParser xml) throws IOException, XmlPullParserException {
+		ArrayList<TextureBinding> texBindings = new ArrayList<>();
+		ArrayList<Integer> texUnits = new ArrayList<>();
+		
+		while(xml.nextTag() == XmlPullParser.START_TAG && xml.getName().equals("texture")) {
+			String texName = xml.getAttributeValue(null, "name");
+			String unit = xml.getAttributeValue(null, "unit");
+			
+			throwIfNull(texName, "name", "texture in node '" + name + "'");
+			throwIfNull(unit, "unit", "texture in node '" + name + "'");
+			
+			if(!textures.containsKey(texName))
+				throw new IllegalArgumentException("Texture named '" + texName + "' in node '" + name + "' does not exist.");
+			
+			int texUnit;
+			try {
+				texUnit = Integer.parseInt(unit);
+			} catch(Exception exc) {
+				throw new IllegalArgumentException("Invalid value for unit at texture '" + texName + "' at node '" + name + "'.");
+			}
+			
+			if(texUnits.contains(texUnit))
+				throw new IllegalArgumentException("Texture unit used more than once at texture '" + texName + "' at node '" + name + "'.");
+			
+			texUnits.add(texUnit);
+			
+			final int[] magFilterGLEnums = {
+					GL_NEAREST,
+					GL_LINEAR,
+					GL_NEAREST,
+					GL_LINEAR
+			};
+			
+			final int[] minFilterGLEnums = {
+					GL_NEAREST,
+					GL_LINEAR,
+					GL_NEAREST_MIPMAP_NEAREST,
+					GL_NEAREST_MIPMAP_LINEAR
+			};
+			
+			final int[] edgeGLEnums = {
+					GL_CLAMP_TO_EDGE,
+					GL_CLAMP_TO_BORDER,
+					GL_REPEAT,
+					GL_MIRRORED_REPEAT
+			};
+			
+			final String[] filterNames = {
+					"nearest",
+					"linear",
+					"mipmap nearest",
+					"mipmap linear"
+			};
+			
+			final String[] edgeNames = {
+					"clamp edge",
+					"clamp border",
+					"repeat",
+					"mirror repeat"
+			};
+			
+			String filterMode = xml.getAttributeValue(null, "sampler-filter");
+			throwIfNull(filterMode, "sampler-filter", "texture in node '" + name + "'");
+			
+			int filter = -1;
+			for(int a = 0; a < filterNames.length; a++)
+				if(filterNames[a].equals(filterMode.toLowerCase())) {
+					filter = a;
+					break;
+				}
+			
+			if(filter == -1)
+				throw new IllegalArgumentException("Invalid sampler-filter value '" + filterMode + "' at texture in node '" + name + "'.");
+			
+			String edgeMode = xml.getAttributeValue(null, "sampler-edge");
+			
+			int edge;
+			if(edgeMode == null)
+				edge = 2;
+			else {
+				edge = -1;
+				for(int a = 0; a < edgeNames.length; a++)
+					if(edgeNames[a].equals(edgeMode.toLowerCase())) {
+						edge = a;
+						break;
+					}
+				
+				if(edge == -1)
+					throw new IllegalArgumentException("Invalid sampler-edge value '" + edgeMode + "' at texture in node '" + name + "'.");
+			}
+			
+			String anisoMode = xml.getAttributeValue(null, "sampler-aniso");
+			
+			float aniso;
+			if(anisoMode == null)
+				aniso = 0;
+			else {
+				anisoMode = anisoMode.toLowerCase();
+				
+				float max = glGetFloat(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT);
+				
+				switch(anisoMode) {
+					case "none":
+						aniso = 0;
+						break;
+					case "half":
+						aniso = max / 2;
+						break;
+					case "max":
+						aniso = max;
+						break;
+					default:
+						try {
+							aniso = Integer.parseInt(anisoMode);
+							
+							if(aniso > max)
+								aniso = max;
+						} catch(Exception exc) {
+							throw new IllegalArgumentException("Invalid value for sampler-aniso '" + anisoMode + "' at texture in node '" + name + "'.");
+						}
+				}
+			}
+			
+			int sampler = glGenSamplers();
+			glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, edgeGLEnums[edge]);
+			glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, edgeGLEnums[edge]);
+			glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, edgeGLEnums[edge]);
+			
+			glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, magFilterGLEnums[filter]);
+			glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, minFilterGLEnums[filter]);
+			
+			if(aniso > 0)
+				glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
+			
+			texBindings.add(new TextureBinding(textures.get(texName), texUnit, sampler));
+			
+			xml.next();
+			xml.require(XmlPullParser.END_TAG, null, "texture");
+		}
+		
+		return texBindings;
+	}
+	
+	private void throwIfNull(String s, String name, String type) {
+		if(s == null)
+			throw new IllegalArgumentException("No " + name + " at " + type + ".");
+	}
+	
+	public SceneNode findNode(String nodeName) {
+		return nodes.get(nodeName);
+	}
+	
+	public ShaderProgram findProgram(String programName) {
+		return programs.get(programName).program;
+	}
+	
+	public Mesh findMesh(String meshName) {
+		return meshes.get(meshName);
+	}
+	
+	public SceneTexture findTexture(String textureName) {
+		return textures.get(textureName);
+	}
+	
+	public void render(Matrix4 cameraMatrix) {
+		for(SceneNode node : nodes.values())
+			node.render(cameraMatrix);
+	}
+	
+	public static class Transform {
+		private Quaternion orient = new Quaternion();
+		private Vector3 scale = new Vector3(1);
+		private Vector3 translate = new Vector3();
+		
+		public Matrix4 getMatrix() {
+			return new Matrix4().clearToIdentity().translate(translate).mult(orient.toMatrix()).scale(scale);
+		}
+	}
+	
+	public static class SceneTexture {
+		private int texture;
+		private int type;
+		
+		public SceneTexture(InputStream is, int creationFlags) throws IOException {
+			if(is == null)
+				throw new IOException("Invalid InputStream");
+			
+			ImageSet imageSet = DdsLoader.load(is);
+			texture = TextureGenerator.createTexture(imageSet, creationFlags);
+			type = TextureGenerator.getTextureType(imageSet, creationFlags);
+		}
+	}
+	
+	public static class SceneProgram {
+		private ShaderProgram program;
+		private int matrixUniform;
+		private int normalMatrixUniform;
+		private int invNormalMatrixUniform;
+		
+		public SceneProgram(ShaderProgram program, int matrixUniform, int normalMatrixUniform, int invNormalMatrixUniform) {
+			this.program = program;
+			this.matrixUniform = matrixUniform;
+			this.normalMatrixUniform = normalMatrixUniform;
+			this.invNormalMatrixUniform = invNormalMatrixUniform;
+		}
+	}
+	
+	public static class SceneNode {
+		private Mesh mesh;
+		private Variant baseVariant;
+		
+		private HashMap<String,Variant> variants;
+		private ArrayList<StateBinder> binders;
+		
+		private Transform nodeTransform = new Transform();
+		private Transform objectTransform = new Transform();
+		
+		public SceneNode(Mesh mesh, SceneProgram program, Vector3 nodePos, ArrayList<TextureBinding> texBindings, HashMap<String,Variant> variants) {
+			this.mesh = mesh;
+			
+			baseVariant = new Variant(program, texBindings);
+			
+			this.variants = variants;
+			
+			binders = new ArrayList<>();
+			
+			nodeTransform.translate.set(nodePos);
+		}
+		
+		public void setScale(Vector3 scale) {
+			nodeTransform.scale.set(scale);
+		}
+		
+		public void rotate(Quaternion orient) {
+			nodeTransform.orient.mult(orient);
+		}
+		
+		public void setOrient(Quaternion orient) {
+			nodeTransform.orient.set(orient).normalize();
+		}
+		
+		public Quaternion getOrient() {
+			return nodeTransform.orient.copy();
+		}
+		
+		public void offset(Vector3 offset) {
+			nodeTransform.translate.add(offset);
+		}
+		
+		public void setTranslate(Vector3 translate) {
+			nodeTransform.translate.set(translate);
+		}
+		
+		public void setStateBinder(StateBinder binder) {
+			binders.add(binder);
+		}
+		
+		public int getProgram() {
+			return baseVariant.program.program.getProgram();
+		}
+		
+		public void render(Matrix4 baseMatrix) {
+			if(baseVariant.program != null)
+				render(baseVariant, baseMatrix);
+		}
+		
+		public void render(String variation, Matrix4 baseMatrix) {
+			Variant v = variants.get(variation);
+			if(v == null)
+				throw new IllegalArgumentException("Invalid variation");
+			
+			render(v, baseMatrix);
+		}
+		
+		private void render(Variant variant, Matrix4 baseMatrix) {
+			baseMatrix = baseMatrix.copy().mult(nodeTransform.getMatrix());
+			Matrix4 objectMatrix = baseMatrix.copy().mult(objectTransform.getMatrix());
+			
+			variant.program.program.begin();
+			glUniformMatrix4(variant.program.matrixUniform, false, objectMatrix.toBuffer());
+			
+			if(variant.program.normalMatrixUniform != -1)
+				glUniformMatrix3(variant.program.normalMatrixUniform, false, new Matrix3(objectMatrix.inverse().transpose()).toBuffer());
+			
+			if(variant.program.invNormalMatrixUniform != -1)
+				glUniformMatrix3(variant.program.invNormalMatrixUniform, false, new Matrix3(objectMatrix.inverse().transpose()).inverse().toBuffer());
+			
+			for(StateBinder binder : binders)
+				binder.bindState(variant.program.program.getProgram());
+			
+			for(TextureBinding binding : variant.texBindings) {
+				glActiveTexture(GL_TEXTURE0 + binding.texUnit);
+				glBindTexture(binding.tex.type, binding.tex.texture);
+				glBindSampler(binding.texUnit, binding.sampler);
+			}
+			
+			mesh.render();
+			
+			for(TextureBinding binding : variant.texBindings) {
+				glActiveTexture(GL_TEXTURE0 + binding.texUnit);
+				glBindTexture(binding.tex.type, 0);
+				glBindSampler(binding.texUnit, 0);
+			}
+			
+			for(StateBinder binder : binders)
+				binder.unbindState(variant.program.program.getProgram());
+			
+			variant.program.program.end();
+		}
+		
+		public static class Variant {
+			private SceneProgram program;
+			private ArrayList<TextureBinding> texBindings;
+			
+			public Variant(SceneProgram program, ArrayList<TextureBinding> texBindings) {
+				this.program = program;
+				this.texBindings = texBindings;
+			}
+		}
+	}
+	
+	public static class TextureBinding {
+		private SceneTexture tex;
+		private int texUnit;
+		private int sampler;
+		
+		public TextureBinding(SceneTexture tex, int texUnit, int sampler) {
+			this.tex = tex;
+			this.texUnit = texUnit;
+			this.sampler = sampler;
+		}
+	}
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.