ソースを参照

Merge branch 'next' of https://github.com/blackberry-gaming/GamePlay into next-dgough

Conflicts:
	gameplay-encoder/gameplay-encoder.vcxproj.filters
	gameplay-encoder/src/AnimationChannel.cpp
	gameplay-encoder/src/AnimationChannel.h
	gameplay-encoder/src/DAEChannelTarget.cpp
	gameplay-encoder/src/DAESceneEncoder.cpp
	gameplay-encoder/src/EncoderArguments.cpp
	gameplay-encoder/src/FileIO.cpp
	gameplay-encoder/src/FileIO.h
	gameplay-encoder/src/GPBFile.cpp
	gameplay-encoder/src/Mesh.cpp
	gameplay-encoder/src/MeshSkin.cpp
	gameplay-encoder/src/MeshSkin.h
	gameplay-encoder/src/Node.cpp
	gameplay-encoder/src/Node.h
	gameplay-encoder/src/Scene.h
	gameplay-encoder/src/StringUtil.cpp
	gameplay-encoder/src/StringUtil.h
	gameplay-encoder/src/Vector2.cpp
	gameplay-encoder/src/Vector2.h
	gameplay-encoder/src/Vector3.h
	gameplay-encoder/src/Vector4.h
	gameplay-encoder/src/Vertex.cpp
	gameplay/src/Joint.cpp
Darryl Gough 14 年 前
コミット
acf9cdff74
100 ファイル変更1350 行追加531 行削除
  1. 5 10
      README.md
  2. 155 0
      gameplay-codestyle.xml
  3. 3 1
      gameplay-encoder/gameplay-binary.txt
  4. 10 2
      gameplay-encoder/gameplay-encoder.vcxproj
  5. 18 36
      gameplay-encoder/gameplay-encoder.vcxproj.filters
  6. 1 2
      gameplay-encoder/gameplay-encoder.vcxproj.user
  7. 23 2
      gameplay-encoder/gameplay-encoder.xcodeproj/project.pbxproj
  8. 6 0
      gameplay-encoder/src/Animation.cpp
  9. 8 0
      gameplay-encoder/src/Animation.h
  10. 37 6
      gameplay-encoder/src/AnimationChannel.cpp
  11. 9 4
      gameplay-encoder/src/AnimationChannel.h
  12. 11 0
      gameplay-encoder/src/Animations.cpp
  13. 4 0
      gameplay-encoder/src/Animations.h
  14. 31 10
      gameplay-encoder/src/Base.h
  15. 137 0
      gameplay-encoder/src/BoundingVolume.cpp
  16. 57 0
      gameplay-encoder/src/BoundingVolume.h
  17. 1 1
      gameplay-encoder/src/Camera.cpp
  18. 1 0
      gameplay-encoder/src/Camera.h
  19. 2 1
      gameplay-encoder/src/CameraInstance.cpp
  20. 3 0
      gameplay-encoder/src/CameraInstance.h
  21. 3 1
      gameplay-encoder/src/DAEChannelTarget.cpp
  22. 0 12
      gameplay-encoder/src/DAEChannelTarget.h
  23. 7 4
      gameplay-encoder/src/DAEOptimizer.cpp
  24. 5 11
      gameplay-encoder/src/DAEOptimizer.h
  25. 19 14
      gameplay-encoder/src/DAESceneEncoder.cpp
  26. 4 16
      gameplay-encoder/src/DAESceneEncoder.h
  27. 8 3
      gameplay-encoder/src/DAEUtil.cpp
  28. 6 17
      gameplay-encoder/src/DAEUtil.h
  29. 4 1
      gameplay-encoder/src/Effect.cpp
  30. 1 2
      gameplay-encoder/src/Effect.h
  31. 7 1
      gameplay-encoder/src/EncoderArguments.cpp
  32. 4 2
      gameplay-encoder/src/EncoderArguments.h
  33. 2 2
      gameplay-encoder/src/FileIO.cpp
  34. 2 2
      gameplay-encoder/src/FileIO.h
  35. 2 1
      gameplay-encoder/src/Font.cpp
  36. 1 2
      gameplay-encoder/src/Font.h
  37. 2 1
      gameplay-encoder/src/GPBDecoder.cpp
  38. 1 4
      gameplay-encoder/src/GPBDecoder.h
  39. 15 1
      gameplay-encoder/src/GPBFile.cpp
  40. 14 8
      gameplay-encoder/src/GPBFile.h
  41. 5 3
      gameplay-encoder/src/Glyph.cpp
  42. 1 0
      gameplay-encoder/src/Glyph.h
  43. 2 1
      gameplay-encoder/src/Light.cpp
  44. 1 3
      gameplay-encoder/src/Light.h
  45. 2 2
      gameplay-encoder/src/LightInstance.cpp
  46. 3 1
      gameplay-encoder/src/LightInstance.h
  47. 2 1
      gameplay-encoder/src/Material.cpp
  48. 1 2
      gameplay-encoder/src/Material.h
  49. 2 1
      gameplay-encoder/src/MaterialParameter.cpp
  50. 1 2
      gameplay-encoder/src/MaterialParameter.h
  51. 57 3
      gameplay-encoder/src/Matrix.cpp
  52. 23 2
      gameplay-encoder/src/Matrix.h
  53. 35 16
      gameplay-encoder/src/Mesh.cpp
  54. 13 8
      gameplay-encoder/src/Mesh.h
  55. 2 1
      gameplay-encoder/src/MeshPart.cpp
  56. 1 5
      gameplay-encoder/src/MeshPart.h
  57. 342 16
      gameplay-encoder/src/MeshSkin.cpp
  58. 16 11
      gameplay-encoder/src/MeshSkin.h
  59. 20 1
      gameplay-encoder/src/Model.cpp
  60. 2 3
      gameplay-encoder/src/Model.h
  61. 23 7
      gameplay-encoder/src/Node.cpp
  62. 14 5
      gameplay-encoder/src/Node.h
  63. 2 1
      gameplay-encoder/src/Object.cpp
  64. 2 2
      gameplay-encoder/src/Object.h
  65. 1 1
      gameplay-encoder/src/Quaternion.cpp
  66. 2 1
      gameplay-encoder/src/Quaternion.h
  67. 2 1
      gameplay-encoder/src/Reference.cpp
  68. 1 0
      gameplay-encoder/src/Reference.h
  69. 2 1
      gameplay-encoder/src/ReferenceTable.cpp
  70. 1 3
      gameplay-encoder/src/ReferenceTable.h
  71. 3 3
      gameplay-encoder/src/Scene.cpp
  72. 2 1
      gameplay-encoder/src/Scene.h
  73. 2 3
      gameplay-encoder/src/StringUtil.cpp
  74. 2 3
      gameplay-encoder/src/StringUtil.h
  75. 8 3
      gameplay-encoder/src/TTFFontEncoder.cpp
  76. 5 7
      gameplay-encoder/src/TTFFontEncoder.h
  77. 2 0
      gameplay-encoder/src/Transform.cpp
  78. 3 3
      gameplay-encoder/src/Vector2.cpp
  79. 3 3
      gameplay-encoder/src/Vector3.cpp
  80. 3 3
      gameplay-encoder/src/Vector4.cpp
  81. 2 1
      gameplay-encoder/src/Vertex.cpp
  82. 1 0
      gameplay-encoder/src/Vertex.h
  83. 2 1
      gameplay-encoder/src/VertexElement.cpp
  84. 1 0
      gameplay-encoder/src/VertexElement.h
  85. 1 3
      gameplay-encoder/src/main.cpp
  86. BIN
      gameplay-tutorials/sample01-longboard.pdf
  87. BIN
      gameplay-tutorials/sample02-spaceship.pdf
  88. 0 13
      gameplay.sln
  89. 0 3
      gameplay.xcworkspace/contents.xcworkspacedata
  90. 3 2
      gameplay/gameplay.xcodeproj/project.pbxproj
  91. 43 25
      gameplay/src/Animation.cpp
  92. 8 2
      gameplay/src/Animation.h
  93. 20 29
      gameplay/src/AnimationClip.cpp
  94. 1 3
      gameplay/src/AnimationClip.h
  95. 4 7
      gameplay/src/AnimationController.cpp
  96. 2 1
      gameplay/src/AnimationController.h
  97. 11 79
      gameplay/src/AnimationTarget.cpp
  98. 4 46
      gameplay/src/AnimationTarget.h
  99. 1 1
      gameplay/src/AnimationValue.cpp
  100. 3 2
      gameplay/src/AnimationValue.h

+ 5 - 10
README.md

@@ -2,20 +2,16 @@
 GamePlay is a open-source, cross-platform 3D native gaming framework making it easy to learn and write mobile and desktop games. 
 
 ## Supported Platforms
-- BlackBerry PlayBook 1.0,2.0 (using BlackBerry Native SDK 1.0,2.0)
+- BlackBerry PlayBook 1.0/2.0 (using BlackBerry Native SDK 1.0/2.0)
 - Apple MacOS X (using Apple XCode 4.0)
-- Microsoft Windows 7 (using Microsoft Visual Studio 2010)
+- Microsoft Windows 7 (using Microsoft Visual Studio 2010 Pro/Express)
 	* Requires OpenAL 1.1 (http://connect.creativelabs.com/openal/Downloads/Forms/AllItems.aspx)
 
 ## Roadmap for 'next' branch
-- VisibilityController for node culling.
-- Materials/Shaders supporting multi-texturing for light maps.
-- Billboard and MeshBatch classes.
 - UI Forms with Themed Overlays.
-- Gamepad with Touch Themed Overlays.
-- Physics Sample and Tutorial.
-- New Project Setup Scripts for each platform.
-- Developer Users Guide.
+- Improvements to Lighting.
+- Developer Guide.
+- More Samples and Tutorials.
 - Apple iOS 5 Support.
 
 ## Bug Reporting and Feature Requests
@@ -25,7 +21,6 @@ to the Committers to the project to let them know that you have filed
 an [Issue](https://github.com/blackberry/GamePlay/issues).
 
 ## Disclaimer
-
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 
 PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 

+ 155 - 0
gameplay-codestyle.xml

@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<profiles version="1">
+<profile kind="CodeFormatterProfile" name="BSD/Allman Gaming" version="1">
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.lineSplit" value="1024"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_base_types" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_exception_specification" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_base_types" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_access_specifier" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_exception_specification" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_arguments" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_declarator_list" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_bracket" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.tabulation.size" value="4"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_enumerator_list" value="49"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_declarator_list" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_empty_lines" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_method_declaration" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_arguments" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_base_clause" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_declarator_list" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_brackets" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_bracket" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_block" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_type_declaration" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_expression_list" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.continuation_indentation" value="2"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_expression_list" value="0"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_access_specifier_compare_to_type_header" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_body_declarations_compare_to_namespace_header" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_compact_if" value="0"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_template_parameters" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_expression_list" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_exception_specification" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_identifier_in_function_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_base_clause_in_type_declaration" value="80"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_between_empty_parens_in_exception_specification" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_declaration_compare_to_template_header" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_statements_compare_to_body" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indent_statements_compare_to_block" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_template_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_angle_bracket_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.tabulation.char" value="space"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_parameters" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_block_in_case" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.compact_else_if" value="true"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_base_clause" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_after_template_declaration" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_switch" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.indentation.size" value="4"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_namespace_declaration" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_angle_bracket_in_template_arguments" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.brace_position_for_array_initializer" value="next_line"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_brace_in_namespace_declaration" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_closing_bracket" value="do not insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_new_line_before_while_in_do_statement" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_closing_angle_bracket_in_template_parameters" value="insert"/>
+<setting id="org.eclipse.cdt.core.formatter.insert_space_after_opening_angle_bracket_in_template_arguments" value="do not insert"/>
+</profile>
+</profiles>

+ 3 - 1
gameplay-encoder/gameplay-binary.txt

@@ -16,7 +16,7 @@ Section      Name            Type
 ------------------------------------------------------------------------------------------------------
 Header
              Identifier      byte[9]     = { '«', 'G', 'P', 'B', '»', '\r', '\n', '\x1A', '\n' } 
-             Version         byte[2]     = { 1, 0 }
+             Version         byte[2]     = { 1, 1 }
              References      Reference[]
 Data
              Objects         Object[]
@@ -211,6 +211,8 @@ Reference
                 bindShape               float[16]
                 joints                  xref:Node[]
                 jointsBindPoses         float[] // 16 * joints.length
+                boundingBox             BoundingBox { float[3] min, float[3] max }
+                boundingSphere          BoundingSphere { float[3] center, float radius }
 ------------------------------------------------------------------------------------------------------
 128->Font
                 family                  string

+ 10 - 2
gameplay-encoder/gameplay-encoder.vcxproj

@@ -11,9 +11,11 @@
     </ProjectConfiguration>
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="..\gameplay\src\Curve.cpp" />
     <ClCompile Include="src\Animation.cpp" />
     <ClCompile Include="src\AnimationChannel.cpp" />
     <ClCompile Include="src\Base.cpp" />
+    <ClCompile Include="src\BoundingVolume.cpp" />
     <ClCompile Include="src\Camera.cpp" />
     <ClCompile Include="src\CameraInstance.cpp" />
     <ClCompile Include="src\EncoderArguments.cpp" />
@@ -55,9 +57,11 @@
     <ClCompile Include="src\VertexElement.cpp" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="..\gameplay\src\Curve.h" />
     <ClInclude Include="src\Animation.h" />
     <ClInclude Include="src\AnimationChannel.h" />
     <ClInclude Include="src\Base.h" />
+    <ClInclude Include="src\BoundingVolume.h" />
     <ClInclude Include="src\Camera.h" />
     <ClInclude Include="src\CameraInstance.h" />
     <ClInclude Include="src\EncoderArguments.h" />
@@ -147,12 +151,15 @@
       <Optimization>Disabled</Optimization>
       <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;NO_BOOST;NO_ZAE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <AdditionalIncludeDirectories>../external-deps/freetype2/include;../external-deps/collada-dom/include;../external-deps/collada-dom/include/1.4</AdditionalIncludeDirectories>
+      <DisableLanguageExtensions>
+      </DisableLanguageExtensions>
     </ClCompile>
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalLibraryDirectories>../external-deps/freetype2/lib/win32;../external-deps/collada-dom/lib/win32</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>;../external-deps/freetype2/lib/win32;../external-deps/collada-dom/lib/win32</AdditionalLibraryDirectories>
       <AdditionalDependencies>freetype245.lib;libcollada14dom22-d.lib;%(AdditionalDependencies)</AdditionalDependencies>
+      <IgnoreSpecificDefaultLibraries>MSVCRT</IgnoreSpecificDefaultLibraries>
     </Link>
     <PostBuildEvent>
       <Command>copy /Y "$(ProjectDir)..\external-deps\collada-dom\lib\win32\*.dll" "$(TargetDir)"</Command>
@@ -175,7 +182,8 @@
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
       <AdditionalDependencies>freetype245.lib;libcollada14dom22-d.lib;%(AdditionalDependencies)</AdditionalDependencies>
-      <AdditionalLibraryDirectories>../external-deps/freetype2/lib/win32;../external-deps/collada-dom/lib/win32</AdditionalLibraryDirectories>
+      <AdditionalLibraryDirectories>;../external-deps/freetype2/lib/win32;../external-deps/collada-dom/lib/win32</AdditionalLibraryDirectories>
+      <IgnoreSpecificDefaultLibraries>MSVCRT</IgnoreSpecificDefaultLibraries>
     </Link>
     <PostBuildEvent>
       <Command>copy /Y "$(ProjectDir)..\external-deps\collada-dom\lib\win32\*.dll" "$(TargetDir)"</Command>

+ 18 - 36
gameplay-encoder/gameplay-encoder.vcxproj.filters

@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <ItemGroup>
+    <ClCompile Include="src\DAESceneEncoder.cpp" />
     <ClCompile Include="src\main.cpp" />
     <ClCompile Include="src\ReferenceTable.cpp" />
     <ClCompile Include="src\TTFFontEncoder.cpp" />
@@ -60,6 +61,7 @@
       <Filter>Objects\Animation</Filter>
     </ClCompile>
     <ClCompile Include="src\GPBFile.cpp" />
+    <ClCompile Include="src\DAEChannelTarget.cpp" />
     <ClCompile Include="src\FileIO.cpp" />
     <ClCompile Include="src\StringUtil.cpp" />
     <ClCompile Include="src\Effect.cpp">
@@ -85,28 +87,21 @@
     <ClCompile Include="src\Matrix.cpp">
       <Filter>Math</Filter>
     </ClCompile>
+    <ClCompile Include="src\DAEOptimizer.cpp" />
+    <ClCompile Include="src\DAEUtil.cpp" />
     <ClCompile Include="src\EncoderArguments.cpp" />
     <ClCompile Include="src\Animations.cpp">
       <Filter>Objects\Animation</Filter>
     </ClCompile>
-    <ClCompile Include="src\Base.cpp" />
-    <ClCompile Include="src\FBXSceneEncoder.cpp">
-      <Filter>FBX</Filter>
-    </ClCompile>
-    <ClCompile Include="src\DAEChannelTarget.cpp">
-      <Filter>DAE</Filter>
-    </ClCompile>
-    <ClCompile Include="src\DAEOptimizer.cpp">
-      <Filter>DAE</Filter>
-    </ClCompile>
-    <ClCompile Include="src\DAESceneEncoder.cpp">
-      <Filter>DAE</Filter>
-    </ClCompile>
-    <ClCompile Include="src\DAEUtil.cpp">
-      <Filter>DAE</Filter>
+    <ClCompile Include="..\gameplay\src\Curve.cpp" />
+    <ClCompile Include="src\BoundingVolume.cpp">
+      <Filter>Math</Filter>
     </ClCompile>
+    <ClCompile Include="src\Base.cpp" />
+    <ClCompile Include="src\FBXSceneEncoder.cpp" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="src\DAESceneEncoder.h" />
     <ClInclude Include="src\ReferenceTable.h" />
     <ClInclude Include="src\TTFFontEncoder.h" />
     <ClInclude Include="src\CameraInstance.h">
@@ -165,6 +160,7 @@
       <Filter>Objects\Animation</Filter>
     </ClInclude>
     <ClInclude Include="src\GPBFile.h" />
+    <ClInclude Include="src\DAEChannelTarget.h" />
     <ClInclude Include="src\FileIO.h" />
     <ClInclude Include="src\StringUtil.h" />
     <ClInclude Include="src\Effect.h">
@@ -190,26 +186,18 @@
     <ClInclude Include="src\Matrix.h">
       <Filter>Math</Filter>
     </ClInclude>
+    <ClInclude Include="src\DAEOptimizer.h" />
+    <ClInclude Include="src\DAEUtil.h" />
     <ClInclude Include="src\EncoderArguments.h" />
     <ClInclude Include="src\Animations.h">
       <Filter>Objects\Animation</Filter>
     </ClInclude>
-    <ClInclude Include="src\Base.h" />
-    <ClInclude Include="src\FBXSceneEncoder.h">
-      <Filter>FBX</Filter>
-    </ClInclude>
-    <ClInclude Include="src\DAEUtil.h">
-      <Filter>DAE</Filter>
-    </ClInclude>
-    <ClInclude Include="src\DAEChannelTarget.h">
-      <Filter>DAE</Filter>
-    </ClInclude>
-    <ClInclude Include="src\DAEOptimizer.h">
-      <Filter>DAE</Filter>
-    </ClInclude>
-    <ClInclude Include="src\DAESceneEncoder.h">
-      <Filter>DAE</Filter>
+    <ClInclude Include="..\gameplay\src\Curve.h" />
+    <ClInclude Include="src\BoundingVolume.h">
+      <Filter>Math</Filter>
     </ClInclude>
+    <ClInclude Include="src\Base.h" />
+    <ClInclude Include="src\FBXSceneEncoder.h" />
   </ItemGroup>
   <ItemGroup>
     <Filter Include="Objects">
@@ -239,12 +227,6 @@
     <Filter Include="Math">
       <UniqueIdentifier>{4368ed2b-7fce-423a-a9cb-76a0fdc42858}</UniqueIdentifier>
     </Filter>
-    <Filter Include="FBX">
-      <UniqueIdentifier>{5ee87ce4-f055-46e4-a70f-f1619bae1e09}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="DAE">
-      <UniqueIdentifier>{d3b0fd39-8efe-4978-8d2d-3a74bb6a1deb}</UniqueIdentifier>
-    </Filter>
   </ItemGroup>
   <ItemGroup>
     <None Include="src\Vector2.inl">

+ 1 - 2
gameplay-encoder/gameplay-encoder.vcxproj.user

@@ -1,8 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <LocalDebuggerCommandArguments>
-    </LocalDebuggerCommandArguments>
+    <LocalDebuggerCommandArguments>-groupAnimations group1 movements C:\Git\gaming\GamePlay\gameplay-encoder\res\seymour.dae</LocalDebuggerCommandArguments>
     <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
   </PropertyGroup>
 </Project>

+ 23 - 2
gameplay-encoder/gameplay-encoder.xcodeproj/project.pbxproj

@@ -8,6 +8,8 @@
 
 /* Begin PBXBuildFile section */
 		42475D7C14720ECE00610A6A /* libdom.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 42475D7B14720ECE00610A6A /* libdom.a */; };
+		4283905914896E6C00E2B2F5 /* BoundingVolume.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4283905714896E6C00E2B2F5 /* BoundingVolume.cpp */; };
+		4283906314896F1600E2B2F5 /* Curve.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4283906114896F1600E2B2F5 /* Curve.cpp */; };
 		42C8EE0A14724CD700E43619 /* Animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C8EDB714724CD700E43619 /* Animation.cpp */; };
 		42C8EE0B14724CD700E43619 /* AnimationChannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C8EDB914724CD700E43619 /* AnimationChannel.cpp */; };
 		42C8EE0C14724CD700E43619 /* Animations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 42C8EDBB14724CD700E43619 /* Animations.cpp */; };
@@ -73,6 +75,10 @@
 /* Begin PBXFileReference section */
 		42475CE6147208A000610A6A /* gameplay-encoder */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "gameplay-encoder"; sourceTree = BUILT_PRODUCTS_DIR; };
 		42475D7B14720ECE00610A6A /* libdom.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libdom.a; path = "../external-deps/collada-dom/lib/macos/libdom.a"; sourceTree = "<group>"; };
+		4283905714896E6C00E2B2F5 /* BoundingVolume.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BoundingVolume.cpp; path = src/BoundingVolume.cpp; sourceTree = SOURCE_ROOT; };
+		4283905814896E6C00E2B2F5 /* BoundingVolume.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BoundingVolume.h; path = src/BoundingVolume.h; sourceTree = SOURCE_ROOT; };
+		4283906114896F1600E2B2F5 /* Curve.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Curve.cpp; path = ../gameplay/src/Curve.cpp; sourceTree = "<group>"; };
+		4283906214896F1600E2B2F5 /* Curve.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Curve.h; path = ../gameplay/src/Curve.h; sourceTree = "<group>"; };
 		42C8EDB714724CD700E43619 /* Animation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Animation.cpp; path = src/Animation.cpp; sourceTree = SOURCE_ROOT; };
 		42C8EDB814724CD700E43619 /* Animation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Animation.h; path = src/Animation.h; sourceTree = SOURCE_ROOT; };
 		42C8EDB914724CD700E43619 /* AnimationChannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AnimationChannel.cpp; path = src/AnimationChannel.cpp; sourceTree = SOURCE_ROOT; };
@@ -185,7 +191,8 @@
 		42475CDB147208A000610A6A = {
 			isa = PBXGroup;
 			children = (
-				42475CE9147208A000610A6A /* gameplay-encoder */,
+				4283906414896F3000E2B2F5 /* gameplay */,
+				42475CE9147208A000610A6A /* src */,
 				427D4F44147DC9080076760E /* Libraries */,
 				42475CE7147208A000610A6A /* Products */,
 			);
@@ -199,7 +206,7 @@
 			name = Products;
 			sourceTree = "<group>";
 		};
-		42475CE9147208A000610A6A /* gameplay-encoder */ = {
+		42475CE9147208A000610A6A /* src */ = {
 			isa = PBXGroup;
 			children = (
 				42C8EDB714724CD700E43619 /* Animation.cpp */,
@@ -210,6 +217,8 @@
 				42C8EDBC14724CD700E43619 /* Animations.h */,
 				42C8EDBD14724CD700E43619 /* Base.cpp */,
 				42C8EDBE14724CD700E43619 /* Base.h */,
+				4283905714896E6C00E2B2F5 /* BoundingVolume.cpp */,
+				4283905814896E6C00E2B2F5 /* BoundingVolume.h */,
 				42C8EDBF14724CD700E43619 /* Camera.cpp */,
 				42C8EDC014724CD700E43619 /* Camera.h */,
 				42C8EDC114724CD700E43619 /* CameraInstance.cpp */,
@@ -286,6 +295,7 @@
 				42C8EE0814724CD700E43619 /* VertexElement.cpp */,
 				42C8EE0914724CD700E43619 /* VertexElement.h */,
 			);
+			name = src;
 			path = "gameplay-encoder";
 			sourceTree = "<group>";
 		};
@@ -303,6 +313,15 @@
 			name = Libraries;
 			sourceTree = "<group>";
 		};
+		4283906414896F3000E2B2F5 /* gameplay */ = {
+			isa = PBXGroup;
+			children = (
+				4283906114896F1600E2B2F5 /* Curve.cpp */,
+				4283906214896F1600E2B2F5 /* Curve.h */,
+			);
+			name = gameplay;
+			sourceTree = "<group>";
+		};
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
@@ -395,6 +414,8 @@
 				42C8EE3114724CD700E43619 /* Vector4.cpp in Sources */,
 				42C8EE3214724CD700E43619 /* Vertex.cpp in Sources */,
 				42C8EE3314724CD700E43619 /* VertexElement.cpp in Sources */,
+				4283905914896E6C00E2B2F5 /* BoundingVolume.cpp in Sources */,
+				4283906314896F1600E2B2F5 /* Curve.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 6 - 0
gameplay-encoder/src/Animation.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Animation.h"
 
 namespace gameplay
@@ -55,4 +56,9 @@ unsigned int Animation::getAnimationChannelCount() const
     return _channels.size();
 }
 
+AnimationChannel* Animation::getAnimationChannel(unsigned int index) const
+{
+    return _channels[index];
+}
+
 }

+ 8 - 0
gameplay-encoder/src/Animation.h

@@ -27,6 +27,7 @@ public:
     virtual void writeText(FILE* file);
 
     void add(AnimationChannel* animationChannel);
+
     /**
      * Returns the number of animation channels contained in this animation.
      * 
@@ -34,9 +35,16 @@ public:
      */
     unsigned int getAnimationChannelCount() const;
 
+    /**
+     * Returns the specified animation channel.
+     */
+    AnimationChannel* getAnimationChannel(unsigned int index) const;
+
 private:
+
     std::vector<AnimationChannel*> _channels;
 };
 
 }
+
 #endif

+ 37 - 6
gameplay-encoder/src/AnimationChannel.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "AnimationChannel.h"
 #include "Transform.h"
 
@@ -57,7 +58,42 @@ void AnimationChannel::setInterpolation(unsigned int interpolation)
     _interpolations.push_back(interpolation);
 }
 
-void AnimationChannel::setTargetId(const std::string str)
+const std::string& AnimationChannel::getTargetId() const
+{
+    return _targetId;
+}
+
+unsigned int AnimationChannel::getTargetAttribute() const
+{
+    return _targetAttrib;
+}
+
+const std::vector<float>& AnimationChannel::getKeyValues() const
+{
+    return _keyValues;
+}
+
+const std::vector<float>& AnimationChannel::getKeyTimes() const
+{
+    return _keytimes;
+}
+
+const std::vector<float>& AnimationChannel::getTangentsIn() const
+{
+    return _tangentsIn;
+}
+
+const std::vector<float>& AnimationChannel::getTangentsOut() const
+{
+    return _tangentsOut;
+}
+
+const std::vector<unsigned int>& AnimationChannel::getInterpolationTypes() const
+{
+    return _interpolations;
+}
+
+void AnimationChannel::setTargetId(const std::string& str)
 {
     _targetId = str;
 }
@@ -92,11 +128,6 @@ void AnimationChannel::setInterpolations(const std::vector<unsigned int>& values
     _interpolations = values;
 }
 
-const std::vector<float>& AnimationChannel::getKeyValues() const
-{
-    return _keyValues;
-}
-
 void AnimationChannel::removeDuplicates()
 {
     if (_targetAttrib == Transform::ANIMATE_SCALE_ROTATE_TRANSLATE)

+ 9 - 4
gameplay-encoder/src/AnimationChannel.h

@@ -35,6 +35,8 @@ public:
     virtual void writeBinary(FILE* file);
     virtual void writeText(FILE* file);
 
+    const std::string& getTargetId() const;
+
     /**
      * Sets the interpolation type of the entire animation channel.
      * 
@@ -42,7 +44,7 @@ public:
      */
     void setInterpolation(unsigned int interpolation);
 
-    void setTargetId(const std::string str);
+    void setTargetId(const std::string& str);
     void setTargetAttribute(unsigned int attrib);
 
     void setKeyTimes(const std::vector<float>& values);
@@ -51,7 +53,12 @@ public:
     void setTangentsOut(const std::vector<float>& values);
     void setInterpolations(const std::vector<unsigned int>& values);
 
+    unsigned int getTargetAttribute() const;
     const std::vector<float>& getKeyValues() const;
+    const std::vector<float>& getKeyTimes() const;
+    const std::vector<float>& getTangentsIn() const;
+    const std::vector<float>& getTangentsOut() const;
+    const std::vector<unsigned int>& getInterpolationTypes() const;
 
     void removeDuplicates();
 
@@ -71,7 +78,6 @@ public:
 private:
 
     void deleteRange(size_t begin, size_t end);
-
 private:
 
     std::string _targetId;
@@ -83,7 +89,6 @@ private:
     std::vector<unsigned int> _interpolations;
 };
 
-
 }
-#endif
 
+#endif

+ 11 - 0
gameplay-encoder/src/Animations.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Animations.h"
 
 namespace gameplay
@@ -51,4 +52,14 @@ void Animations::add(Animation* animation)
     _animations.push_back(animation);
 }
 
+unsigned int Animations::getAnimationCount() const
+{
+    return _animations.size();
+}
+
+Animation* Animations::getAnimation(unsigned int index) const
+{
+    return _animations[index];
+}
+
 }

+ 4 - 0
gameplay-encoder/src/Animations.h

@@ -30,10 +30,14 @@ public:
     virtual void writeText(FILE* file);
 
     void add(Animation* animation);
+    unsigned int getAnimationCount() const;
+    Animation* getAnimation(unsigned int index) const;
 
 private:
+
     std::vector<Animation*> _animations;
 };
 
 }
+
 #endif

+ 31 - 10
gameplay-encoder/src/Base.h

@@ -1,23 +1,35 @@
 #ifndef BASE_H_
 #define BASE_H_
 
+// C++ includes
 #include <cmath>
+#include <cstdio>
+#include <cstdlib>
+#include <cstdarg>
+#include <cassert>
+#include <cmath>
+#include <cfloat>
+#include <ctime>
 #include <iostream>
+#include <fstream>
 #include <string>
 #include <vector>
 #include <list>
 #include <map>
-#include <stdio.h>
-#include <stdlib.h>
-#include <iostream>
-#include <string>
+#include <algorithm>
 #include <sys/stat.h>
-#include <vector>
-#include <assert.h>
-#include <math.h>
-#include <float.h>
 
+// Collada includes
+#include <dae.h>
+#include <dae/daeSIDResolver.h>
+#include <dae/domAny.h>
+#include <dom/domCOLLADA.h>
+#include <dom/domConstants.h>
+#include <dom/domElements.h>
+#include <dom/domCamera.h>
+#include <dom/domProfile_COMMON.h>
 
+// Defines
 #ifndef M_1_PI        
 #define M_1_PI                      0.31830988618379067154
 #endif
@@ -59,9 +71,18 @@ enum VertexUsage
     TEXCOORD7 = 15
 };
 
-
 void fillArray(float values[], float value, size_t length);
 
-}
+#define ISZERO(x) (fabs(x) < 0.000001f)
+
+#ifdef NDEBUG
+#define DEBUGPRINT(x)
+#define DEBUGPRINT_VARG(x, ...)
+#else
+#define DEBUGPRINT(x)  printf(x)
+#define DEBUGPRINT_VARG(x, ...) printf(x, __VA_ARGS__)
 #endif
 
+}
+
+#endif

+ 137 - 0
gameplay-encoder/src/BoundingVolume.cpp

@@ -0,0 +1,137 @@
+#include "Base.h"
+#include "BoundingVolume.h"
+
+namespace gameplay
+{
+
+BoundingVolume::BoundingVolume()
+    : radius(0.0f)
+{
+}
+
+void updateMinMax(Vector3* point, Vector3* min, Vector3* max)
+{
+    // Leftmost point.
+    if (point->x < min->x)
+    {
+        min->x = point->x;
+    }
+
+    // Rightmost point.
+    if (point->x > max->x)
+    {
+        max->x = point->x;
+    }
+
+    // Lowest point.
+    if (point->y < min->y)
+    {
+        min->y = point->y;
+    }
+
+    // Highest point.
+    if (point->y > max->y)
+    {
+        max->y = point->y;
+    }
+
+    // Farthest point.
+    if (point->z < min->z)
+    {
+        min->z = point->z;
+    }
+
+    // Nearest point.
+    if (point->z > max->z)
+    {
+        max->z = point->z;
+    }
+}
+
+void BoundingVolume::transform(const Matrix& m)
+{
+    // Transform the bounding sphere
+    m.transformPoint(center, &center);
+    Vector3 translate;
+    m.decompose(&translate, NULL, NULL);
+    float r = radius * translate.x;
+    r = std::max(radius, radius * translate.y);
+    r = std::max(radius, radius * translate.z);
+    radius = r;
+
+    // Transform the bounding box
+    Vector3 corners[8];
+    corners[0].set(min.x, max.y, max.z);
+    // Left-bottom-front.
+    corners[1].set(min.x, min.y, max.z);
+    // Right-bottom-front.
+    corners[2].set(max.x, min.y, max.z);
+    // Right-top-front.
+    corners[3].set(max.x, max.y, max.z);
+    // Right-top-back.
+    corners[4].set(max.x, max.y, min.z);
+    // Right-bottom-back.
+    corners[5].set(max.x, min.y, min.z);
+    // Left-bottom-back.
+    corners[6].set(min.x, min.y, min.z);
+    // Left-top-back.
+    corners[7].set(min.x, max.y, min.z);
+
+    // Transform the corners, recalculating the min and max points along the way.
+    m.transformPoint(corners[0], &corners[0]);
+    Vector3 newMin = corners[0];
+    Vector3 newMax = corners[0];
+    for (int i = 1; i < 8; i++)
+    {
+        m.transformPoint(corners[i], &corners[i]);
+        updateMinMax(&corners[i], &newMin, &newMax);
+    }
+    min = newMin;
+    max = newMax;
+}
+
+void BoundingVolume::merge(const BoundingVolume& v)
+{
+    // Calculate the distance between the two centers.
+    float vx = center.x - v.center.x;
+    float vy = center.y - v.center.y;
+    float vz = center.z - v.center.z;
+    float d = sqrt(vx * vx + vy * vy + vz * vz);
+
+    // If one sphere is contained inside the other, set to the larger sphere.
+    if (d <= (v.radius - radius))
+    {
+        // Use targert volume
+        radius = v.radius;
+        center = v.center;
+    }
+    else if (d <= (radius - v.radius))
+    {
+        // No change
+    }
+    else
+    {
+        // Calculate the unit vector between the two centers.
+        float dI = 1.0f / d;
+        vx *= dI;
+        vy *= dI;
+        vz *= dI;
+
+        // Calculate the new radius.
+        float r = (radius + v.radius + d) * 0.5f;
+
+        // Calculate the new center.
+        float scaleFactor = (r - v.radius);
+        vx = vx * scaleFactor + v.center.x;
+        vy = vy * scaleFactor + v.center.y;
+        vz = vz * scaleFactor + v.center.z;
+
+        // Set the new center and radius.
+        center.x = vx;
+        center.y = vy;
+        center.z = vz;
+        radius = r;
+    }
+}
+
+}

+ 57 - 0
gameplay-encoder/src/BoundingVolume.h

@@ -0,0 +1,57 @@
+#ifndef BOUNDINGVOLUME_H_
+#define BOUNDINGVOLUME_H_
+
+#include "Vector3.h"
+#include "Matrix.h"
+
+namespace gameplay
+{
+
+/**
+ * Represents a 3D bounding volumes, which defines both a
+ * bounding sphere and an axis-aligned bounding box (AABB).
+ */
+class BoundingVolume
+{
+public:
+
+    /**
+     * Radius of the bounding sphere.
+     */
+    float radius;
+
+    /**
+     * Center point of the bounding sphere.
+     */
+    Vector3 center;
+
+    /**
+     * Minimum point of the AABB.
+     */
+    Vector3 min;
+
+    /**
+     * Maximum point of the AABB.
+     */
+    Vector3 max;
+
+    /**
+     * Constructor.
+     */
+    BoundingVolume();
+
+    /**
+     * Transforms this bounding volume by the specified matrix.
+     */
+    void transform(const Matrix& m);
+
+    /**
+     * Merges this bounding volume with the specified one and
+     * stores the result in this BoundingVolume.
+     */
+    void merge(const BoundingVolume& v);
+};
+
+}
+
+#endif

+ 1 - 1
gameplay-encoder/src/Camera.cpp

@@ -1,4 +1,4 @@
-#include <assert.h>
+#include "Base.h"
 #include "Camera.h"
 
 namespace gameplay

+ 1 - 0
gameplay-encoder/src/Camera.h

@@ -54,4 +54,5 @@ private:
 };
 
 }
+
 #endif

+ 2 - 1
gameplay-encoder/src/CameraInstance.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "CameraInstance.h"
 
 namespace gameplay
@@ -50,4 +51,4 @@ void CameraInstance::setCamera(Camera* camera)
     _ref = camera;
 }
 
-}
+}

+ 3 - 0
gameplay-encoder/src/CameraInstance.h

@@ -28,9 +28,12 @@ public:
 
     Camera* getCamera();
     void setCamera(Camera* camera);
+
 private:
+
     Camera* _ref;
 };
 
 }
+
 #endif

+ 3 - 1
gameplay-encoder/src/DAEChannelTarget.cpp

@@ -1,3 +1,5 @@
+
+#include "Base.h"
 #include "DAEChannelTarget.h"
 
 namespace gameplay
@@ -96,4 +98,4 @@ void DAEChannelTarget::getPropertyName(size_t index, std::string* str)
     str->clear();
 }
 
-}
+}

+ 0 - 12
gameplay-encoder/src/DAEChannelTarget.h

@@ -1,18 +1,6 @@
 #ifndef DAECHANNELTARGET_H_
 #define DAECHANNELTARGET_H_
 
-#include <dae.h>
-#include <dae/daeSIDResolver.h>
-#include <dae/domAny.h>
-#include <dom/domCOLLADA.h>
-#include <dom/domConstants.h>
-#include <dom/domElements.h>
-#include <dom/domProfile_COMMON.h>
-
-#include <vector>
-
-#include "Base.h"
-
 namespace gameplay
 {
 

+ 7 - 4
gameplay-encoder/src/DAEOptimizer.cpp

@@ -1,9 +1,10 @@
+#include "Base.h"
 #include "DAEOptimizer.h"
-
-#include <algorithm>
-
 #include "StringUtil.h"
 
+namespace gameplay
+{
+
 DAEOptimizer::DAEOptimizer(domCOLLADA* dom)
 {
     _dom = dom;
@@ -122,4 +123,6 @@ void DAEOptimizer::deleteEmptyAnimations()
     {
         daeElement::removeFromParent(*i);
     }
-}
+}
+
+}

+ 5 - 11
gameplay-encoder/src/DAEOptimizer.h

@@ -1,19 +1,11 @@
 #ifndef DAEOPTIMIZER_H_
 #define DAEOPTIMIZER_H_
 
-#include <dae.h>
-#include <dae/daeSIDResolver.h>
-#include <dae/domAny.h>
-#include <dom/domCOLLADA.h>
-#include <dom/domConstants.h>
-#include <dom/domElements.h>
-#include <dom/domProfile_COMMON.h>
-
-#include <vector>
-
-#include "Base.h"
 #include "DAEUtil.h"
 
+namespace gameplay
+{
+
 /**
  * The DAEOptimizer optimizes a COLLADA dom.
  */
@@ -60,4 +52,6 @@ private:
     std::string _inputPath;
 };
 
+}
+
 #endif

+ 19 - 14
gameplay-encoder/src/DAESceneEncoder.cpp

@@ -1,11 +1,15 @@
-#include <algorithm>
+/*
+ * DAESceneEncoder.h
+ */
+#include "Base.h"
 
 #include "DAESceneEncoder.h"
 #include "DAEOptimizer.h"
 
 //#define ENCODER_PRINT_TIME 1
 
-using namespace gameplay;
+namespace gameplay
+{
 
 DAESceneEncoder::DAESceneEncoder()
     : _collada(NULL), _dom(NULL), file(NULL), _vertexBlendWeights(NULL), _vertexBlendIndices(NULL)
@@ -221,7 +225,7 @@ void DAESceneEncoder::createTrianglesFromPolylist(domMesh* domMesh, domPolylist*
 
 void DAESceneEncoder::write(const std::string& filepath, const EncoderArguments& arguments)
 {
-    _begin = std::clock();
+    _begin = clock();
     const char* nodeId = arguments.getNodeId();
     bool text = arguments.textOutputEnabled();
 
@@ -641,14 +645,14 @@ bool DAESceneEncoder::loadTarget(const domChannelRef& channelRef, AnimationChann
 void DAESceneEncoder::begin()
 {
     #ifdef ENCODER_PRINT_TIME
-    _begin = std::clock();
+    _begin = clock();
     #endif
 }
 
 void DAESceneEncoder::end(const char* str)
 {
     #ifdef ENCODER_PRINT_TIME
-    clock_t time = std::clock() - _begin;
+    clock_t time = clock() - _begin;
     fprintf(stderr,"%5d %s\n", time, str);
     #endif
 }
@@ -1245,9 +1249,9 @@ void DAESceneEncoder::loadSkeleton(domInstance_controller::domSkeleton* skeleton
     }
 
     // Resolve and set joints array for skin
-    std::list<Node*> _joints;
-    const std::list<std::string>& jointNames = skin->getJointNames();
-    for (std::list<std::string>::const_iterator i = jointNames.begin(); i != jointNames.end(); ++i)
+    std::vector<Node*> _joints;
+    const std::vector<std::string>& jointNames = skin->getJointNames();
+    for (std::vector<std::string>::const_iterator i = jointNames.begin(); i != jointNames.end(); i++)
     {
         Object* obj = _gamePlayFile.getFromRefTable(*i);
         if (obj)
@@ -1281,7 +1285,6 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
     domSkin::domJointsRef _joints = skinElement->getJoints();
     domInputLocal_Array& jointInputs = _joints->getInput_array();
 
-
     // Process "JOINT" input semantic first (we need to do this to set the joint count)
     unsigned int jointCount = 0;
     for (unsigned int i = 0; i < jointInputs.getCount(); ++i)
@@ -1295,12 +1298,12 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
         if (equals(inputSemantic, "JOINT"))
         {
             // Get the joint Ids's
-            std::list<std::string> list;
+            std::vector<std::string> list;
             getJointNames(source, list);
 
             // Go through the joint list and conver them from sid to id because the sid information is
             // lost when converting to the gameplay binary format.
-            for (std::list<std::string>::iterator i = list.begin(); i != list.end(); ++i)
+            for (std::vector<std::string>::iterator i = list.begin(); i != list.end(); i++)
             {
                 daeSIDResolver resolver(source->getDocument()->getDomRoot(), i->c_str());
                 daeElement* element = resolver.getElement();
@@ -1319,7 +1322,7 @@ Model* DAESceneEncoder::loadSkin(const domSkin* skinElement)
             jointCount = list.size();
             _jointInverseBindPoseMatrices.reserve(jointCount);
             unsigned int j = 0;
-            for (std::list<std::string>::const_iterator i = list.begin(); i != list.end(); ++i)
+            for (std::vector<std::string>::const_iterator i = list.begin(); i != list.end(); i++)
             {
                 _jointLookupTable[*i] = j++;
             }
@@ -1661,7 +1664,7 @@ Mesh* DAESceneEncoder::loadMesh(const domMesh* meshElement, const std::string& g
         domTriangles* triangles = daeSafeCast<domTriangles>(trianglesArray.get(i));
 
         // Parse the material for this subset
-        //std::string materialName = triangles->getMaterial() == NULL ? _T("") : triangles->getMaterial();
+        //string materialName = triangles->getMaterial() == NULL ? _T("") : triangles->getMaterial();
         //if (materialName.size() > 0)
         ///    subset->material = ParseMaterial(bindMaterial, materialName);
 
@@ -1918,4 +1921,6 @@ DAESceneEncoder::DAEPolygonInput::DAEPolygonInput(void) :
 
 DAESceneEncoder::DAEPolygonInput::~DAEPolygonInput(void)
 {
-}
+}
+
+}

+ 4 - 16
gameplay-encoder/src/DAESceneEncoder.h

@@ -1,21 +1,6 @@
 #ifndef DAESCENEEENCODER_H_
 #define DAESCENEEENCODER_H_
 
-#include <iostream>
-#include <list>
-#include <vector>
-#include <ctime>
-
-#include <dae.h>
-#include <dae/daeSIDResolver.h>
-#include <dae/domAny.h>
-#include <dom/domCOLLADA.h>
-#include <dom/domConstants.h>
-#include <dom/domElements.h>
-#include <dom/domProfile_COMMON.h>
-#include <dom/domCamera.h>
-
-#include "Base.h"
 #include "StringUtil.h"
 #include "Object.h"
 #include "Node.h"
@@ -38,7 +23,8 @@
 #include "DAEUtil.h"
 #include "EncoderArguments.h"
 
-using namespace gameplay;
+namespace gameplay
+{
 
 /**
  * Class for binary encoding a Collada (DAE) file.
@@ -219,4 +205,6 @@ private:
     clock_t _begin;
 };
 
+}
+
 #endif

+ 8 - 3
gameplay-encoder/src/DAEUtil.cpp

@@ -1,6 +1,9 @@
-
+#include "Base.h"
 #include "DAEUtil.h"
 
+namespace gameplay
+{
+
 /**
  * Returns the index of the skeleton in skeletonArray that points to the given node.
  * 
@@ -11,7 +14,7 @@
  */
 int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, const domNodeRef& node);
 
-void getJointNames(const domSourceRef source, std::list<std::string>& list)
+void getJointNames(const domSourceRef source, std::vector<std::string>& list)
 {
     // BLENDER used name_array
     const domName_arrayRef& nameArray = source->getName_array();
@@ -40,7 +43,7 @@ void getJointNames(const domSourceRef source, std::list<std::string>& list)
     }
 }
 
-void getJointNames(const domSkin* skin, std::list<std::string>& list)
+void getJointNames(const domSkin* skin, std::vector<std::string>& list)
 {
     const domSkin::domJointsRef& joints = skin->getJoints();
     const domInputLocal_Array& inputArray = joints->getInput_array();
@@ -301,3 +304,5 @@ int getIndex(const domInstance_controller::domSkeleton_Array& skeletonArray, con
     }
     return -1;
 }
+
+}

+ 6 - 17
gameplay-encoder/src/DAEUtil.h

@@ -1,21 +1,8 @@
 #ifndef DAEUTIL_H_
 #define DAEUTIL_H_
 
-#include <iostream>
-#include <list>
-#include <vector>
-
-#include <dae.h>
-#include <dae/daeSIDResolver.h>
-#include <dae/domAny.h>
-#include <dom/domCOLLADA.h>
-#include <dom/domConstants.h>
-#include <dom/domElements.h>
-#include <dom/domProfile_COMMON.h>
-
-#include "Base.h"
-
-using namespace gameplay;
+namespace gameplay
+{
 
 /**
  * Gets the joint names for the given source and appends them to the given list.
@@ -23,7 +10,7 @@ using namespace gameplay;
  * @param source The source element to search in.
  * @param list The list to append the joint names to.
  */
-void getJointNames(const domSourceRef source, std::list<std::string>& list);
+void getJointNames(const domSourceRef source, std::vector<std::string>& list);
 
 /**
  * Gets the joint names for the given skin and appends them to the given list.
@@ -31,7 +18,7 @@ void getJointNames(const domSourceRef source, std::list<std::string>& list);
  * @param skin The skin element to search in.
  * @param list The list to append the joint names to.
  */
-void getJointNames(const domSkin* skin, std::list<std::string>& list);
+void getJointNames(const domSkin* skin, std::vector<std::string>& list);
 
 /**
  * Gets the input source from the given channel.
@@ -119,4 +106,6 @@ void moveChannelAndSouresToAnimation(domChannelRef& channel, domAnimationRef& an
  */
 bool isEmptyAnimation(domAnimationRef& animation);
 
+}
+
 #endif

+ 4 - 1
gameplay-encoder/src/Effect.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Effect.h"
 
 namespace gameplay
@@ -15,6 +16,7 @@ unsigned int Effect::getTypeId(void) const
 {
     return EFFECT_ID;
 }
+
 const char* Effect::getElementName(void) const
 {
     return "Effect";
@@ -26,6 +28,7 @@ void Effect::writeBinary(FILE* file)
     write(_vertexShader, file);
     write(_fragmentShader, file);
 }
+
 void Effect::writeText(FILE* file)
 {
     fprintElementStart(file);
@@ -34,4 +37,4 @@ void Effect::writeText(FILE* file)
     fprintElementEnd(file);
 }
 
-}
+}

+ 1 - 2
gameplay-encoder/src/Effect.h

@@ -33,7 +33,6 @@ private:
     std::string _fragmentShader;
 };
 
-
 }
-#endif
 
+#endif

+ 7 - 1
gameplay-encoder/src/EncoderArguments.cpp

@@ -1,4 +1,5 @@
-#include <algorithm>
+#include "Base.h"
+
 #include "EncoderArguments.h"
 #include "StringUtil.h"
 
@@ -7,6 +8,9 @@
     #define realpath(A,B)    _fullpath(B,A,PATH_MAX)
 #endif
 
+namespace gameplay
+{
+
 EncoderArguments::EncoderArguments(size_t argc, const char** argv) :
     _fontSize(0),
     _parseError(false),
@@ -295,3 +299,5 @@ void EncoderArguments::replace_char(char* str, char oldChar, char newChar)
         }
     }
 }
+
+}

+ 4 - 2
gameplay-encoder/src/EncoderArguments.h

@@ -1,8 +1,8 @@
 #ifndef ENCODERARGUMENTS_H_
 #define ENCODERARGUMENTS_H_
 
-
-#include "Base.h"
+namespace gameplay
+{
 
 /**
  * EncoderArguments handles parsing the command line arguments for the GamePlay Encoder.
@@ -116,4 +116,6 @@ private:
     std::vector<std::string> _groupAnimationAnimationId;
 };
 
+}
+
 #endif

+ 2 - 2
gameplay-encoder/src/FileIO.cpp

@@ -1,9 +1,9 @@
+#include "Base.h"
 #include "FileIO.h"
 
 namespace gameplay
 {
 
-
 // Writing out a binary file //
 
 void write(unsigned char value, FILE* file)
@@ -180,4 +180,4 @@ void writeVectorText(const Vector4& v, FILE* file)
     fprintf(file, "%f %f %f %f\n", v.x, v.y, v.z, v.w);
 }
 
-}
+}

+ 2 - 2
gameplay-encoder/src/FileIO.h

@@ -1,7 +1,7 @@
 #ifndef FILEIO_H_
 #define FILEIO_H_
 
-#include "Base.h"
+
 #include "Vector2.h"
 #include "Vector3.h"
 #include "Vector4.h"
@@ -134,5 +134,5 @@ void writeVectorBinary(const Vector4& v, FILE* file);
 void writeVectorText(const Vector4& v, FILE* file);
 
 }
-#endif
 
+#endif

+ 2 - 1
gameplay-encoder/src/Font.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Font.h"
 
 namespace gameplay
@@ -50,4 +51,4 @@ void Font::writeText(FILE* file)
     fprintElementEnd(file);
 }
 
-}
+}

+ 1 - 2
gameplay-encoder/src/Font.h

@@ -44,7 +44,6 @@ public:
     };
 };
 
-
 }
-#endif
 
+#endif

+ 2 - 1
gameplay-encoder/src/GPBDecoder.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "GPBDecoder.h"
 
 namespace gameplay
@@ -113,4 +114,4 @@ std::string GPBDecoder::readString(FILE* fp)
     return result;
 }
 
-};
+}

+ 1 - 4
gameplay-encoder/src/GPBDecoder.h

@@ -1,10 +1,6 @@
 #ifndef GPBDECODER_H_
 #define GPBDECODER_H_
 
-#include <iostream>
-#include <list>
-#include <assert.h>
-
 #include "FileIO.h"
 
 namespace gameplay
@@ -36,6 +32,7 @@ public:
     std::string readString(FILE* fp);
 
 private:
+
     FILE* _file;
     FILE* _outFile;
 };

+ 15 - 1
gameplay-encoder/src/GPBFile.cpp

@@ -1,17 +1,26 @@
+#include "Base.h"
 #include "GPBFile.h"
 
 namespace gameplay
 {
 
+static GPBFile* __instance = NULL;
+
 GPBFile::GPBFile(void)
     : _file(NULL), _animationsAdded(false)
 {
+    __instance = this;
 }
 
 GPBFile::~GPBFile(void)
 {
 }
 
+GPBFile* GPBFile::getInstance()
+{
+    return __instance;
+}
+
 void GPBFile::saveBinary(const std::string& filepath)
 {
     _file = fopen(filepath.c_str(), "w+b");
@@ -208,6 +217,11 @@ Node* GPBFile::getNode(const char* id)
     return NULL;
 }
 
+Animations* GPBFile::getAnimations()
+{
+    return &_animations;
+}
+
 void GPBFile::adjust()
 {
     // calculate the ambient color for each scene
@@ -235,4 +249,4 @@ void GPBFile::adjust()
     //   This can be merged into one animation. Same for scale animations.
 }
 
-}
+}

+ 14 - 8
gameplay-encoder/src/GPBFile.h

@@ -1,9 +1,6 @@
 #ifndef GPBFILE_H_
 #define GPBFILE_H_
 
-#include <iostream>
-#include <list>
-
 #include "FileIO.h"
 #include "Object.h"
 #include "Scene.h"
@@ -19,11 +16,12 @@
 
 namespace gameplay
 {
-    /**
-     * Increment the version number when making a change that break binary compatibility.
-     * [0] is major, [1] is minor.
-     */
-    const unsigned char VERSION[2] = {1, 0};
+
+/**
+ * Increment the version number when making a change that break binary compatibility.
+ * [0] is major, [1] is minor.
+ */
+const unsigned char VERSION[2] = {1, 1};
 
 /**
  * The GamePlay Binary file class handles writing the GamePlay Binary file.
@@ -42,6 +40,11 @@ public:
      */
     ~GPBFile(void);
 
+    /**
+     * Returns the GPBFile instance.
+     */
+    static GPBFile* getInstance();
+
     /**
      * Saves the GPBFile as a binary file at filepath.
      *
@@ -84,6 +87,8 @@ public:
     Mesh* getMesh(const char* id);
     Node* getNode(const char* id);
 
+    Animations* getAnimations();
+
     /**
      * Adjusts the game play binary file before it is written.
      */
@@ -104,4 +109,5 @@ private:
 };
 
 }
+
 #endif

+ 5 - 3
gameplay-encoder/src/Glyph.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Glyph.h"
 
 namespace gameplay
@@ -10,10 +11,10 @@ Glyph::Glyph(void) :
     fillArray(uvCoords, 0.0f, 4);
 }
 
-
-Glyph::~Glyph(void)
+    Glyph::~Glyph(void)
 {
 }
+
 const char* Glyph::getElementName(void) const
 {
     return "Glyph";
@@ -28,6 +29,7 @@ void Glyph::writeBinary(FILE* file)
     write(uvCoords, 4, file);
 
 }
+
 void Glyph::writeText(FILE* file)
 {
     fprintElementStart(file);
@@ -37,4 +39,4 @@ void Glyph::writeText(FILE* file)
     fprintElementEnd(file);
 }
 
-}
+}

+ 1 - 0
gameplay-encoder/src/Glyph.h

@@ -30,4 +30,5 @@ public:
 };
 
 }
+
 #endif

+ 2 - 1
gameplay-encoder/src/Light.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Light.h"
 #include "DAESceneEncoder.h"
 
@@ -227,4 +228,4 @@ void Light::setFalloffExponent(float value)
     }
 }
 
-}
+}

+ 1 - 3
gameplay-encoder/src/Light.h

@@ -77,8 +77,6 @@ private:
     float _outerAngle;
 };
 
-
-
 }
-#endif
 
+#endif

+ 2 - 2
gameplay-encoder/src/LightInstance.cpp

@@ -1,5 +1,5 @@
+#include "Base.h"
 #include "LightInstance.h"
-#include "assert.h"
 
 namespace gameplay
 {
@@ -52,4 +52,4 @@ bool LightInstance::isAmbient() const
     return _ref != NULL && _ref->isAmbient();
 }
 
-}
+}

+ 3 - 1
gameplay-encoder/src/LightInstance.h

@@ -32,9 +32,11 @@ public:
     bool isAmbient() const;
 
 private:
+
     Light* _ref;
+
 };
 
 }
-#endif
 
+#endif

+ 2 - 1
gameplay-encoder/src/Material.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Material.h"
 
 namespace gameplay
@@ -35,4 +36,4 @@ void Material::writeText(FILE* file)
     fprintElementEnd(file);
 }
 
-}
+}

+ 1 - 2
gameplay-encoder/src/Material.h

@@ -32,7 +32,6 @@ private:
     Effect* _effect;
 };
 
-
 }
-#endif
 
+#endif

+ 2 - 1
gameplay-encoder/src/MaterialParameter.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "MaterialParameter.h"
 
 namespace gameplay
@@ -35,4 +36,4 @@ void MaterialParameter::writeText(FILE* file)
     fprintElementEnd(file);
 }
 
-}
+}

+ 1 - 2
gameplay-encoder/src/MaterialParameter.h

@@ -30,7 +30,6 @@ private:
     unsigned int _type;
 };
 
-
 }
-#endif
 
+#endif

+ 57 - 3
gameplay-encoder/src/Matrix.cpp

@@ -1,9 +1,9 @@
+#include "Base.h"
 #include "Matrix.h"
 
 namespace gameplay
 {
 
-
 Matrix::Matrix(void)
 {
     setIdentity(m);
@@ -41,6 +41,45 @@ void Matrix::setIdentity(float* matrix)
     memcpy(matrix, MATRIX4F_IDENTITY, MATRIX4F_SIZE);
 }
 
+void Matrix::createRotation(const Quaternion& q, float* dst)
+{
+    assert(dst);
+
+    float x2 = q.x + q.x;
+    float y2 = q.y + q.y;
+    float z2 = q.z + q.z;
+
+    float xx2 = q.x * x2;
+    float yy2 = q.y * y2;
+    float zz2 = q.z * z2;
+    float xy2 = q.x * y2;
+    float xz2 = q.x * z2;
+    float yz2 = q.y * z2;
+    float wx2 = q.w * x2;
+    float wy2 = q.w * y2;
+    float wz2 = q.w * z2;
+
+    dst[0] = 1.0f - yy2 - zz2;
+    dst[1] = xy2 + wz2;
+    dst[2] = xz2 - wy2;
+    dst[3] = 0.0f;
+
+    dst[4] = xy2 - wz2;
+    dst[5] = 1.0f - xx2 - zz2;
+    dst[6] = yz2 + wx2;
+    dst[7] = 0.0f;
+
+    dst[8] = xz2 + wy2;
+    dst[9] = yz2 - wx2;
+    dst[10] = 1.0f - xx2 - yy2;
+    dst[11] = 0.0f;
+
+    dst[12] = 0.0f;
+    dst[13] = 0.0f;
+    dst[14] = 0.0f;
+    dst[15] = 1.0f;
+}
+
 void Matrix::createRotation(float x, float y, float z, float angle, float* dst)
 {
     // Make sure the input axis is normalized
@@ -48,7 +87,7 @@ void Matrix::createRotation(float x, float y, float z, float angle, float* dst)
     if (n != 1.0f)
     {
         // Not normalized
-        n = sqrtf(n);
+        n = sqrt(n);
         if (n > 0.000001f) // prevent divide too close to zero
         {
             n = 1.0f / n;
@@ -167,6 +206,13 @@ void Matrix::scale(float x, float y, float z)
     multiply(m, s, m);
 }
 
+void Matrix::rotate(const Quaternion& q)
+{
+    float r[16];
+    createRotation(q, r);
+    multiply(m, r, m);
+}
+
 void Matrix::rotate(float x, float y, float z, float angle)
 {
     float r[16];
@@ -350,4 +396,12 @@ float Matrix::determinant() const
     return (a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0);
 }
 
-}
+void Matrix::transformPoint(const Vector3& p, Vector3* dst) const
+{
+    dst->set(
+        p.x * m[0] + p.y * m[4] + p.z * m[8] +  m[12],
+        p.x * m[1] + p.y * m[5] + p.z * m[9] +  m[13],
+        p.x * m[2] + p.y * m[6] + p.z * m[10] + m[14] );
+}
+
+}

+ 23 - 2
gameplay-encoder/src/Matrix.h

@@ -12,7 +12,6 @@
 #define TORADIANS(degrees) (degrees * (PI / 180.0f))
 #define TODEGREES(radians) (radians * (180.0f / PI))
 
-
 namespace gameplay
 {
 
@@ -31,6 +30,11 @@ class Matrix
 {
 public:
 
+    /**
+     * Matrix colums.
+     */
+    float m[16];
+
     /**
      * Constructor.
      */
@@ -81,6 +85,11 @@ public:
      */
     static void createScale(float x, float y, float z, float* dst);
 
+    /**
+     * Creates a rotation matrix from the given quaternion.
+     */
+    static void createRotation(const Quaternion& q, float* dst);
+
     /**
      * Creates a rotation matrix from the given axis and angle in degrees.
      */
@@ -121,6 +130,11 @@ public:
      */
     void scale(float x, float y, float z);
 
+    /**
+     * Rotates the matrix by the given Quaternion.
+     */
+    void rotate(const Quaternion& q);
+
     /**
      * Rotates the matrix by the axies specified and angle.
      */
@@ -141,8 +155,15 @@ public:
      */
     void rotateZ(float angle);
 
-    float m[16];
+    /**
+     * Transforms the specified point by this matrix.
+     *
+     * Note that the input vector is treated as a point and NOT a vector.
+     */
+    void transformPoint(const Vector3& p, Vector3* dst) const;
+
 };
 
 }
+
 #endif

+ 35 - 16
gameplay-encoder/src/Mesh.cpp

@@ -1,9 +1,11 @@
+#include "Base.h"
 #include "Mesh.h"
+#include "Model.h"
 
 namespace gameplay
 {
 
-Mesh::Mesh(void)
+Mesh::Mesh(void) : model(NULL)
 {
 }
 
@@ -25,8 +27,8 @@ void Mesh::writeBinary(FILE* file)
 {
     Object::writeBinary(file);
     // vertex formats
-    write(_vertexFormats.size(), file);
-    for (std::vector<VertexElement>::iterator i = _vertexFormats.begin(); i != _vertexFormats.end(); ++i)
+    write(_vertexFormat.size(), file);
+    for (std::vector<VertexElement>::iterator i = _vertexFormat.begin(); i != _vertexFormat.end(); i++)
     {
         i->writeBinary(file);
     }
@@ -73,7 +75,7 @@ void Mesh::writeText(FILE* file)
     // for each VertexFormat
     if (vertices.size() > 0 )
     {
-        for (std::vector<VertexElement>::iterator i = _vertexFormats.begin(); i != _vertexFormats.end(); ++i)
+        for (std::vector<VertexElement>::iterator i = _vertexFormat.begin(); i != _vertexFormat.end(); i++)
         {
             i->writeText(file);
         }
@@ -123,7 +125,7 @@ void Mesh::addMeshPart(Vertex* vertex)
 
 void Mesh::addVetexAttribute(unsigned int usage, unsigned int count)
 {
-    _vertexFormats.push_back(VertexElement(usage, count));
+    _vertexFormat.push_back(VertexElement(usage, count));
 }
 
 size_t Mesh::getVertexCount() const
@@ -131,6 +133,21 @@ size_t Mesh::getVertexCount() const
     return vertices.size();
 }
 
+const Vertex& Mesh::getVertex(unsigned int index) const
+{
+    return vertices[index];
+}
+
+size_t Mesh::getVertexElementCount() const
+{
+    return _vertexFormat.size();
+}
+
+const VertexElement& Mesh::getVertexElement(unsigned int index) const
+{
+    return _vertexFormat[index];
+}
+
 bool Mesh::contains(const Vertex& vertex) const
 {
     return vertexLookupTable.count(vertex) > 0;
@@ -153,13 +170,20 @@ unsigned int Mesh::getVertexIndex(const Vertex& vertex)
 
 void Mesh::computeBounds()
 {
+    // If we have a Model with a MeshSkin associated with it,
+    // compute the bounds from the skin - otherwise compute
+    // it from the local mesh data.
+    if (model && model->getSkin())
+    {
+        model->getSkin()->computeBounds();
+        return;
+    }
+
     bounds.min.x = bounds.min.y = bounds.min.z = FLT_MAX;
     bounds.max.x = bounds.max.y = bounds.max.z = FLT_MIN;
     bounds.center.x = bounds.center.y = bounds.center.z = 0.0f;
     bounds.radius = 0.0f;
-    
-    // for each vertex
-    Vector3 avgPos;
+
     for (std::vector<Vertex>::const_iterator i = vertices.begin(); i != vertices.end(); ++i)
     {
         // Update min/max for this vertex
@@ -175,16 +199,11 @@ void Mesh::computeBounds()
             bounds.max.y = i->position.y;
         if (i->position.z > bounds.max.z)
             bounds.max.z = i->position.z;
-
-        avgPos.x += i->position.x;
-        avgPos.y += i->position.y;
-        avgPos.z += i->position.z;
     }
 
     // Compute center point
-    bounds.center.x = avgPos.x / (float)vertices.size();
-    bounds.center.y = avgPos.y / (float)vertices.size();
-    bounds.center.z = avgPos.z / (float)vertices.size();
+    Vector3::add(bounds.min, bounds.max, &bounds.center);
+    bounds.center.scale(0.5f);
 
     // Compute radius by looping through all points again and finding the max
     // distance between the center point and each vertex position
@@ -198,7 +217,7 @@ void Mesh::computeBounds()
     }
 
     // Convert squared distance to distance for radius
-    bounds.radius = sqrtf(bounds.radius);
+    bounds.radius = sqrt(bounds.radius);
 }
 
 }

+ 13 - 8
gameplay-encoder/src/Mesh.h

@@ -5,12 +5,17 @@
 #include "Object.h"
 #include "MeshPart.h"
 #include "VertexElement.h"
+#include "BoundingVolume.h"
 
 namespace gameplay
 {
 
+class Model;
+
 class Mesh : public Object
 {
+    friend class Model;
+
 public:
 
     /**
@@ -38,6 +43,10 @@ public:
     void addVetexAttribute(unsigned int usage, unsigned int count);
 
     size_t getVertexCount() const;
+    const Vertex& getVertex(unsigned int index) const;
+
+    size_t getVertexElementCount() const;
+    const VertexElement& getVertexElement(unsigned int index) const;
 
     /**
      * Returns true if this MeshPart contains the given Vertex.
@@ -51,15 +60,10 @@ public:
 
     unsigned int getVertexIndex(const Vertex& vertex);
 
+    Model* model;
     std::vector<Vertex> vertices;
     std::vector<MeshPart*> parts;
-    struct
-    {
-        Vector3 min;
-        Vector3 max;
-        Vector3 center;
-        float radius;
-    } bounds;
+    BoundingVolume bounds;
     std::map<Vertex, unsigned int> vertexLookupTable;
 
 private:
@@ -67,9 +71,10 @@ private:
     void computeBounds();
 
 private:
-    std::vector<VertexElement> _vertexFormats;
+    std::vector<VertexElement> _vertexFormat;
 
 };
 
 }
+
 #endif

+ 2 - 1
gameplay-encoder/src/MeshPart.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "MeshPart.h"
 
 namespace gameplay
@@ -104,4 +105,4 @@ void MeshPart::updateIndexFormat(unsigned int newIndex)
     }
 }
 
-}
+}

+ 1 - 5
gameplay-encoder/src/MeshPart.h

@@ -1,8 +1,6 @@
 #ifndef MESHPART_H_
 #define MESHPART_H_
 
-#include <vector>
-
 #include "Base.h"
 #include "Object.h"
 #include "Vertex.h"
@@ -85,8 +83,6 @@ private:
     std::vector<unsigned int> _indices;
 };
 
-
-
 }
-#endif
 
+#endif

+ 342 - 16
gameplay-encoder/src/MeshSkin.cpp

@@ -1,6 +1,12 @@
+#include "Base.h"
 #include "MeshSkin.h"
 #include "Node.h"
 #include "StringUtil.h"
+#include "Mesh.h"
+#include "GPBFile.h"
+#include "Animations.h"
+#include "Transform.h"
+#include "../../gameplay/src/Curve.h"
 #include "Matrix.h"
 
 namespace gameplay
@@ -31,11 +37,28 @@ void MeshSkin::writeBinary(FILE* file)
     Object::writeBinary(file);
     write(_bindShape, 16, file);
     write(_joints.size(), file);
-    for (std::list<Node*>::const_iterator i = _joints.begin(); i != _joints.end(); ++i)
+    for (std::vector<Node*>::const_iterator i = _joints.begin(); i != _joints.end(); i++)
     {
         (*i)->writeBinaryXref(file);
     }
-    write(_bindPoses, file);
+    write(_bindPoses.size() * 16, file);
+    for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); i++)
+    {
+        write(i->m, 16, file);
+    }
+
+    /*
+    // Write joint bounding spheres
+    write((unsigned int)_jointBounds.size(), file);
+    for (unsigned int i = 0; i < _jointBounds.size(); ++i)
+    {
+        BoundingVolume& v = _jointBounds[i];
+        write(v.center.x, file);
+        write(v.center.y, file);
+        write(v.center.z, file);
+        write(v.radius, file);
+    }
+    */
 }
 
 void MeshSkin::writeText(FILE* file)
@@ -45,17 +68,21 @@ void MeshSkin::writeText(FILE* file)
     fprintfMatrix4f(file, _bindShape);
     fprintf(file, "</bindShape>");
     fprintf(file, "<joints>");
-    for (std::list<std::string>::const_iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
+    for (std::vector<std::string>::const_iterator i = _jointNames.begin(); i != _jointNames.end(); i++)
     {
         fprintf(file, "%s ", i->c_str());
     }
     fprintf(file, "</joints>\n");
-    fprintf(file, "<bindPoses count=\"%lu\">", _bindPoses.size());
-    for (std::list<float>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); ++i)
+    fprintf(file, "<bindPoses count=\"%lu\">", _bindPoses.size() * 16);
+    for (std::vector<Matrix>::const_iterator i = _bindPoses.begin(); i != _bindPoses.end(); i++)
     {
-        fprintf(file, "%f ", *i);
+        for (unsigned int j = 0; j < 16; ++j)
+        {
+            fprintf(file, "%f ", i->m[j]);
+        }
     }
     fprintf(file, "</bindPoses>\n");
+
     fprintElementEnd(file);
 }
 
@@ -72,17 +99,17 @@ void MeshSkin::setVertexInfluenceCount(unsigned int count)
     _vertexInfluenceCount = count;
 }
 
-void MeshSkin::setJointNames(const std::list<std::string>& list)
+void MeshSkin::setJointNames(const std::vector<std::string>& list)
 {
     _jointNames = list;
 }
 
-const std::list<std::string>& MeshSkin::getJointNames()
+const std::vector<std::string>& MeshSkin::getJointNames()
 {
     return _jointNames;
 }
 
-void MeshSkin::setJoints(const std::list<Node*>& list)
+void MeshSkin::setJoints(const std::vector<Node*>& list)
 {
     _joints = list;
 }
@@ -91,17 +118,13 @@ void MeshSkin::setBindPoses(std::vector<Matrix>& list)
 {
     for (std::vector<Matrix>::iterator i = list.begin(); i != list.end(); ++i)
     {
-        float* a = i->m;
-        for (int j = 0; j < 16; ++j)
-        {
-            _bindPoses.push_back(a[j]);
-        }
+        _bindPoses.push_back(*i);
     }
 }
 
 bool MeshSkin::hasJoint(const char* id)
 {
-    for (std::list<std::string>::iterator i = _jointNames.begin(); i != _jointNames.end(); ++i)
+    for (std::vector<std::string>::iterator i = _jointNames.begin(); i != _jointNames.end(); i++)
     {
         if (equals(*i, id))
         {
@@ -111,4 +134,307 @@ bool MeshSkin::hasJoint(const char* id)
     return false;
 }
 
-}
+void MeshSkin::computeBounds()
+{
+    // Find the offset of the blend indices and blend weights within the mesh vertices
+    int blendIndexOffset = -1;
+    int blendWeightOffset = -1;
+    for (unsigned int i = 0, count = _mesh->getVertexElementCount(); i < count; ++i)
+    {
+        const VertexElement& e = _mesh->getVertexElement(i);
+        switch (e.usage)
+        {
+        case BLENDINDICES:
+            blendIndexOffset = i;
+            break;
+        case BLENDWEIGHTS:
+            blendWeightOffset = i;
+            break;
+        }
+    }
+    if (blendIndexOffset == -1 || blendWeightOffset == -1)
+    {
+        // Need blend indices and blend weights to calculate skinned bounding volume
+        return;
+    }
+
+    DEBUGPRINT_VARG("\nComputing bounds for skin of mesh: %s\n", _mesh->getId().c_str());
+
+    Node* joint;
+
+    // Get the root joint
+    Node* rootJoint = _joints[0];
+    Node* parent = rootJoint->getParent();
+    while (parent)
+    {
+        // Is this parent in the list of joints that form the skeleton?
+        // If not, then it's simply a parent node to the root joint
+        if (find(_joints.begin(), _joints.end(), parent) != _joints.end())
+        {
+            rootJoint = parent;
+        }
+        parent = parent->getParent();
+    }
+
+    // If the root joint has a parent node, temporarily detach it so that its transform is
+    // not included in the bounding volume calculation below
+    Node* rootJointParent = rootJoint->getParent();
+    if (rootJointParent)
+    {
+        rootJointParent->removeChild(rootJoint);
+    }
+
+    unsigned int jointCount = _joints.size();
+    unsigned int vertexCount = _mesh->getVertexCount();
+
+    DEBUGPRINT_VARG("> %d joints found.\n", jointCount);
+
+    std::vector<AnimationChannel*> channels;
+    std::vector<Node*> channelTargets;
+    std::vector<Curve*> curves;
+    std::vector<Vector3> vertices;
+    _jointBounds.resize(jointCount);
+
+    // Construct a list of all animation channels that target the joints affecting this mesh skin
+    DEBUGPRINT("> Collecting animations...\n");
+    DEBUGPRINT("> 0%%\r");
+    for (unsigned int i = 0; i < jointCount; ++i)
+    {
+        joint = _joints[i];
+
+        // Find all animations that target this joint
+        Animations* animations = GPBFile::getInstance()->getAnimations();
+        for (unsigned int j = 0, animationCount = animations->getAnimationCount(); j < animationCount; ++j)
+        {
+            Animation* animation = animations->getAnimation(j);
+            for (unsigned int k = 0, channelCount = animation->getAnimationChannelCount(); k < channelCount; ++k)
+            {
+                AnimationChannel* channel = animation->getAnimationChannel(k);
+                if (channel->getTargetId() == joint->getId())
+                {
+                    if (find(channels.begin(), channels.end(), channel) == channels.end())
+                    {
+                        channels.push_back(channel);
+                        channelTargets.push_back(joint);
+                    }
+                }
+            }
+        }
+
+        // Calculate the local bounding volume for this joint
+        vertices.clear();
+        BoundingVolume jointBounds;
+        jointBounds.min.set(FLT_MAX, FLT_MAX, FLT_MAX);
+        jointBounds.max.set(FLT_MIN, FLT_MIN, FLT_MIN);
+        for (unsigned int j = 0; j < vertexCount; ++j)
+        {
+            const Vertex& v = _mesh->getVertex(j);
+
+            if ((v.blendIndices.x == i && !ISZERO(v.blendWeights.x)) ||
+                (v.blendIndices.y == i && !ISZERO(v.blendWeights.y)) ||
+                (v.blendIndices.z == i && !ISZERO(v.blendWeights.z)) ||
+                (v.blendIndices.w == i && !ISZERO(v.blendWeights.w)))
+            {
+                vertices.push_back(v.position);
+                // Update box min/max
+                if (v.position.x < jointBounds.min.x)
+                    jointBounds.min.x = v.position.x;
+                if (v.position.y < jointBounds.min.y)
+                    jointBounds.min.y = v.position.y;
+                if (v.position.z < jointBounds.min.z)
+                    jointBounds.min.z = v.position.z;
+                if (v.position.x > jointBounds.max.x)
+                    jointBounds.max.x = v.position.x;
+                if (v.position.y > jointBounds.max.y)
+                    jointBounds.max.y = v.position.y;
+                if (v.position.z > jointBounds.max.z)
+                    jointBounds.max.z = v.position.z;
+            }
+        }
+        if (vertices.size() > 0)
+        {
+            // Compute center point
+            Vector3::add(jointBounds.min, jointBounds.max, &jointBounds.center);
+            jointBounds.center.scale(0.5f);
+            // Compute radius
+            for (unsigned int j = 0, jointVertexCount = vertices.size(); j < jointVertexCount; ++j)
+            {
+                float d = jointBounds.center.distanceSquared(vertices[j]);
+                if (d > jointBounds.radius)
+                    jointBounds.radius = d;
+            }
+            jointBounds.radius = sqrt(jointBounds.radius);
+        }
+        _jointBounds[i] = jointBounds;
+
+        DEBUGPRINT_VARG("> %d%%\r", (int)((float)(i+1) / (float)jointCount * 100.0f));
+    }
+    DEBUGPRINT("\n");
+
+    unsigned int channelCount = channels.size();
+
+    // Create a Curve for each animation channel
+    float maxDuration = 0.0f;
+    DEBUGPRINT("> Building animation curves...\n");
+    DEBUGPRINT("> 0%%\r");
+    for (unsigned int i = 0; i < channelCount; ++i)
+    {
+        AnimationChannel* channel = channels[i];
+
+        const std::vector<float>& keyTimes = channel->getKeyTimes();
+        unsigned int keyCount = keyTimes.size();
+        if (keyCount == 0)
+            continue;
+
+        // Create a curve for this animation channel
+        Curve* curve = NULL;
+        switch (channel->getTargetAttribute())
+        {
+        case Transform::ANIMATE_SCALE_ROTATE_TRANSLATE:
+            curve = new Curve(keyCount, 10);
+            curve->addQuaternionOffset(3);
+            break;
+        }
+        if (curve == NULL)
+        {
+            // Unsupported/not implemented curve type 
+            continue;
+        }
+
+        // Copy key values into a temporary array
+        unsigned int keyValuesCount = channel->getKeyValues().size();
+        float* keyValues = new float[keyValuesCount];
+        for (unsigned int j = 0; j < keyValuesCount; ++j)
+            keyValues[j] = channel->getKeyValues()[j];
+
+        // Determine animation duration
+        float startTime = keyTimes[0];
+        float duration = keyTimes[keyCount-1] - startTime;
+        if (duration > maxDuration)
+            maxDuration = duration;
+
+        // Set curve points
+        float* keyValuesPtr = keyValues;
+        for (unsigned int j = 0; j < keyCount; ++j)
+        {
+            // Store time normalized, between 0-1
+            float t = (keyTimes[j] - startTime) / duration;
+
+            // Set the curve point
+            // TODO: Handle other interpolation types
+            curve->setPoint(j, t, keyValuesPtr, gameplay::Curve::LINEAR);
+
+            // Move to the next point on the curve
+            keyValuesPtr += curve->getComponentCount();
+        }
+
+        delete[] keyValues;
+        keyValues = NULL;
+
+        curves.push_back(curve);
+
+        DEBUGPRINT_VARG("> %d%%\r", (int)((float)(i+1) / (float)channelCount * 100.0f));
+    }
+    DEBUGPRINT("\n");
+
+    // Compute a total combined bounding volume for the MeshSkin that contains all possible
+    // vertex positions for all animations targetting the skin. This rough approximation allows
+    // us to store a volume that can be used for rough intersection tests (such as for visibility
+    // determination) efficiently at runtime.
+
+    // Backup existing node transforms so we can restore them when we are finished
+    Matrix* oldTransforms = new Matrix[jointCount];
+    for (unsigned int i = 0; i < jointCount; ++i)
+    {
+        memcpy(oldTransforms[i].m, _joints[i]->getTransformMatrix().m, 16 * sizeof(float));
+    }
+
+    float time = 0.0f;
+    float srt[10];
+    Matrix temp;
+    Matrix* jointTransforms = new Matrix[jointCount];
+    _mesh->bounds.min.set(FLT_MAX, FLT_MAX, FLT_MAX);
+    _mesh->bounds.max.set(FLT_MIN, FLT_MIN, FLT_MIN);
+    _mesh->bounds.center.set(0, 0, 0);
+    _mesh->bounds.radius = 0;
+    Vector3 skinnedPos;
+    Vector3 tempPos;
+    DEBUGPRINT("> Evaluating joints...\n");
+    DEBUGPRINT("> 0%%\r");
+    BoundingVolume finalBounds;
+    while (time <= maxDuration)
+    {
+        // Evaluate joint transforms at this time interval
+        for (unsigned int i = 0, curveCount = curves.size(); i < curveCount; ++i)
+        {
+            Node* joint = channelTargets[i];
+            Curve* curve = curves[i];
+
+            // Evalulate the curve at this time to get the new value
+            float tn = time / maxDuration;
+            if (tn > 1.0f)
+                tn = 1.0f;
+            curve->evaluate(tn, srt);
+
+            // Update the joint's local transform
+            Matrix::createTranslation(srt[7], srt[8], srt[9], temp.m);
+            temp.rotate(*((Quaternion*)&srt[3]));
+            temp.scale(srt[0], srt[1], srt[2]);
+            joint->setTransformMatrix(temp.m);
+        }
+
+        // Store the final matrix pallette of resovled world space joint matrices
+        std::vector<Matrix>::const_iterator bindPoseItr = _bindPoses.begin();
+        for (unsigned int i = 0; i < jointCount; ++i, bindPoseItr++)
+        {
+            BoundingVolume bounds = _jointBounds[i];
+            if (ISZERO(bounds.radius))
+                continue;
+
+            Matrix& m = jointTransforms[i];
+            Matrix::multiply(_joints[i]->getWorldMatrix().m, bindPoseItr->m, m.m);
+            Matrix::multiply(m.m, _bindShape, m.m);
+
+            // Get a world-space bounding volume for this joint
+            bounds.transform(m);
+            if (ISZERO(finalBounds.radius))
+                finalBounds = bounds;
+            else
+                finalBounds.merge(bounds);
+        }
+
+        // Increment time by 1/30th of second (~ 33 ms)
+        if (time < maxDuration && (time + 33.0f) > maxDuration)
+            time = maxDuration;
+        else
+            time += 33.0f;
+
+        DEBUGPRINT_VARG("> %d%%\r", (int)(time / maxDuration * 100.0f));
+    }
+    DEBUGPRINT("\n");
+
+    // Update the bounding sphere for the mesh
+    _mesh->bounds = finalBounds;
+
+    // Restore original joint transforms
+    for (unsigned int i = 0; i < jointCount; ++i)
+    {
+        _joints[i]->setTransformMatrix(oldTransforms[i].m);
+    }
+
+    // Cleanup
+    for (unsigned int i = 0, curveCount = curves.size(); i < curveCount; ++i)
+    {
+        delete curves[i];
+    }
+    delete[] oldTransforms;
+    delete[] jointTransforms;
+
+    // Restore removed joints
+    if (rootJointParent)
+    {
+        rootJointParent->addChild(rootJoint);
+    }
+}
+
+}

+ 16 - 11
gameplay-encoder/src/MeshSkin.h

@@ -1,20 +1,22 @@
 #ifndef MESHSKIN_H_
 #define MESHSKIN_H_
 
-#include <vector>
-
 #include "Base.h"
 #include "Object.h"
 #include "Matrix.h"
 #include "Animation.h"
+#include "BoundingVolume.h"
 
 namespace gameplay
 {
 
 class Node;
+class Mesh;
 
 class MeshSkin : public Object
 {
+    friend class Model;
+
 public:
 
     /**
@@ -32,15 +34,15 @@ public:
     virtual void writeBinary(FILE* file);
     virtual void writeText(FILE* file);
 
-    const std::list<std::string>& getJointNames();
-
     void setBindShape(const float data[]);
 
     void setVertexInfluenceCount(unsigned int count);
 
-    void setJointNames(const std::list<std::string>& list);
+    void setJointNames(const std::vector<std::string>& list);
+
+    const std::vector<std::string>& getJointNames();
 
-    void setJoints(const std::list<Node*>& list);
+    void setJoints(const std::vector<Node*>& list);
 
     void setBindPoses(std::vector<Matrix>& list);
 
@@ -53,16 +55,19 @@ public:
      */
     bool hasJoint(const char* id);
 
+    void computeBounds();
+
 private:
 
+    Mesh* _mesh;
     float _bindShape[16];
-    std::list<Node*> _joints;
-    std::list<float> _bindPoses;
-
-    std::list<std::string> _jointNames;
-
+    std::vector<Node*> _joints;
+    std::vector<Matrix> _bindPoses;
+    std::vector<std::string> _jointNames;
     unsigned int _vertexInfluenceCount;
+    std::vector<BoundingVolume> _jointBounds;
 };
 
 }
+
 #endif

+ 20 - 1
gameplay-encoder/src/Model.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Model.h"
 
 namespace gameplay
@@ -49,8 +50,11 @@ void Model::writeBinary(FILE* file)
     writeBinaryObjects(_materials, file);
 
 }
+
 void Model::writeText(FILE* file)
 {
+    // Compute mesh bounds before writing
+
     fprintElementStart(file);
     if (_ref != NULL)
     {
@@ -71,11 +75,26 @@ MeshSkin* Model::getSkin()
 void Model::setMesh(Mesh* mesh)
 {
     _ref = mesh;
+
+    if (mesh)
+    {
+        mesh->model = this;
+    }
+
+    if (_ref && _meshSkin)
+    {
+        _meshSkin->_mesh = _ref;
+    }
 }
 
 void Model::setSkin(MeshSkin* skin)
 {
     _meshSkin = skin;
+
+    if (_meshSkin)
+    {
+        _meshSkin->_mesh = _ref;
+    }
 }
 
-}
+}

+ 2 - 3
gameplay-encoder/src/Model.h

@@ -1,8 +1,6 @@
 #ifndef MODEL_H_
 #define MODEL_H_
 
-#include <list>
-
 #include "Object.h"
 #include "Mesh.h"
 #include "MeshSkin.h"
@@ -35,11 +33,12 @@ public:
     void setSkin(MeshSkin* skin);
 
 private:
+
     Mesh* _ref;
     MeshSkin* _meshSkin;
     std::list<Material*> _materials;
 };
 
 }
-#endif
 
+#endif

+ 23 - 7
gameplay-encoder/src/Node.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Node.h"
 #include "Matrix.h"
 
@@ -13,7 +14,6 @@ Node::Node(void) :
     _firstChild(NULL), _lastChild(NULL), _parent(NULL),
     _camera(NULL), _light(NULL), _model(NULL), _joint(false)
 {
-    Matrix::setIdentity(_transform);
 }
 
 Node::~Node(void)
@@ -38,7 +38,7 @@ void Node::writeBinary(FILE* file)
     unsigned int type = _joint ? JOINT : NODE;
     write(type, file);
 
-    write(_transform, 16, file);
+    write(_transform.m, 16, file);
     // children
     write(getChildCount(), file); // write number of children
     for (Node* node = getFirstChild(); node != NULL; node = node->getNextSibling())
@@ -85,7 +85,7 @@ void Node::writeText(FILE* file)
         fprintElementStart(file);
     }
     fprintf(file, "<transform>");
-    fprintfMatrix4f(file, _transform);
+    fprintfMatrix4f(file, _transform.m);
     fprintf(file, "</transform>\n");
 
     // children
@@ -233,17 +233,33 @@ void Node::setModel(Model* model)
     _model = model;
 }
 
+const Matrix& Node::getTransformMatrix() const
+{
+    return _transform;
+}
+
 void Node::setTransformMatrix(float matrix[])
 {
-    for (int i = 0; i < 16; ++i)
+    memcpy(_transform.m, matrix, 16 * sizeof(float));
+}
+
+const Matrix& Node::getWorldMatrix() const
+{
+    if (_parent)
     {
-        _transform[i] = matrix[i];
+        Matrix::multiply(_parent->getWorldMatrix().m, _transform.m, _worldTransform.m);
     }
+    else
+    {
+        memcpy(_worldTransform.m, _transform.m, 16 * sizeof(float));
+    }
+
+    return _worldTransform;
 }
 
 void Node::resetTransformMatrix()
 {
-    Matrix::setIdentity(_transform);
+    Matrix::setIdentity(_transform.m);
 }
 
 void Node::setIsJoint(bool value)
@@ -310,4 +326,4 @@ bool Node::hasLight() const
     return _light != NULL;
 }
 
-}
+}

+ 14 - 5
gameplay-encoder/src/Node.h

@@ -1,8 +1,6 @@
 #ifndef NODE_H_
 #define NODE_H_
 
-#include <list>
-
 #include "Object.h"
 #include "CameraInstance.h"
 #include "LightInstance.h"
@@ -125,12 +123,22 @@ public:
      */
     Model* getModel() const;
 
+    /**
+     * Returns the transform matrix for the node.
+     */
+    const Matrix& getTransformMatrix() const;
+
     /**
      * Sets the transform for this node.
      */
     void setTransformMatrix(float matrix[]);
 
     /**
+     * Returns the resolved world matrix for the node.
+     */
+    const Matrix& getWorldMatrix() const;
+
+    /*
      * Resets the node's transform matrix to the identity matrix.
      */
     void resetTransformMatrix();
@@ -162,7 +170,9 @@ public:
     bool hasLight() const;
     
 private:
-    float _transform[16];
+
+    Matrix _transform;
+    mutable Matrix _worldTransform;
 
     int _childCount;
     Node* _nextSibling;
@@ -178,7 +188,6 @@ private:
     bool _joint;
 };
 
-
 }
-#endif
 
+#endif

+ 2 - 1
gameplay-encoder/src/Object.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Object.h"
 
 namespace gameplay
@@ -76,4 +77,4 @@ void Object::writeBinaryXref(FILE* file)
     write(xref, file);
 }
 
-}
+}

+ 2 - 2
gameplay-encoder/src/Object.h

@@ -1,11 +1,11 @@
 #ifndef OBJ_H_
 #define OBJ_H_
 
-#include "Base.h"
 #include "FileIO.h"
 
 namespace gameplay
 {
+
 /**
  * Object is the abstract base class of all the objects that can be written in the GamePlay Binary file.
  */
@@ -35,7 +35,6 @@ public:
         FONT_ID = 128,
     };
 
-
     /**
      * Constructor.
      */
@@ -137,6 +136,7 @@ public:
     }
 
 private:
+
     /**
      * Saves where this object was written to in the binary file.
      */

+ 1 - 1
gameplay-encoder/src/Quaternion.cpp

@@ -158,7 +158,7 @@ void Quaternion::normalize(Quaternion* dst) const
     if (n == 1.0f)
         return;
 
-    n = sqrtf(n);
+    n = sqrt(n);
     // too close to zero
     if (n < 0.000001f)
         return;

+ 2 - 1
gameplay-encoder/src/Quaternion.h

@@ -304,4 +304,5 @@ private:
 };
 
 }
-#endif /* QUATERNION_H_ */
+
+#endif

+ 2 - 1
gameplay-encoder/src/Reference.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Reference.h"
 
 namespace gameplay
@@ -83,4 +84,4 @@ Object* Reference::getObj()
     return _ref;
 }
 
-}
+}

+ 1 - 0
gameplay-encoder/src/Reference.h

@@ -53,4 +53,5 @@ private:
 };
 
 }
+
 #endif

+ 2 - 1
gameplay-encoder/src/ReferenceTable.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "ReferenceTable.h"
 
 namespace gameplay
@@ -65,4 +66,4 @@ std::map<std::string, Reference>::iterator ReferenceTable::end()
     return _table.end();
 }
 
-}
+}

+ 1 - 3
gameplay-encoder/src/ReferenceTable.h

@@ -1,8 +1,6 @@
 #ifndef REFTABLE_H_
 #define REFTABLE_H_
 
-#include <map>
-
 #include "FileIO.h"
 #include "Reference.h"
 #include "Object.h"
@@ -56,5 +54,5 @@ private:
 };
 
 }
-#endif
 
+#endif

+ 3 - 3
gameplay-encoder/src/Scene.cpp

@@ -1,5 +1,4 @@
-#include <algorithm>
-
+#include "Base.h"
 #include "Scene.h"
 
 namespace gameplay
@@ -40,6 +39,7 @@ void Scene::writeBinary(FILE* file)
     }
     write(_ambientColor, Light::COLOR_SIZE, file);
 }
+
 void Scene::writeText(FILE* file)
 {
     fprintElementStart(file);
@@ -120,4 +120,4 @@ void Scene::calcAmbientColor(const Node* node, float* values) const
     }
 }
 
-}
+}

+ 2 - 1
gameplay-encoder/src/Scene.h

@@ -73,4 +73,5 @@ private:
 };
 
 }
-#endif
+
+#endif

+ 2 - 3
gameplay-encoder/src/StringUtil.cpp

@@ -1,7 +1,6 @@
+#include "Base.h"
 #include "StringUtil.h"
 
-#include <string>
-
 namespace gameplay
 {
 
@@ -119,4 +118,4 @@ std::string getFilenameNoExt(const std::string& filename)
     return filename;
 }
 
-}
+}

+ 2 - 3
gameplay-encoder/src/StringUtil.h

@@ -1,8 +1,6 @@
 #ifndef STRINGUTIL_H_
 #define STRINGUTIL_H_
 
-#include <string>
-
 namespace gameplay
 {
 
@@ -24,4 +22,5 @@ std::string getFilenameFromFilePath(const std::string& filepath);
 std::string getFilenameNoExt(const std::string& filename);
 
 }
-#endif
+
+#endif

+ 8 - 3
gameplay-encoder/src/TTFFontEncoder.cpp

@@ -1,5 +1,9 @@
+#include "Base.h"
 #include "TTFFontEncoder.h"
+#include "GPBFile.h"
 
+namespace gameplay
+{
 
 void drawBitmap(unsigned char* dstBitmap, int x, int y, int dstWidth, unsigned char* srcBitmap, int srcWidth, int srcHeight)
 {
@@ -263,9 +267,8 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
     
     // File header and version.
     char fileHeader[9]     = {'«', 'G', 'P', 'B', '»', '\r', '\n', '\x1A', '\n'};
-    char fileVersion[2]    = {1, 0};
     fwrite(fileHeader, sizeof(char), 9, gpbFp);
-    fwrite(fileVersion, sizeof(char), 2, gpbFp);
+    fwrite(gameplay::VERSION, sizeof(char), 2, gpbFp);
 
     // Write Ref table (for a single font)
     writeUint(gpbFp, 1);                // Ref[] count
@@ -326,4 +329,6 @@ int writeFont(const char* filename, unsigned int fontSize, const char* id, bool
     FT_Done_Face(face);
     FT_Done_FreeType(library);
     return 0;
-}
+}
+
+}

+ 5 - 7
gameplay-encoder/src/TTFFontEncoder.h

@@ -1,9 +1,4 @@
-#include <stdio.h>
 #include <ft2build.h>
-#include "string.h"
-#include <fstream>
-#include <math.h>
-
 #include FT_FREETYPE_H
 
 #define START_INDEX     32
@@ -11,6 +6,8 @@
 
 #define GLYPH_PADDING   4
 
+namespace gameplay
+{
 
 // Structure of Glyph.
 class Glyph
@@ -21,7 +18,6 @@ public:
     float uvCoords[4];
 };
 
-
 void drawBitmap(unsigned char* dstBitmap, int x, int y, int dstWidth, unsigned char* srcBitmap, int srcWidth, int srcHeight);
 
 void writeUint(FILE* fp, unsigned int i);
@@ -30,4 +26,6 @@ void writeFloat(FILE* fp, float f);
 
 void writeString(FILE* fp, const char* str);
 
-int writeFont(const char* filename, unsigned int fontSize, const char* id, bool fontpreview);
+int writeFont(const char* filename, unsigned int fontSize, const char* id, bool fontpreview);
+
+}

+ 2 - 0
gameplay-encoder/src/Transform.cpp

@@ -0,0 +1,2 @@
+#include "Base.h"
+#include "Transform.h"

+ 3 - 3
gameplay-encoder/src/Vector2.cpp

@@ -129,7 +129,7 @@ float Vector2::distance(const Vector2& v) const
     float dx = v.x - x;
     float dy = v.y - y;
 
-    return sqrtf(dx * dx + dy * dy);
+    return sqrt(dx * dx + dy * dy);
 }
 
 float Vector2::distanceSquared(const Vector2& v) const
@@ -151,7 +151,7 @@ float Vector2::dot(const Vector2& v1, const Vector2& v2)
 
 float Vector2::length() const
 {
-    return sqrtf(x * x + y * y);
+    return sqrt(x * x + y * y);
 }
 
 float Vector2::lengthSquared() const
@@ -185,7 +185,7 @@ void Vector2::normalize(Vector2* dst)
     if (n == 1.0f)
         return;
 
-    n = sqrtf(n);
+    n = sqrt(n);
     // Too close to zero.
     if (n < MATH_TOLERANCE)
         return;

+ 3 - 3
gameplay-encoder/src/Vector3.cpp

@@ -94,7 +94,7 @@ float Vector3::angle(const Vector3& v1, const Vector3& v2)
     float dy = v1.z * v2.x - v1.x * v2.z;
     float dz = v1.x * v2.y - v1.y * v2.x;
 
-    return atan2f(sqrtf(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
+    return atan2f(sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
 }
 
 void Vector3::add(const Vector3& v)
@@ -191,7 +191,7 @@ float Vector3::distance(const Vector3& v) const
     float dy = v.y - y;
     float dz = v.z - z;
 
-    return sqrtf(dx * dx + dy * dy + dz * dz);
+    return sqrt(dx * dx + dy * dy + dz * dz);
 }
 
 float Vector3::distanceSquared(const Vector3& v) const
@@ -215,7 +215,7 @@ float Vector3::dot(const Vector3& v1, const Vector3& v2)
 
 float Vector3::length() const
 {
-    return sqrtf(x * x + y * y + z * z);
+    return sqrt(x * x + y * y + z * z);
 }
 
 float Vector3::lengthSquared() const

+ 3 - 3
gameplay-encoder/src/Vector4.cpp

@@ -100,7 +100,7 @@ float Vector4::angle(const Vector4& v1, const Vector4& v2)
     float dy = v1.w * v2.y - v1.y * v2.w - v1.z * v2.x + v1.x * v2.z;
     float dz = v1.w * v2.z - v1.z * v2.w - v1.x * v2.y + v1.y * v2.x;
 
-    return atan2f(sqrtf(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
+    return atan2f(sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2));
 }
 
 void Vector4::add(const Vector4& v)
@@ -191,7 +191,7 @@ float Vector4::distance(const Vector4& v) const
     float dz = v.z - z;
     float dw = v.w - w;
 
-    return sqrtf(dx * dx + dy * dy + dz * dz + dw * dw);
+    return sqrt(dx * dx + dy * dy + dz * dz + dw * dw);
 }
 
 float Vector4::distanceSquared(const Vector4& v) const
@@ -216,7 +216,7 @@ float Vector4::dot(const Vector4& v1, const Vector4& v2)
 
 float Vector4::length() const
 {
-    return sqrtf(x * x + y * y + z * z + w * w);
+    return sqrt(x * x + y * y + z * z + w * w);
 }
 
 

+ 2 - 1
gameplay-encoder/src/Vertex.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "Vertex.h"
 
 namespace gameplay
@@ -104,4 +105,4 @@ void Vertex::normalizeBlendWeight()
     }   
 }
 
-}
+}

+ 1 - 0
gameplay-encoder/src/Vertex.h

@@ -94,4 +94,5 @@ public:
     void normalizeBlendWeight();
 };
 }
+
 #endif

+ 2 - 1
gameplay-encoder/src/VertexElement.cpp

@@ -1,3 +1,4 @@
+#include "Base.h"
 #include "VertexElement.h"
 
 namespace gameplay
@@ -72,4 +73,4 @@ const char* VertexElement::usageStr(unsigned int usage)
     }
 }
 
-}
+}

+ 1 - 0
gameplay-encoder/src/VertexElement.h

@@ -31,4 +31,5 @@ public:
 };
 
 }
+
 #endif

+ 1 - 3
gameplay-encoder/src/main.cpp

@@ -1,5 +1,4 @@
-#include <string>
-
+#include "Base.h"
 #include "DAESceneEncoder.h"
 #include "FBXSceneEncoder.h"
 #include "TTFFontEncoder.h"
@@ -96,4 +95,3 @@ int main(int argc, const char** argv)
 
     return 0;
 }
-

BIN
gameplay-tutorials/sample01-longboard.pdf


BIN
gameplay-tutorials/sample02-spaceship.pdf


+ 0 - 13
gameplay.sln

@@ -25,13 +25,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample03-character", "gamep
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gameplay-encoder", "gameplay-encoder\gameplay-encoder.vcxproj", "{9D69B743-4872-4DD1-8E30-0087C64298D7}"
 EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{D3CA8AE2-3ED6-458B-963A-EDA671E6F51C}"
-EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "sample04-sandbox", "gameplay-samples\sample04-sandbox\sample04-sandbox.vcxproj", "{FA260001-5B2E-41B7-86DD-C7F26DF3A485}"
-	ProjectSection(ProjectDependencies) = postProject
-		{1032BA4B-57EB-4348-9E03-29DD63E80E4A} = {1032BA4B-57EB-4348-9E03-29DD63E80E4A}
-	EndProjectSection
-EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -75,12 +68,6 @@ Global
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.DebugMem|Win32.Build.0 = Debug|Win32
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.Release|Win32.ActiveCfg = Release|Win32
 		{9D69B743-4872-4DD1-8E30-0087C64298D7}.Release|Win32.Build.0 = Release|Win32
-		{FA260001-5B2E-41B7-86DD-C7F26DF3A485}.Debug|Win32.ActiveCfg = Debug|Win32
-		{FA260001-5B2E-41B7-86DD-C7F26DF3A485}.Debug|Win32.Build.0 = Debug|Win32
-		{FA260001-5B2E-41B7-86DD-C7F26DF3A485}.DebugMem|Win32.ActiveCfg = DebugMem|Win32
-		{FA260001-5B2E-41B7-86DD-C7F26DF3A485}.DebugMem|Win32.Build.0 = DebugMem|Win32
-		{FA260001-5B2E-41B7-86DD-C7F26DF3A485}.Release|Win32.ActiveCfg = Release|Win32
-		{FA260001-5B2E-41B7-86DD-C7F26DF3A485}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 0 - 3
gameplay.xcworkspace/contents.xcworkspacedata

@@ -19,7 +19,4 @@
    <FileRef
       location = "group:gameplay-samples/sample03-character/sample03-character.xcodeproj">
    </FileRef>
-   <FileRef
-      location = "group:gameplay-samples/sample04-sandbox/sample04-sandbox.xcodeproj">
-   </FileRef>
 </Workspace>

+ 3 - 2
gameplay/gameplay.xcodeproj/project.pbxproj

@@ -344,7 +344,7 @@
 		4234D98A14686BB6003031B3 = {
 			isa = PBXGroup;
 			children = (
-				4234D9A314686C52003031B3 /* gameplay */,
+				4234D9A314686C52003031B3 /* src */,
 				427D4F42147DC8DE0076760E /* Libraries */,
 				42CCD4AF146D811D00353661 /* Frameworks */,
 				4234D99B14686C52003031B3 /* Products */,
@@ -359,7 +359,7 @@
 			name = Products;
 			sourceTree = "<group>";
 		};
-		4234D9A314686C52003031B3 /* gameplay */ = {
+		4234D9A314686C52003031B3 /* src */ = {
 			isa = PBXGroup;
 			children = (
 				42CD0DB1147D8FF50000361E /* Animation.cpp */,
@@ -512,6 +512,7 @@
 				42CD0E44147D8FF50000361E /* Viewport.cpp */,
 				42CD0E45147D8FF50000361E /* Viewport.h */,
 			);
+			name = src;
 			path = gameplay;
 			sourceTree = "<group>";
 		};

+ 43 - 25
gameplay/src/Animation.cpp

@@ -5,7 +5,6 @@
 #include "AnimationTarget.h"
 #include "Game.h"
 #include "Transform.h"
-#include <string.h>
 #include "Properties.h"
 
 #define ANIMATION_DEFAULT_CLIP_SUFFIX "__default__clip"
@@ -31,15 +30,6 @@ Animation::Animation(const char* id, AnimationTarget* target, int propertyId, un
 
 Animation::~Animation()
 {
-    std::vector<Channel*>::iterator channelIter = _channels.begin();
-    
-    while (channelIter != _channels.end())
-    {
-        SAFE_DELETE(*channelIter);
-        channelIter++;
-    }
-    _channels.clear();
-    
     if (_clips != NULL)
     {
         std::vector<AnimationClip*>::iterator clipIter = _clips->begin();
@@ -47,31 +37,42 @@ Animation::~Animation()
         while (clipIter != _clips->end())
         {   
             AnimationClip* clip = *clipIter;
+            clip->stop();
             SAFE_RELEASE(clip);
             clipIter++;
         }
         _clips->clear();
     }
-
     SAFE_DELETE(_clips);
 
     SAFE_DELETE(_defaultClip);
+
+    /*vector<Channel*>::iterator channelIter = _channels.begin();
+    while (channelIter != _channels.end())
+    {
+        Animation::Channel* channel = *channelIter;
+        channel->_target->removeChannel(channel);
+        SAFE_RELEASE(channel);
+        channelIter++;
+    }*/
+    _channels.clear();
 }
 
-Animation::Channel::Channel(AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration)
-    : _isRelative(false)
+Animation::Channel::Channel(Animation* animation, AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration)
+    : _animation(animation), _target(target), _propertyId(propertyId), _curve(curve), _duration(duration)
 {
     // get property component count, and ensure the property exists on the AnimationTarget by getting the property component count.
-    assert(target->getAnimationPropertyComponentCount(propertyId));
+    assert(_target->getAnimationPropertyComponentCount(propertyId));
+
+    _animation->addRef();
 
-    _target = target;
-    _propertyId = propertyId;
-    _curve = curve;
-    _duration = duration;
+    _target->addChannel(this);
 }
 
 Animation::Channel::~Channel()
 {
+    _animation->removeChannel(this);
+    SAFE_RELEASE(_animation);
     SAFE_DELETE(_curve);
 }
 
@@ -106,7 +107,7 @@ void Animation::createClips(const char* animationFile)
         const char* repeat = pClip->getString("repeatCount");
         if (repeat)
         {
-            if (((std::string)repeat).compare(ANIMATION_INDEFINITE_STR) == 0)
+            if (strcmp(repeat, ANIMATION_INDEFINITE_STR) == 0)
             {
                 clip->setRepeatCount(AnimationClip::REPEAT_INDEFINITE);
             }
@@ -246,10 +247,8 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
 
     SAFE_DELETE(normalizedKeyTimes);
 
-    Channel* channel = new Channel(target, propertyId, curve, duration);
-
+    Channel* channel = new Channel(this, target, propertyId, curve, duration);
     addChannel(channel);
-
     return channel;
 }
 
@@ -295,10 +294,8 @@ Animation::Channel* Animation::createChannel(AnimationTarget* target, int proper
 
     SAFE_DELETE(normalizedKeyTimes);
 
-    Channel* channel = new Channel(target, propertyId, curve, duration);
-
+    Channel* channel = new Channel(this, target, propertyId, curve, duration);
     addChannel(channel);
-
     return channel;
 }
 
@@ -310,6 +307,27 @@ void Animation::addChannel(Channel* channel)
         _duration = channel->_duration;
 }
 
+void Animation::removeChannel(Channel* channel)
+{
+    std::vector<Animation::Channel*>::iterator itr = _channels.begin();
+    while (itr != _channels.end())
+    {
+        Animation::Channel* chan = *itr;
+        if (channel == chan) 
+        {
+            _channels.erase(itr);
+            itr = _channels.end();
+        }
+        else
+        {
+            itr++;
+        }
+    }
+
+    if (_channels.empty())
+        _controller->destroyAnimation(this);
+}
+
 void Animation::createDefaultClip()
 {
     std::string clipId = _id + ANIMATION_DEFAULT_CLIP_SUFFIX;

+ 8 - 2
gameplay/src/Animation.h

@@ -93,18 +93,19 @@ private:
     {
         friend class AnimationClip;
         friend class Animation;
+        friend class AnimationTarget;
 
     private:
 
-        Channel(AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration);
+        Channel(Animation* animation, AnimationTarget* target, int propertyId, Curve* curve, unsigned long duration);
         Channel(const Channel& copy);
         ~Channel();
 
+        Animation* _animation;                // Reference to the animation this channel belongs to.
         AnimationTarget* _target;             // The target of this channel.
         int _propertyId;                      // The target property this channel targets.
         Curve* _curve;                        // The curve used to represent the animation data.
         unsigned long _duration;              // The length of the animation (in milliseconds).
-        bool _isRelative;                     // Whether the data should be treated relatively or not. 
     };
 
     /**
@@ -161,6 +162,11 @@ private:
      * Adds a channel to the animation.
      */
     void addChannel(Channel* channel);
+
+    /**
+     * Removes a channel from the animation.
+     */
+    void removeChannel(Channel* channel);
     
     AnimationController* _controller;       // The AnimationController that this Animation will run on.
     std::string _id;                        // The Animation's ID.

+ 20 - 29
gameplay/src/AnimationClip.cpp

@@ -7,7 +7,6 @@
 
 namespace gameplay
 {
-    int AnimationClip::_crazyCounter = 0;
 
 AnimationClip::AnimationClip(const char* id, Animation* animation, unsigned long startTime, unsigned long endTime)
     : _id(id), _animation(animation), _startTime(startTime), _endTime(endTime), _duration(_endTime - _startTime), _repeatCount(1.0f), 
@@ -29,20 +28,15 @@ AnimationClip::AnimationClip(const char* id, Animation* animation, unsigned long
 
 AnimationClip::~AnimationClip()
 {
-    // Explicitly stop this clip if it's currently playing so it gets removed from the controller
-    if (_isPlaying)
-    {
-        stop();
-    }
-
     std::vector<AnimationValue*>::iterator valueIter = _values.begin();
     while (valueIter != _values.end())
     {
         SAFE_DELETE(*valueIter);
         valueIter++;
     }
+    _values.clear();
 
-    SAFE_DELETE(_crossFadeToClip);
+    SAFE_RELEASE(_crossFadeToClip);
     SAFE_DELETE(_channelPriority);
     SAFE_DELETE(_beginListeners);
     SAFE_DELETE(_endListeners);
@@ -308,10 +302,12 @@ bool AnimationClip::update(unsigned long elapsedTime)
         // Get the current value.
         target->getAnimationPropertyValue(channel->_propertyId, value);
 
+        bool isHighest = false;
         // My channel priority has changed if my priority is greater than the active animation count.
-        if (target->_reassignPriorities)
+        if (!target->_highestPriority)
         {
-            _channelPriority[i] = target->getPriority();
+            target->_highestPriority = channel;
+            value->_isFirstActing = true;
         }
 
         if (_blendWeight != 0.0f)
@@ -321,7 +317,7 @@ bool AnimationClip::update(unsigned long elapsedTime)
 
             if (channel->_curve->_quaternionOffsetsCount == 0)
             {
-                if (_channelPriority[i] == 1)
+                if (value->_isFirstActing)
                 {
                     unsigned int componentCount = value->_componentCount;
                     for (unsigned int j = 0; j < componentCount; j++)
@@ -350,7 +346,7 @@ bool AnimationClip::update(unsigned long elapsedTime)
                 unsigned int quaternionOffsetIndex = 0;
                 unsigned int quaternionOffset = 0;
 
-                if (_channelPriority[i] == 1)
+                if (value->_isFirstActing)
                 {
                     do {
                         quaternionOffset = channel->_curve->_quaternionOffsets[quaternionOffsetIndex];
@@ -434,7 +430,7 @@ bool AnimationClip::update(unsigned long elapsedTime)
                 }
             }
         }
-        else if (_channelPriority[i] == 1)
+        else if (value->_isFirstActing)
         {
             if (channel->_curve->_quaternionOffsetsCount == 0)
             {
@@ -503,17 +499,6 @@ void AnimationClip::onBegin()
         _runningTime = _activeDuration;
     }
 
-    AnimationTarget* target = NULL;
-    unsigned int channelCount = _animation->_channels.size();
-    // Sets the starting value.
-    for (unsigned int i = 0; i < channelCount; i++)
-    {
-        target = _animation->_channels[i]->_target;
-
-        target->increaseActiveAnimationCount();
-        _channelPriority[i] = target->getPriority();
-    }
-
     // Notify begin listeners.. if any.
     if (_beginListeners)
     {
@@ -528,15 +513,21 @@ void AnimationClip::onBegin()
 
 void AnimationClip::onEnd()
 {
+    AnimationValue* value;
+    Animation::Channel* channel = NULL;
     AnimationTarget* target = NULL;
     unsigned int channelCount = _animation->_channels.size();
     for (unsigned int i = 0; i < channelCount; i++)
     {
-        target = _animation->_channels[i]->_target;
-        
-        // Decrease active animation count on target and reset the channel priority
-        target->decreaseActiveAnimationCount();
-        _channelPriority[i] = 0;
+        value = _values[i];
+
+        if (value->_isFirstActing)
+        {
+            channel = _animation->_channels[i];
+            target = channel->_target;
+            target->_highestPriority = NULL;
+            value->_isFirstActing = false;
+        }
     }
 
     _blendWeight = 1.0f;

+ 1 - 3
gameplay/src/AnimationClip.h

@@ -27,8 +27,6 @@ public:
      */
     static const unsigned int REPEAT_INDEFINITE = 0;
 
-    static int _crazyCounter;
-
     /**
      * Defines an animation event listener.
      */
@@ -230,7 +228,7 @@ private:
     void onEnd();
 
     std::string _id;                          // AnimationClip ID.
-    Animation* _animation;                    // Animations that this clip plays in parallel.
+    Animation* _animation;                    // The Animation this clip is created from.
     unsigned long _startTime;                 // Start time of the clip.
     unsigned long _endTime;                   // End time of the clip.
     unsigned long _duration;                  // The total duration.

+ 4 - 7
gameplay/src/AnimationController.cpp

@@ -28,9 +28,7 @@ Animation* AnimationController::createAnimation(const char* id, AnimationTarget*
     animation = new Animation(id, target, propertyId, keyCount, keyTimes, keyValues, type);
 
     addAnimation(animation);
-
-    target->addAnimation(animation);
-
+    
     return animation;
 }
 
@@ -46,8 +44,6 @@ Animation* AnimationController::createAnimation(const char* id, AnimationTarget*
 
     addAnimation(animation);
 
-    target->addAnimation(animation);
-
     return animation;
 }
 
@@ -130,6 +126,7 @@ void AnimationController::initialize()
 
 void AnimationController::finalize()
 {
+    stopAllAnimations();
     _state = PAUSED;
 }
 
@@ -218,6 +215,8 @@ void AnimationController::destroyAnimation(Animation* animation)
     {
         if (animation == *itr)
         {
+            Animation* animation = *itr;
+            SAFE_RELEASE(animation);
             _animations.erase(itr);
             return;
         }
@@ -227,8 +226,6 @@ void AnimationController::destroyAnimation(Animation* animation)
 
 void AnimationController::destroyAllAnimations()
 {
-    stopAllAnimations();
-
     std::vector<Animation*>::iterator itr = _animations.begin();
     
     while (itr != _animations.end())

+ 2 - 1
gameplay/src/AnimationController.h

@@ -14,6 +14,7 @@ namespace gameplay
 class AnimationController
 {
     friend class Game;
+    friend class Animation;
     friend class AnimationClip;
 
 public:
@@ -180,7 +181,7 @@ private:
     
     State _state;                               // The current state of the AnimationController.
     std::list<AnimationClip*> _runningClips;    // A list of currently running AnimationClips.
-    std::vector<Animation*> _animations;
+    std::vector<Animation*> _animations;        // A list of animations registered with the AnimationController
 };
 
 }

+ 11 - 79
gameplay/src/AnimationTarget.cpp

@@ -2,104 +2,36 @@
 #include "AnimationTarget.h"
 #include "Animation.h"
 #include "Game.h"
-#include <string.h>
 #include "Transform.h"
 
 namespace gameplay
 {
 
 AnimationTarget::AnimationTarget()
-    : _targetType(SCALAR), _activeAnimationCount(0), _currentPriority(0), _animations(NULL), _reassignPriorities(false)
+    : _targetType(SCALAR), _highestPriority(NULL), _animationChannels(NULL)
 {
 }
 
 AnimationTarget::~AnimationTarget()
 {
-    if (_animations)
+    if (_animationChannels)
     {
-        std::vector<Animation*>::iterator animationIter = _animations->begin();
-        while (animationIter != _animations->end())
+        std::vector<Animation::Channel*>::iterator itr = _animationChannels->begin();
+        while (itr != _animationChannels->end())
         {
-            SAFE_RELEASE((*animationIter));
-            animationIter++;
+            SAFE_DELETE((*itr));
+            itr++;
         }
-        SAFE_DELETE(_animations);
+        SAFE_DELETE(_animationChannels);
     }
 }
 
-void AnimationTarget::addAnimation(Animation* animation)
+void AnimationTarget::addChannel(Animation::Channel* channel)
 {
-    if (_animations == NULL)
-    {
-        _animations = new std::vector<Animation*>;
-    }
-
-    _animations->push_back(animation);
-
-    animation->addRef();
-}
-
-unsigned int AnimationTarget::getAnimationCount() const
-{
-    if (_animations)
-        return _animations->size();
-
-    return 0;
-}
-
-Animation* AnimationTarget::getAnimation(unsigned int index) const
-{
-    if (_animations)
-        return _animations->at(index);
-    else
-        return 0;
-}
-
-Animation* AnimationTarget::getAnimation(const char* id) const
-{
-    if (_animations)
-    {
-        std::vector<Animation*>::iterator animationIter = _animations->begin();
-        while(animationIter != _animations->end())
-        {
-            if ((*animationIter)->_id.compare(id) == 0)
-            {
-                return *animationIter;
-            }
-
-            animationIter++;
-        }
-    }
-    
-    return NULL;
-}
-
-void AnimationTarget::increaseActiveAnimationCount()
-{
-    ++_activeAnimationCount;
-}
-
-void AnimationTarget::decreaseActiveAnimationCount()
-{
-    --_activeAnimationCount;
-
-    _reassignPriorities = true;
-    _currentPriority = 0;
-}
-
-unsigned int AnimationTarget::getPriority() 
-{
-    if (_reassignPriorities)
-    {
-        ++_currentPriority;
-
-        if (_currentPriority == _activeAnimationCount)
-            _reassignPriorities = false;
-
-        return _currentPriority;
-    }
+    if (_animationChannels == NULL)
+        _animationChannels = new std::vector<Animation::Channel*>;
 
-    return _activeAnimationCount;
+    _animationChannels->push_back(channel);
 }
 
 }

+ 4 - 46
gameplay/src/AnimationTarget.h

@@ -14,7 +14,7 @@ class AnimationValue;
  * Defines an interface allowing animation to target
  * an object for changing its animation properties.
  */
-class AnimationTarget : public Ref
+class AnimationTarget
 {
     friend class Animation;
     friend class AnimationClip;
@@ -47,31 +47,6 @@ public:
      */
     virtual void setAnimationPropertyValue(int propertyId, AnimationValue* value) = 0;
 
-    /**
-     * Gets the number of Animations on this target.
-     * 
-     * @return The number of Animations targeting this object.
-     */
-    unsigned int getAnimationCount() const;
-
-    /**
-     * Gets the Animation with the given index.
-     * 
-     * @param index The index of the Animation to return.
-     *
-     * @return The Animation at the given index.
-     */
-    Animation* getAnimation(unsigned int index) const;
-
-    /**
-     * Finds the Animation with the given ID.
-     * 
-     * @param id The ID of the Animation to get.
-     * 
-     * @return The Animation with the given ID. NULL if the Animation is not found.
-     */
-    Animation* getAnimation(const char* id) const;
-
 protected:
     
     enum TargetType
@@ -90,7 +65,7 @@ protected:
      */
     virtual ~AnimationTarget();
 
-    void addAnimation(Animation* animation);
+    void addChannel(Animation::Channel* animation);
 
     TargetType _targetType;             // The type of target this is.
 
@@ -101,25 +76,8 @@ private:
      */
     AnimationTarget(const AnimationTarget& copy);
 
-    /**
-     * Increases the active animation count on the target by one.
-     */
-    void increaseActiveAnimationCount();
-
-    /**
-     * Decreases the active animation count on the target by one.
-     */
-    void decreaseActiveAnimationCount();
-
-    /**
-     * Gets the priority to assign to the channel when reassigning priorities.
-     */
-    unsigned int getPriority();
-
-    unsigned int _activeAnimationCount;        // The number of active animations targeting this AnimationTarget.
-    bool _reassignPriorities;                  // A flag to indicate that channel priorities for this AnimationTarget need to be reassigned
-    unsigned int _currentPriority;             // Used to keep track of the current priority when reassigning channel priorities
-    std::vector<Animation*>* _animations;      // Collection of all animations on that target the AnimationTarget
+    Animation::Channel* _highestPriority;
+    std::vector<Animation::Channel*>* _animationChannels;   // Collection of all animation channels that target the AnimationTarget
 
 };
 }

+ 1 - 1
gameplay/src/AnimationValue.cpp

@@ -5,7 +5,7 @@ namespace gameplay
 {
 
 AnimationValue::AnimationValue(unsigned int componentCount)
-  : _componentCount(componentCount), _componentSize(componentCount * sizeof(float))
+  : _isFirstActing(false), _componentCount(componentCount), _componentSize(componentCount * sizeof(float))
 {
     _currentValue = new float[_componentCount];
     _interpolatedValue = new float[_componentCount];

+ 3 - 2
gameplay/src/AnimationValue.h

@@ -72,10 +72,11 @@ private:
      */
     ~AnimationValue();
 
+    bool _isFirstActing;            // Flag indicating if this value's channel is the first to act on the target.
     unsigned int _componentCount;   // The number of float values for the property.
-    unsigned int _componentSize;
+    unsigned int _componentSize;    // The number of bytes of memory the property is.
     float* _currentValue;           // The current value of the property.
-    float* _interpolatedValue;
+    float* _interpolatedValue;      // The last interpolated value of the property.
 };
 
 }

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません