Browse Source

Implemented physics simulation using Bullet
Added an implementation of RigidBodyComponent
Added component creation in PhysicsScene
Added a PhysicsMotionState implementation that ties position and rotation synchronization between the physics simulation and the rest of the engine
Added subject-observer linking of new components in WorldScene during object creation
Added a macro for creating constant string enum name arrays, in EnumFactory, alleviating the need of manually copying enum names and declaring an array
Added more ErrorCodes and ErrorSources
Added a check for the presence of GameObject property in a map, during the scene loading
Added spatial data update during change handling in SpatialComponent::ChangeOccurred, so new posted changes can be retrieved with up-to-date data
Added a lua script for testing kinematics of the physics engine (Kinematic_test.lua)
Fixed an issue of LuaComponent not reseting the GUI and Spatial changes after an update

Paul A 3 years ago
parent
commit
5cefbb89d4

+ 99 - 12
Praxis3D/Data/Maps/componentTest.pmap

@@ -71,19 +71,19 @@
 				{
 				{
 					"LocalPosition": "0.0f, 0.5f, 0.0f",
 					"LocalPosition": "0.0f, 0.5f, 0.0f",
 					"LocalRotation": "0.0f, 45.0f, 0.0f",
 					"LocalRotation": "0.0f, 45.0f, 0.0f",
-					"LocalScale": "10.0f, 10.0f, 10.0f"
+					"LocalScale": "1.0f, 1.0f, 1.0f"
 				}
 				}
 			},
 			},
 			"Physics":
 			"Physics":
 			{
 			{
-				"RigidBody":
+				"RigidBodyComponent":
 				{
 				{
 					"CollisionShape":
 					"CollisionShape":
 					{
 					{
 						"Type": "Box",
 						"Type": "Box",
-						"Size": "50.0f, 50.0f, 50.0f"
+						"Size": "100.01f, 0.25f, 100.01f"
 					},
 					},
-					"Mass": "10.0f"
+					"Mass": "0.0f"
 				}
 				}
 			},
 			},
 			"Rendering":
 			"Rendering":
@@ -128,11 +128,6 @@
 						}
 						}
 					]
 					]
 				}
 				}
-//				"Shaders":
-//				{
-//					"FragmentShader": "geometryPassInf.frag",
-//					"VertexShader": "geometryPassInf.vert"
-//				}
 			}
 			}
 		},
 		},
 		{
 		{
@@ -143,8 +138,79 @@
 			{
 			{
 				"SpatialComponent":
 				"SpatialComponent":
 				{
 				{
-					"LocalPosition": "0.0f, 5.0f, 0.0f",
-					"LocalRotation": "0.0f, 45.0f, 0.0f",
+					"LocalPosition": "0.0f, 30.0f, 0.0f",
+					"LocalRotation": "0.0f, 40.0f, 0.0f",
+					"LocalScale": "2.0f, 2.0f, 2.0f"
+				}
+			},
+			"Rendering":
+			{
+				"ModelComponent":
+				{
+					"Models":
+					[
+						{
+							"Filename": "cube.obj",
+							"Meshes":
+							[
+								{
+									"Index": "0",
+									"AlphaThreshold": "0.0f",
+									"HeightScale": "0.0f",
+									"Materials":
+									{
+										"Diffuse":
+										{
+											"Filename": "Metal_CleanPaintedWithChips_2k_alb.tga",
+											"TextureScale": "2.0f, 2.0f"
+										},
+										"Normal":
+										{
+											"Filename": "Metal_CleanPaintedWithChips_2k_n.tga",
+											"TextureScale": "1.0f, 1.0f"
+										},
+										"Emissive":
+										{
+											"Filename": "default_emissive.png",
+											"TextureScale": "1.0f, 1.0f"
+										},
+										"RMHAO":
+										{
+											"Filename": "Metal_CleanPaintedWithChips_RMHAO3.tga",
+											"TextureScale": "1.0f, 1.0f"
+										}
+									}
+								}
+							]
+						}
+					]
+				}
+			},
+			"Physics":
+			{
+				"RigidBodyComponent":
+				{
+					"Mass": "10.0f",
+					"Restitution": "0.5f",
+					"Friction": "0.5f",
+					"CollisionShape":
+					{
+						"Type": "Box",
+						"Size": "2.0f, 2.0f, 2.0f"
+					}
+				}
+			}
+		},
+		{
+			"ID": "33",
+			"Name": "Cube 2",
+			"Parent": "0",
+			"World":
+			{
+				"SpatialComponent":
+				{
+					"LocalPosition": "3.0f, 3.0f, 0.0f",
+					"LocalRotation": "0.0f, 0.0f, 0.0f",
 					"LocalScale": "2.0f, 2.0f, 2.0f"
 					"LocalScale": "2.0f, 2.0f, 2.0f"
 				}
 				}
 			},
 			},
@@ -190,6 +256,27 @@
 						}
 						}
 					]
 					]
 				}
 				}
+			},
+			"Physics":
+			{
+				"RigidBodyComponent":
+				{
+					"Mass": "0.0f",
+					"Kinematic": "true",
+					"Restitution": "0.1f",
+					"CollisionShape":
+					{
+						"Type": "Box",
+						"Size": "2.0f"
+					}
+				}
+			},
+			"Script":
+			{
+				"LuaComponent":
+				{
+					"Filename": "Kinematic_test.lua"
+				}
 			}
 			}
 		},
 		},
 		{
 		{
@@ -332,7 +419,7 @@
 			{
 			{
 				"SpatialComponent":
 				"SpatialComponent":
 				{
 				{
-					"LocalRotation": "-45.0f, 45.0f, 0.0f"
+					"LocalRotation": "-60.0f, 0.0f, 0.0f"
 				}
 				}
 			},
 			},
 			"Rendering":
 			"Rendering":

+ 43 - 0
Praxis3D/Data/Scripts/Kinematic_test.lua

@@ -0,0 +1,43 @@
+
+function init ()
+	-- Create needed variables
+	create(Types.GameplayVariables, 'gameplayVariables');
+	create(Types.InputVariables, 'inputVariables');
+	create(Types.SpatialDataManager, 'spatialData');
+	
+	-- Create key commands, used to track pressed keys
+	create(Types.KeyCommand, 'forwardKey')
+	create(Types.KeyCommand, 'upKey')
+	create(Types.KeyCommand, 'downKey')
+	
+	-- Bind keys to their corresponding buttons on the keyboard
+	forwardKey:bind(inputVariables.forward_key)
+	upKey:bind(inputVariables.up_editor_key)
+	downKey:bind(inputVariables.down_editor_key)
+		
+	print('Kinematic_test.lua script initialized.')
+end
+
+function update (p_deltaTime)
+	-- Get current spatial data
+	localTransformMat4 = spatialData:getLocalTransform()
+	
+	-- Extract position from spatial data
+	positionVec3 = localTransformMat4:getPosVec3()
+	
+	positionModified = false
+		
+	if upKey:isActivated() then
+		positionVec3.y = positionVec3.y + (10.0 * p_deltaTime)
+		positionModified = true
+	end	
+	if downKey:isActivated() then
+		positionVec3.y = positionVec3.y - (10.0 * p_deltaTime)
+		positionModified = true
+	end
+	
+	if(positionModified) then
+		spatialData:setLocalPosition(positionVec3)
+	end
+	
+end

+ 8 - 0
Praxis3D/Data/error-strings-eng.data

@@ -17,12 +17,19 @@
 		"Window_handle_missing"			: "Failed to get window handle",
 		"Window_handle_missing"			: "Failed to get window handle",
 		"AssimpScene_failed"				: "Assimp scene has failed to load",
 		"AssimpScene_failed"				: "Assimp scene has failed to load",
 		"ObjectPool_full"						: "Object pool overflow",
 		"ObjectPool_full"						: "Object pool overflow",
+		"Collision_invalid"					: "Invalid collision type",
+		"Collision_missing"					: "Collision shape missing",
+		"Kinematic_has_mass"				: "Kinematic object has a mass greater than zero",
+		"Property_missing_size"			: "Missing 'Size' property",
+		"Property_missing_radius"		: "Missing 'Radius' property",
+		"Property_missing_type"			: "Missing 'Type' property",
 		"Property_no_filename"			: "No filename specified",
 		"Property_no_filename"			: "No filename specified",
 		"Shader_attach_failed"			: "Attaching shaders to GPU program has failed",
 		"Shader_attach_failed"			: "Attaching shaders to GPU program has failed",
 		"Shader_compile_failed"			: "Shader compilation from source code has failed to load",
 		"Shader_compile_failed"			: "Shader compilation from source code has failed to load",
 		"Shader_creation_failed"		: "Shader handle creation has failed",
 		"Shader_creation_failed"		: "Shader handle creation has failed",
 		"Shader_link_failed"				: "Shader linking has failed",
 		"Shader_link_failed"				: "Shader linking has failed",
 		"Shader_loading_failed"			: "Shader has failed to load",
 		"Shader_loading_failed"			: "Shader has failed to load",
+		"GameObjects_missing"				: "GameObjects missing from the map file",
 		"Texture_not_found"					: "Texture was not found",
 		"Texture_not_found"					: "Texture was not found",
 		"Texture_empty"							: "Texture data was not found",
 		"Texture_empty"							: "Texture data was not found",
 		"Invalid_num_vid_displays"	: "Invalid number of video displays",
 		"Invalid_num_vid_displays"	: "Invalid number of video displays",
@@ -65,6 +72,7 @@
 		"Source_ModelComponent"						: "Model Component",
 		"Source_ModelComponent"						: "Model Component",
 		"Source_ModelLoader"							: "Model Loader",
 		"Source_ModelLoader"							: "Model Loader",
 		"Source_ObjectDirectory"					: "Object Directory",
 		"Source_ObjectDirectory"					: "Object Directory",
+		"Source_Physics"									: "Physics System",
 		"Source_PhysicsObject"						: "Physics Object",
 		"Source_PhysicsObject"						: "Physics Object",
 		"Source_PlayerObject"							: "Player Object",
 		"Source_PlayerObject"							: "Player Object",
 		"Source_PostProcessPass"					: "Post-process rendering pass",
 		"Source_PostProcessPass"					: "Post-process rendering pass",

+ 1 - 0
Praxis3D/Source/Config.cpp

@@ -230,6 +230,7 @@ void Config::init()
 	AddVariablePredef(m_filepathVar, map_path);
 	AddVariablePredef(m_filepathVar, map_path);
 	AddVariablePredef(m_filepathVar, model_path);
 	AddVariablePredef(m_filepathVar, model_path);
 	AddVariablePredef(m_filepathVar, object_path);
 	AddVariablePredef(m_filepathVar, object_path);
+	AddVariablePredef(m_filepathVar, prefab_path);
 	AddVariablePredef(m_filepathVar, script_path);
 	AddVariablePredef(m_filepathVar, script_path);
 	AddVariablePredef(m_filepathVar, shader_path);
 	AddVariablePredef(m_filepathVar, shader_path);
 	AddVariablePredef(m_filepathVar, sound_path);
 	AddVariablePredef(m_filepathVar, sound_path);

+ 20 - 187
Praxis3D/Source/Config.h

@@ -133,16 +133,18 @@ namespace Systems
 			static constexpr BitMask LocalRotation			= Changes::Type::Spatial + Changes::Common::Shared2;
 			static constexpr BitMask LocalRotation			= Changes::Type::Spatial + Changes::Common::Shared2;
 			static constexpr BitMask LocalScale				= Changes::Type::Spatial + Changes::Common::Shared3;
 			static constexpr BitMask LocalScale				= Changes::Type::Spatial + Changes::Common::Shared3;
 			static constexpr BitMask LocalTransform			= Changes::Type::Spatial + Changes::Common::Shared4;
 			static constexpr BitMask LocalTransform			= Changes::Type::Spatial + Changes::Common::Shared4;
+			static constexpr BitMask LocalTransformNoScale	= Changes::Type::Spatial + Changes::Common::Shared5;
 
 
-			static constexpr BitMask WorldPosition			= Changes::Type::Spatial + Changes::Common::Shared5;
-			static constexpr BitMask WorldRotation			= Changes::Type::Spatial + Changes::Common::Shared6;
-			static constexpr BitMask WorldScale				= Changes::Type::Spatial + Changes::Common::Shared7;
-			static constexpr BitMask WorldTransform			= Changes::Type::Spatial + Changes::Common::Shared8;
+			static constexpr BitMask WorldPosition			= Changes::Type::Spatial + Changes::Common::Shared6;
+			static constexpr BitMask WorldRotation			= Changes::Type::Spatial + Changes::Common::Shared7;
+			static constexpr BitMask WorldScale				= Changes::Type::Spatial + Changes::Common::Shared8;
+			static constexpr BitMask WorldTransform			= Changes::Type::Spatial + Changes::Common::Shared9;
+			static constexpr BitMask WorldTransformNoScale	= Changes::Type::Spatial + Changes::Common::Shared10;
 
 
 			static constexpr BitMask AllLocalNoTransform	= LocalPosition | LocalRotation | LocalScale;
 			static constexpr BitMask AllLocalNoTransform	= LocalPosition | LocalRotation | LocalScale;
 			static constexpr BitMask AllWorldNoTransform	= WorldPosition | WorldRotation | WorldScale;
 			static constexpr BitMask AllWorldNoTransform	= WorldPosition | WorldRotation | WorldScale;
-			static constexpr BitMask AllLocal				= AllLocalNoTransform | LocalTransform;
-			static constexpr BitMask AllWorld				= AllWorldNoTransform | WorldTransform;
+			static constexpr BitMask AllLocal				= AllLocalNoTransform | LocalTransform | LocalTransformNoScale;
+			static constexpr BitMask AllWorld				= AllWorldNoTransform | WorldTransform | WorldTransformNoScale;
 			static constexpr BitMask All					= AllLocal | AllWorld;
 			static constexpr BitMask All					= AllLocal | AllWorld;
 		}
 		}
 		namespace Audio
 		namespace Audio
@@ -317,10 +319,13 @@ namespace Properties
 	Code(Cone,) \
 	Code(Cone,) \
 	Code(ConvexHull,) \
 	Code(ConvexHull,) \
 	Code(Cylinder,) \
 	Code(Cylinder,) \
+	Code(Friction,) \
 	Code(Gravity,) \
 	Code(Gravity,) \
+	Code(Kinematic,) \
 	Code(Mass,) \
 	Code(Mass,) \
 	Code(Physics,) \
 	Code(Physics,) \
 	Code(PhysicsObject,) \
 	Code(PhysicsObject,) \
+	Code(Restitution,) \
 	Code(RigidBody,) \
 	Code(RigidBody,) \
 	Code(RigidBodyComponent,) \
 	Code(RigidBodyComponent,) \
 	Code(Size,) \
 	Code(Size,) \
@@ -377,182 +382,8 @@ namespace Properties
 	Code(NumberOfPropertyIDs,) 
 	Code(NumberOfPropertyIDs,) 
 	DECLARE_ENUM(PropertyID, PROPERTYID)
 	DECLARE_ENUM(PropertyID, PROPERTYID)
 
 
-	const static std::string PropertyNames[PropertyID::NumberOfPropertyIDs] =
-	{
-		GetString(Null),
-		GetString(ArrayEntry),
-		GetString(Components),
-		GetString(Default),
-		GetString(Filename),
-		GetString(Index),
-		GetString(Keybindings),
-		GetString(LoadInBackground),
-		GetString(Name),
-		GetString(Objects),
-		GetString(ObjectPoolSize),
-		GetString(Scene),
-		GetString(Systems),
-		GetString(Type),
-		GetString(Value),
-		GetString(Variables),
-		GetString(OffsetPosition),
-		GetString(OffsetRotation),
-		GetString(LocalPosition),
-		GetString(LocalRotation),
-		GetString(LocalRotationQuaternion),
-		GetString(LocalScale),
-		GetString(WorldPosition),
-		GetString(WorldRotation),
-		GetString(WorldRotationQuaternion),
-		GetString(WorldScale),
-		GetString(AlphaThreshold),
-		GetString(AmbientOcclusion),
-		GetString(Attenuation),
-		GetString(Camera),
-		GetString(CameraComponent),
-		GetString(Color),
-		GetString(CombinedTexture),
-		GetString(ComputeShader),
-		GetString(CutoffAngle),
-		GetString(Diffuse),
-		GetString(Direction),
-		GetString(DirectionalLight),
-		GetString(Emissive),
-		GetString(EnvironmentMapDynamic),
-		GetString(EnvironmentMapObject),
-		GetString(FragmentShader),
-		GetString(GeometryShader),
-		GetString(Graphics),
-		GetString(GraphicsObject),
-		GetString(Height),
-		GetString(HeightScale),
-		GetString(Intensity),
-		GetString(LightComponent),
-		GetString(Lighting),
-		GetString(Materials),
-		GetString(Metalness),
-		GetString(Meshes),
-		GetString(Models),
-		GetString(ModelComponent),
-		GetString(ModelObject),
-		GetString(ModelPoolSize),
-		GetString(NegativeX),
-		GetString(NegativeY),
-		GetString(NegativeZ),
-		GetString(Normal),
-		GetString(ParallaxHeightScale),
-		GetString(PointLight),
-		GetString(PointLightPoolSize),
-		GetString(PositiveX),
-		GetString(PositiveY),
-		GetString(PositiveZ),
-		GetString(PostProcess),
-		GetString(Renderer),
-		GetString(Rendering),
-		GetString(RMHAO),
-		GetString(Roughness),
-		GetString(Shaders),
-		GetString(ShaderComponent),
-		GetString(ShaderPoolSize),
-		GetString(ShaderGraphicsObject),
-		GetString(ShaderModelObject),
-		GetString(SpotLight),
-		GetString(SpotLightPoolSize),
-		GetString(Static),
-		GetString(TessControlShader),
-		GetString(TessEvaluationShader),
-		GetString(TextureTilingFactor),
-		GetString(TextureScale),
-		GetString(VertexShader),
-		GetString(GUI),
-		GetString(GUIObject),
-		GetString(GUISequenceComponent),
-		GetString(Sequence),
-		GetString(BackwardKey),
-		GetString(CenterKey),
-		GetString(CloseKey),
-		GetString(DebugCaptureMouseKey),
-		GetString(DebugFullscreenKey),
-		GetString(DebugVertSyncKey),
-		GetString(DownKey),
-		GetString(ForwardKey),
-		GetString(LeftKey),
-		GetString(LeftStrafeKey),
-		GetString(ModifierKey),
-		GetString(NextKey),
-		GetString(PreviousKey),
-		GetString(RightKey),
-		GetString(RightStrafeKey),
-		GetString(SaveKey),
-		GetString(SprintKey),
-		GetString(UpKey),
-		GetString(ObjectLinks),
-		GetString(Observer),
-		GetString(Subject),
-		// Physics
-		GetString(Box),
-		GetString(Capsule),
-		GetString(CollisionShape),
-		GetString(CollisionShapeComponent),
-		GetString(Cone),
-		GetString(ConvexHull),
-		GetString(Cylinder),
-		GetString(Gravity),
-		GetString(Mass),
-		GetString(Physics),
-		GetString(PhysicsObject),
-		GetString(RigidBody),
-		GetString(RigidBodyComponent),
-		GetString(Size),
-		GetString(Sphere),
-		// Script
-		GetString(Angle),
-		GetString(Axis),
-		GetString(Azimuth),
-		GetString(BaseUIScript),
-		GetString(Day),
-		GetString(DayOfYear),
-		GetString(DebugMoveScript),
-		GetString(DebugRotateScript),
-		GetString(DebugUIScript),
-		GetString(FreeCamera),
-		GetString(Latitude),
-		GetString(Longitude),
-		GetString(LowerLimit),
-		GetString(Lua),
-		GetString(LuaComponent),
-		GetString(InputScript),
-		GetString(Hours),
-		GetString(KeyCode),
-		GetString(KeyName),
-		GetString(Minutes),
-		GetString(Month),
-		GetString(Radius),
-		GetString(Script),
-		GetString(ScriptObject),
-		GetString(Seconds),
-		GetString(SolarTimeScript),
-		GetString(Speed),
-		GetString(SprintSpeed),
-		GetString(SunScript),
-		GetString(TimeMultiplier),
-		GetString(TimeZone),
-		GetString(Year),
-		GetString(UpperLimit),
-		GetString(WorldEditScript),
-		GetString(Zenith),
-		GetString(Fullscreen),
-		GetString(MouseCapture),
-		GetString(VerticalSync),
-		GetString(WindowTitle),
-		// World
-		GetString(Children),
-		GetString(GameObject),
-		GetString(ID),
-		GetString(Parent),
-		GetString(SpatialComponent),
-		GetString(World)
-	};
+	// Declare a string array of all PropertyID names, that is used for matching strings to PropertyIDs
+	DECLARE_NAME_ARRAY(PropertyID, PROPERTYID)
 
 
 	// A few overloaded static functions to convert other values to PropertyID enum
 	// A few overloaded static functions to convert other values to PropertyID enum
 	// Note: converting from string here is very slow, and would be better implemented
 	// Note: converting from string here is very slow, and would be better implemented
@@ -587,7 +418,7 @@ namespace Properties
 
 
 		// Iterate over all PropertyIDs and compare the string to property name
 		// Iterate over all PropertyIDs and compare the string to property name
 		for(int i = 0; i < Properties::PropertyID::NumberOfPropertyIDs; i++)
 		for(int i = 0; i < Properties::PropertyID::NumberOfPropertyIDs; i++)
-			if(Properties::PropertyNames[i] == p_value)
+			if(Properties::PropertyIDNames[i] == p_value)
 				return static_cast<Properties::PropertyID>(i);
 				return static_cast<Properties::PropertyID>(i);
 
 
 		// If this point is reached, no match was found, return null ID
 		// If this point is reached, no match was found, return null ID
@@ -714,9 +545,9 @@ public:
 			gl_blur_buffer_wrap_s_method = GL_CLAMP_TO_EDGE;
 			gl_blur_buffer_wrap_s_method = GL_CLAMP_TO_EDGE;
 			gl_blur_buffer_wrap_t_method = GL_CLAMP_TO_EDGE;
 			gl_blur_buffer_wrap_t_method = GL_CLAMP_TO_EDGE;
 
 
-			gl_final_buffer_min_filter_HDR = GL_LINEAR_MIPMAP_NEAREST;
-			gl_final_buffer_min_filter = GL_NEAREST;
-			gl_final_buffer_mag_filter = GL_NEAREST;
+			gl_final_buffer_min_filter_HDR = GL_LINEAR_MIPMAP_LINEAR;
+			gl_final_buffer_min_filter = GL_LINEAR;
+			gl_final_buffer_mag_filter = GL_LINEAR;
 			gl_final_buffer_s_method = GL_CLAMP_TO_EDGE;
 			gl_final_buffer_s_method = GL_CLAMP_TO_EDGE;
 			gl_final_buffer_t_method = GL_CLAMP_TO_EDGE;
 			gl_final_buffer_t_method = GL_CLAMP_TO_EDGE;
 		}
 		}
@@ -942,7 +773,7 @@ public:
 			right_strafe_key = 7;
 			right_strafe_key = 7;
 			save_editor_key = 22;
 			save_editor_key = 22;
 			sprint_key = 225;
 			sprint_key = 225;
-			up_editor_key = 75;
+			up_editor_key = 95;
 			up_key = 44;
 			up_key = 44;
 			vsync_key = 68;
 			vsync_key = 68;
 			mouse_filter = false;
 			mouse_filter = false;
@@ -1040,6 +871,7 @@ public:
 			map_path = "Data\\Maps\\";
 			map_path = "Data\\Maps\\";
 			model_path = "Data\\Models\\";
 			model_path = "Data\\Models\\";
 			object_path = "Data\\Objects\\";
 			object_path = "Data\\Objects\\";
+			prefab_path = "Data\\Prefabs\\";
 			script_path = "Data\\Scripts\\";
 			script_path = "Data\\Scripts\\";
 			shader_path = "Data\\Shaders\\";
 			shader_path = "Data\\Shaders\\";
 			sound_path = "Data\\Sounds\\";
 			sound_path = "Data\\Sounds\\";
@@ -1050,6 +882,7 @@ public:
 		std::string map_path;
 		std::string map_path;
 		std::string model_path;
 		std::string model_path;
 		std::string object_path;
 		std::string object_path;
+		std::string prefab_path;
 		std::string script_path;
 		std::string script_path;
 		std::string shader_path;
 		std::string shader_path;
 		std::string sound_path;
 		std::string sound_path;

+ 1 - 1
Praxis3D/Source/Containers.h

@@ -38,7 +38,7 @@ struct SpatialData
 		m_rotationQuat = glm::quat();
 		m_rotationQuat = glm::quat();
 	}
 	}
 
 
-	glm::vec3 m_position,
+	glm::vec3	m_position,
 				m_rotationEuler,
 				m_rotationEuler,
 				m_scale;
 				m_scale;
 	glm::quat m_rotationQuat;
 	glm::quat m_rotationQuat;

+ 28 - 18
Praxis3D/Source/EnumFactory.h

@@ -1,34 +1,44 @@
 #include <string.h>
 #include <string.h>
 
 
-// expansion macro for enum value definition
+// Expansion macro for enum value to stringized value name definition
+#define ENUM_NAME(name,assign) #name,
+
+// Expansion macro for enum value definition
 #define ENUM_VALUE(name,assign) name assign,
 #define ENUM_VALUE(name,assign) name assign,
 
 
-// expansion macro for enum to string conversion
+// Expansion macro for enum to string conversion
 #define ENUM_CASE(name,assign) case name: return #name;
 #define ENUM_CASE(name,assign) case name: return #name;
 
 
-// expansion macro for string to enum conversion
+// Expansion macro for string to enum conversion
 #define ENUM_STRCMP(name,assign) if (!strcmp(str,#name)) return name;
 #define ENUM_STRCMP(name,assign) if (!strcmp(str,#name)) return name;
 
 
-/// declare the access function and define enum values
+// Declare the access function and define enum values
 #define DECLARE_ENUM(EnumType,ENUM_DEF) \
 #define DECLARE_ENUM(EnumType,ENUM_DEF) \
-  enum EnumType { \
-    ENUM_DEF(ENUM_VALUE) \
+    enum EnumType { \
+        ENUM_DEF(ENUM_VALUE) \
     }; \
     }; \
-  const char *GetString(EnumType dummy); \
-  EnumType Get##EnumType##Value(const char *string); \
+    const char *GetString(EnumType dummy); \
+    EnumType Get##EnumType##Value(const char *string); \
 
 
-/// define the access function names
+// Define the access function names
 #define DEFINE_ENUM(EnumType,ENUM_DEF) \
 #define DEFINE_ENUM(EnumType,ENUM_DEF) \
-  const char *GetString(EnumType value) \
+    const char *GetString(EnumType value) \
     { \
     { \
     switch(value) \
     switch(value) \
-	    { \
-      ENUM_DEF(ENUM_CASE) \
-      default: return ""; /* handle input error */ \
-	    } \
+        { \
+        ENUM_DEF(ENUM_CASE) \
+        default: return ""; /* handle input error */ \
+        } \
     } \
     } \
-  EnumType Get##EnumType##Value(const char *str) \
+    EnumType Get##EnumType##Value(const char *str) \
+    { \
+        ENUM_DEF(ENUM_STRCMP) \
+        return (EnumType)0; /* handle input error */ \
+    }
+
+// Declare a string array of all enum value names
+#define DECLARE_NAME_ARRAY(EnumType,ENUM_DEF) \
+    const static std::string EnumType##Names[] = \
     { \
     { \
-    ENUM_DEF(ENUM_STRCMP) \
-    return (EnumType)0; /* handle input error */ \
-    }
+        ENUM_DEF(ENUM_NAME) \
+    };

+ 10 - 0
Praxis3D/Source/ErrorCodes.h

@@ -56,7 +56,14 @@ DECLARE_ENUM(ErrorType, ERROR_TYPES)
 	Code(AssimpScene_failed,) \
 	Code(AssimpScene_failed,) \
 	/* Object pool errors */ \
 	/* Object pool errors */ \
 	Code(ObjectPool_full,) \
 	Code(ObjectPool_full,) \
+	/* Physics system errors */ \
+	Code(Collision_invalid,) \
+	Code(Collision_missing,) \
+	Code(Kinematic_has_mass,) \
 	/* Property loader errors */ \
 	/* Property loader errors */ \
+	Code(Property_missing_size,) \
+	Code(Property_missing_radius,) \
+	Code(Property_missing_type,) \
 	Code(Property_no_filename,) \
 	Code(Property_no_filename,) \
 	/* Shader loader errors */ \
 	/* Shader loader errors */ \
 	Code(Shader_attach_failed,) \
 	Code(Shader_attach_failed,) \
@@ -64,6 +71,8 @@ DECLARE_ENUM(ErrorType, ERROR_TYPES)
 	Code(Shader_creation_failed,) \
 	Code(Shader_creation_failed,) \
 	Code(Shader_link_failed,) \
 	Code(Shader_link_failed,) \
 	Code(Shader_loading_failed,) \
 	Code(Shader_loading_failed,) \
+	/* Scene loader errors */ \
+	Code(GameObjects_missing,) \
 	/* Texture loader errors */ \
 	/* Texture loader errors */ \
 	Code(Texture_not_found,) \
 	Code(Texture_not_found,) \
 	Code(Texture_empty,) \
 	Code(Texture_empty,) \
@@ -112,6 +121,7 @@ DECLARE_ENUM(ErrorCode, ERROR_CODES)
     Code(Source_ModelComponent,) \
     Code(Source_ModelComponent,) \
     Code(Source_ModelLoader,) \
     Code(Source_ModelLoader,) \
     Code(Source_ObjectDirectory,) \
     Code(Source_ObjectDirectory,) \
+    Code(Source_Physics,) \
     Code(Source_PhysicsObject,) \
     Code(Source_PhysicsObject,) \
     Code(Source_PlayerObject,) \
     Code(Source_PlayerObject,) \
     Code(Source_PostProcessPass,) \
     Code(Source_PostProcessPass,) \

+ 15 - 57
Praxis3D/Source/ErrorHandler.cpp

@@ -16,7 +16,6 @@
 // AssignErrorType(ERROR_CODE, ERROR_TYPE) ERR_TYP_PREDEF[ERROR_CODE] = ERROR_TYPE; ERR_HASH_PREDEF[GetString(ERROR_CODE)] = ERROR_CODE
 // AssignErrorType(ERROR_CODE, ERROR_TYPE) ERR_TYP_PREDEF[ERROR_CODE] = ERROR_TYPE; ERR_HASH_PREDEF[GetString(ERROR_CODE)] = ERROR_CODE
 //#define AssignErrorSource(ERROR_CODE, ERROR_TYPE) ERR_TYP_PREDEF[ERROR_CODE] = ERROR_TYPE; ERR_HASH_PREDEF[GetString(ERROR_CODE)] = ERROR_CODE
 //#define AssignErrorSource(ERROR_CODE, ERROR_TYPE) ERR_TYP_PREDEF[ERROR_CODE] = ERROR_TYPE; ERR_HASH_PREDEF[GetString(ERROR_CODE)] = ERROR_CODE
 
 
-
 ErrorHandler::ErrorHandler()
 ErrorHandler::ErrorHandler()
 {
 {
 	m_console = nullptr;
 	m_console = nullptr;
@@ -38,12 +37,19 @@ ErrorHandler::ErrorHandler()
 	AssignErrorType(Window_handle_missing, Error);
 	AssignErrorType(Window_handle_missing, Error);
 	AssignErrorType(AssimpScene_failed, Error);
 	AssignErrorType(AssimpScene_failed, Error);
 	AssignErrorType(ObjectPool_full, Warning); 
 	AssignErrorType(ObjectPool_full, Warning); 
+	AssignErrorType(Collision_invalid, Warning);
+	AssignErrorType(Collision_missing, Warning);
+	AssignErrorType(Kinematic_has_mass, Warning);
+	AssignErrorType(Property_missing_size, Warning);
+	AssignErrorType(Property_missing_radius, Warning);
+	AssignErrorType(Property_missing_type, Warning);
 	AssignErrorType(Property_no_filename, Warning);
 	AssignErrorType(Property_no_filename, Warning);
 	AssignErrorType(Shader_attach_failed, Error);
 	AssignErrorType(Shader_attach_failed, Error);
 	AssignErrorType(Shader_compile_failed, Error);
 	AssignErrorType(Shader_compile_failed, Error);
 	AssignErrorType(Shader_creation_failed, Error);
 	AssignErrorType(Shader_creation_failed, Error);
 	AssignErrorType(Shader_link_failed, Error);
 	AssignErrorType(Shader_link_failed, Error);
 	AssignErrorType(Shader_loading_failed, Error);
 	AssignErrorType(Shader_loading_failed, Error);
+	AssignErrorType(GameObjects_missing, Error);
 	AssignErrorType(Texture_not_found, Warning);
 	AssignErrorType(Texture_not_found, Warning);
 	AssignErrorType(Texture_empty, Warning);
 	AssignErrorType(Texture_empty, Warning);
 	AssignErrorType(Invalid_num_vid_displays, Warning);
 	AssignErrorType(Invalid_num_vid_displays, Warning);
@@ -52,67 +58,14 @@ ErrorHandler::ErrorHandler()
 	AssignErrorType(Window_creation_failed, FatalError);
 	AssignErrorType(Window_creation_failed, FatalError);
 	AssignErrorType(Invalid_object_id, Error);
 	AssignErrorType(Invalid_object_id, Error);
 	AssignErrorType(Duplicate_object_id, Error);
 	AssignErrorType(Duplicate_object_id, Error);
-	
+
+	// Add error sources to the hash map, and offset them by number of error codes, because they share the same hash map
 	for(unsigned int i = 0; i < Source_NumberOfErrorSources; i++)
 	for(unsigned int i = 0; i < Source_NumberOfErrorSources; i++)
 	{
 	{
 		ErrorSource errorSource = static_cast<ErrorSource>(i);
 		ErrorSource errorSource = static_cast<ErrorSource>(i);
 		m_errHashmap[GetString(errorSource)] = NumberOfErrorCodes + errorSource;
 		m_errHashmap[GetString(errorSource)] = NumberOfErrorCodes + errorSource;
 	}
 	}
 
 
-	// Add error sources to the hash map, and offset them by number of error codes, because they share the same hash map	
-   /* m_errHashmap[GetString(Source_Unknown)] = NumberOfErrorCodes + Source_Unknown;
-    m_errHashmap[GetString(Source_General)]						= NumberOfErrorCodes + Source_General;
-    m_errHashmap[GetString(Source_AtmScatteringPass)]			= NumberOfErrorCodes + Source_AtmScatteringPass;
-    m_errHashmap[GetString(Source_BloomCompositePass)]			= NumberOfErrorCodes + Source_BloomCompositePass;
-    m_errHashmap[GetString(Source_BloomPass)]					= NumberOfErrorCodes + Source_BloomPass;
-	m_errHashmap[GetString(Source_BlurPass)]					= NumberOfErrorCodes + Source_BlurPass;
-	m_errHashmap[GetString(Source_CameraComponent)]				= NumberOfErrorCodes + Source_CameraComponent;
-	m_errHashmap[GetString(Source_CallisionShapeComponent)]		= NumberOfErrorCodes + Source_CallisionShapeComponent;
-    m_errHashmap[GetString(Source_Config)]						= NumberOfErrorCodes + Source_Config;
-    m_errHashmap[GetString(Source_ConfigLoader)]				= NumberOfErrorCodes + Source_ConfigLoader;
-    m_errHashmap[GetString(Source_Engine)]						= NumberOfErrorCodes + Source_Engine;
-    m_errHashmap[GetString(Source_FileLoader)]					= NumberOfErrorCodes + Source_FileLoader;
-    m_errHashmap[GetString(Source_FinalPass)]					= NumberOfErrorCodes + Source_FinalPass;
-    m_errHashmap[GetString(Source_GameObject)]					= NumberOfErrorCodes + Source_GameObject;
-    m_errHashmap[GetString(Source_GeometryBuffer)]				= NumberOfErrorCodes + Source_GeometryBuffer;
-    m_errHashmap[GetString(Source_GeometryPass)]				= NumberOfErrorCodes + Source_GeometryPass;
-    m_errHashmap[GetString(Source_GraphicsObject)]				= NumberOfErrorCodes + Source_GraphicsObject;
-    m_errHashmap[GetString(Source_GUI)]							= NumberOfErrorCodes + Source_GUI;
-	m_errHashmap[GetString(Source_GUIObject)]					= NumberOfErrorCodes + Source_GUIObject;
-	m_errHashmap[GetString(Source_GUISequenceComponent)]		= NumberOfErrorCodes + Source_GUISequenceComponent;
-    m_errHashmap[GetString(Source_HdrMappingPass)]				= NumberOfErrorCodes + Source_HdrMappingPass;
-    m_errHashmap[GetString(Source_LensFlareCompositePass)]		= NumberOfErrorCodes + Source_LensFlareCompositePass;
-    m_errHashmap[GetString(Source_LensFlarePass)]				= NumberOfErrorCodes + Source_LensFlarePass;
-	m_errHashmap[GetString(Source_LightComponent)]				= NumberOfErrorCodes + Source_LightComponent;
-    m_errHashmap[GetString(Source_LightObject)]					= NumberOfErrorCodes + Source_LightObject;
-	m_errHashmap[GetString(Source_LightingPass)]				= NumberOfErrorCodes + Source_LightingPass;
-	m_errHashmap[GetString(Source_LuaComponent)]				= NumberOfErrorCodes + Source_LuaComponent;
-	m_errHashmap[GetString(Source_LuminancePass)]				= NumberOfErrorCodes + Source_LuminancePass;
-	m_errHashmap[GetString(Source_ModelComponent)]				= NumberOfErrorCodes + Source_ModelComponent;
-    m_errHashmap[GetString(Source_ModelLoader)]					= NumberOfErrorCodes + Source_ModelLoader;
-	m_errHashmap[GetString(Source_ObjectDirectory)]				= NumberOfErrorCodes + Source_ObjectDirectory;
-	m_errHashmap[GetString(Source_PhysicsObject)]				= NumberOfErrorCodes + Source_PhysicsObject;
-    m_errHashmap[GetString(Source_PlayerObject)]				= NumberOfErrorCodes + Source_PlayerObject;
-    m_errHashmap[GetString(Source_PostProcessPass)]				= NumberOfErrorCodes + Source_PostProcessPass;
-    m_errHashmap[GetString(Source_PropertyLoader)]				= NumberOfErrorCodes + Source_PropertyLoader;
-    m_errHashmap[GetString(Source_ReflectionPass)]				= NumberOfErrorCodes + Source_ReflectionPass;
-    m_errHashmap[GetString(Source_Renderer)]					= NumberOfErrorCodes + Source_Renderer;
-	m_errHashmap[GetString(Source_RendererScene)]				= NumberOfErrorCodes + Source_RendererScene;
-	m_errHashmap[GetString(Source_RendererSystem)]				= NumberOfErrorCodes + Source_RendererSystem;
-	m_errHashmap[GetString(Source_RigidBodyComponent)]			= NumberOfErrorCodes + Source_RigidBodyComponent;
-    m_errHashmap[GetString(Source_SceneLoader)]					= NumberOfErrorCodes + Source_SceneLoader;
-    m_errHashmap[GetString(Source_Script)]						= NumberOfErrorCodes + Source_Script;
-    m_errHashmap[GetString(Source_ScriptObject)]				= NumberOfErrorCodes + Source_ScriptObject;
-	m_errHashmap[GetString(Source_ShaderComponent)]				= NumberOfErrorCodes + Source_ShaderComponent;
-    m_errHashmap[GetString(Source_ShaderLoader)]				= NumberOfErrorCodes + Source_ShaderLoader;
-    m_errHashmap[GetString(Source_SkyObject)]					= NumberOfErrorCodes + Source_SkyObject;
-    m_errHashmap[GetString(Source_SkyPass)]						= NumberOfErrorCodes + Source_SkyPass;
-    m_errHashmap[GetString(Source_TextureLoader)]				= NumberOfErrorCodes + Source_TextureLoader;
-    m_errHashmap[GetString(Source_Window)]						= NumberOfErrorCodes + Source_Window;
-	m_errHashmap[GetString(Source_World)]						= NumberOfErrorCodes + Source_World;
-	m_errHashmap[GetString(Source_WorldScene)]					= NumberOfErrorCodes + Source_WorldScene;
-	m_errHashmap[GetString(Source_WorldSystem)]					= NumberOfErrorCodes + Source_WorldSystem;*/
-
 	// Add error types to the hash map, and offset them by number of error codes and error sources, because they share the same hash map
 	// Add error types to the hash map, and offset them by number of error codes and error sources, because they share the same hash map
 	m_errHashmap[GetString(Info)]		= NumberOfErrorCodes + Source_NumberOfErrorSources + Info;
 	m_errHashmap[GetString(Info)]		= NumberOfErrorCodes + Source_NumberOfErrorSources + Info;
 	m_errHashmap[GetString(Warning)]	= NumberOfErrorCodes + Source_NumberOfErrorSources + Warning;
 	m_errHashmap[GetString(Warning)]	= NumberOfErrorCodes + Source_NumberOfErrorSources + Warning;
@@ -232,4 +185,9 @@ void ErrorHandler::log(ErrorCode p_errorCode, ErrorSource p_errorSource, std::st
 	}
 	}
 	else
 	else
 		log(m_errorData[p_errorCode].m_errorType, p_errorSource, m_errorData[p_errorCode].m_errorString + ": " + p_error);
 		log(m_errorData[p_errorCode].m_errorType, p_errorSource, m_errorData[p_errorCode].m_errorString + ": " + p_error);
-}
+}
+
+void ErrorHandler::log(const ErrorCode p_errorCode, const std::string &p_objectName, const ErrorSource p_errorSource)
+{
+	log(m_errorData[p_errorCode].m_errorType, p_errorSource, "\'" + p_objectName + "\': " + m_errorData[p_errorCode].m_errorString);
+}

+ 3 - 1
Praxis3D/Source/ErrorHandler.h

@@ -24,6 +24,7 @@ public:
 	virtual void log(ErrorCode p_errorCode, ErrorSource p_errorSource) = 0;
 	virtual void log(ErrorCode p_errorCode, ErrorSource p_errorSource) = 0;
 	virtual void log(ErrorType p_errorType, ErrorSource p_errorSource, std::string p_error) = 0;
 	virtual void log(ErrorType p_errorType, ErrorSource p_errorSource, std::string p_error) = 0;
 	virtual void log(ErrorCode p_errorCode, ErrorSource p_errorSource, std::string p_error) = 0;
 	virtual void log(ErrorCode p_errorCode, ErrorSource p_errorSource, std::string p_error) = 0;
+	virtual void log(const ErrorCode p_errorCode, const std::string &p_objectName, const ErrorSource p_errorSource) = 0;
 
 
 	// This should be used when trying to pass an error code and an error string as a return. So instead of logging
 	// This should be used when trying to pass an error code and an error string as a return. So instead of logging
 	// the error immediately, it is cached and then can be retrieved later (presumably from higher scope / parent, etc).
 	// the error immediately, it is cached and then can be retrieved later (presumably from higher scope / parent, etc).
@@ -48,6 +49,7 @@ public:
 	void log(ErrorCode p_errorCode, ErrorSource p_errorSource);
 	void log(ErrorCode p_errorCode, ErrorSource p_errorSource);
 	void log(ErrorType p_errorType, ErrorSource p_errorSource, std::string p_error);
 	void log(ErrorType p_errorType, ErrorSource p_errorSource, std::string p_error);
 	void log(ErrorCode p_errorCode, ErrorSource p_errorSource, std::string p_error);
 	void log(ErrorCode p_errorCode, ErrorSource p_errorSource, std::string p_error);
+	void log(const ErrorCode p_errorCode, const std::string &p_objectName, const ErrorSource p_errorSource);
 
 
 	// Note: Unusable at the time - needs to be updated to be thread safe (using TLS for example)
 	// Note: Unusable at the time - needs to be updated to be thread safe (using TLS for example)
 	//inline ErrorCode cacheError(ErrorCode p_errorCode, std::string p_error) { m_cachedError.cache(p_errorCode, p_error); return ErrorCode::CachedError; }
 	//inline ErrorCode cacheError(ErrorCode p_errorCode, std::string p_error) { m_cachedError.cache(p_errorCode, p_error); return ErrorCode::CachedError; }
@@ -110,7 +112,6 @@ private:
 	};
 	};
 	
 	
 	ErrorData m_errorData[ErrorCode::NumberOfErrorCodes];
 	ErrorData m_errorData[ErrorCode::NumberOfErrorCodes];
-	ErrorType m_errorTypes[NumberOfErrorCodes];
 
 
 	std::string m_errorTypeStrings[NumberOfErrorTypes];
 	std::string m_errorTypeStrings[NumberOfErrorTypes];
 	std::string m_errorSources[Source_NumberOfErrorSources];
 	std::string m_errorSources[Source_NumberOfErrorSources];
@@ -136,6 +137,7 @@ public:
 	void log(ErrorCode p_errorCode, ErrorSource p_errorSource) { printf("Error: %i.\n", p_errorCode); }
 	void log(ErrorCode p_errorCode, ErrorSource p_errorSource) { printf("Error: %i.\n", p_errorCode); }
 	void log(ErrorType p_errorType, ErrorSource p_errorSource, std::string p_error) { printf("Error: %s.\n", p_error.c_str()); }
 	void log(ErrorType p_errorType, ErrorSource p_errorSource, std::string p_error) { printf("Error: %s.\n", p_error.c_str()); }
 	void log(ErrorCode p_errorCode, ErrorSource p_errorSource, std::string p_error) { printf("Error: %i.\n", p_errorCode); }
 	void log(ErrorCode p_errorCode, ErrorSource p_errorSource, std::string p_error) { printf("Error: %i.\n", p_errorCode); }
+	void log(const ErrorCode p_errorCode, const std::string &p_objectName, const ErrorSource p_errorSource) { printf("Error: %s: %i.\n", p_objectName.c_str(), p_errorCode); }
 
 
 	bool ifSuccessful(ErrorCode p_errorCode, ErrorCode &p_returnCode) { p_returnCode = p_errorCode; return p_errorCode == ErrorCode::Success; }
 	bool ifSuccessful(ErrorCode p_errorCode, ErrorCode &p_returnCode) { p_returnCode = p_errorCode; return p_errorCode == ErrorCode::Success; }
 	//ErrorCode cacheError(ErrorCode p_errorCode, std::string p_error) { return ErrorCode::Undefined; }
 	//ErrorCode cacheError(ErrorCode p_errorCode, std::string p_error) { return ErrorCode::Undefined; }

+ 1 - 1
Praxis3D/Source/GameObject.h

@@ -307,7 +307,7 @@ public:
 
 
 private:
 private:
 	// Set the ID of the object. The ID must be unique
 	// Set the ID of the object. The ID must be unique
-	void setGameObjectID(std::size_t p_id) { m_GameObjectID = p_id; }
+	void setGameObjectID(EntityID p_id) { m_GameObjectID = p_id; }
 
 
 	// Unlinks the given component, so that it is removed from observers/listeners
 	// Unlinks the given component, so that it is removed from observers/listeners
 	void unlinkComponent(SystemObject *p_component)
 	void unlinkComponent(SystemObject *p_component)

+ 6 - 0
Praxis3D/Source/LuaComponent.h

@@ -56,6 +56,12 @@ public:
 			// Get the changes from the lua script
 			// Get the changes from the lua script
 			auto changes = m_luaScript->getChanges();
 			auto changes = m_luaScript->getChanges();
 
 
+			// Add spatial changes to the current changes, because they are tracked separately
+			changes += m_luaSpatialData.getCurrentChangesAndReset();
+
+			// Add GUI changes to the current changes, because they are tracked separately
+			changes += m_GUIData.getCurrentChangesAndReset();
+
 			// Post the new changes
 			// Post the new changes
 			postChanges(changes);
 			postChanges(changes);
 		}
 		}

+ 4 - 6
Praxis3D/Source/LuaScript.h

@@ -124,12 +124,6 @@ public:
 
 
 		// Call update function in the lua script
 		// Call update function in the lua script
 		m_luaUpdate(p_deltaTime);
 		m_luaUpdate(p_deltaTime);
-
-		// Add spatial changes to the current changes, because they are tracked separately
-		m_currentChanges += m_spatialData.getCurrentChanges();
-
-		// Add GUI changes to the current changes, because they are tracked separately
-		m_currentChanges += m_GUIData.getCurrentChanges();
 	}
 	}
 
 
 	// Clears the currently registered changes. They are also cleared at the beginning of each update call
 	// Clears the currently registered changes. They are also cleared at the beginning of each update call
@@ -166,6 +160,8 @@ public:
 		clearChanges();
 		clearChanges();
 	}
 	}
 
 
+	const inline std::string &getLuaScriptFilename() const { return m_luaScriptFilename; }
+
 private:
 private:
 	// Sets lua tables with various definitions and values
 	// Sets lua tables with various definitions and values
 	void setDefinitions()
 	void setDefinitions()
@@ -441,6 +437,7 @@ private:
 			"m_spatialData", &SpatialTransformData::m_spatialData);
 			"m_spatialData", &SpatialTransformData::m_spatialData);
 
 
 		m_luaState.new_usertype<SpatialDataManager>("SpatialDataManager",
 		m_luaState.new_usertype<SpatialDataManager>("SpatialDataManager",
+			"update", &SpatialDataManager::update,
 			"getLocalSpaceData", &SpatialDataManager::getLocalSpaceData,
 			"getLocalSpaceData", &SpatialDataManager::getLocalSpaceData,
 			"getLocalTransform", &SpatialDataManager::getLocalTransform,
 			"getLocalTransform", &SpatialDataManager::getLocalTransform,
 			"getParemtTransform", &SpatialDataManager::getParemtTransform,
 			"getParemtTransform", &SpatialDataManager::getParemtTransform,
@@ -573,6 +570,7 @@ private:
 	// Lua state for the loaded script
 	// Lua state for the loaded script
 	sol::state m_luaState;
 	sol::state m_luaState;
 	std::string m_luaScriptFilename;
 	std::string m_luaScriptFilename;
+
 	// Function binds that call functions inside the lua script
 	// Function binds that call functions inside the lua script
 	sol::function m_luaInit;
 	sol::function m_luaInit;
 	sol::function m_luaUpdate;
 	sol::function m_luaUpdate;

+ 13 - 1
Praxis3D/Source/Math.h

@@ -33,7 +33,17 @@
 
 
 namespace Math
 namespace Math
 {
 {
-	const glm::mat4 createTransformMat(const glm::vec3 &p_position, const glm::vec3 &p_rotation, const glm::vec3 &p_scale);
+	const glm::mat4 createTransformMat(const glm::vec3 &p_position, const glm::vec3 &p_rotation, const glm::vec3 &p_scale);	
+	const inline glm::mat4 createTransformMat(const glm::vec3 &p_position, const glm::quat &p_rotation)
+	{
+		glm::mat4 returnMatrix(1.0f);
+
+		returnMatrix = glm::translate(returnMatrix, p_position);
+
+		returnMatrix *= glm::toMat4(p_rotation);
+
+		return returnMatrix;
+	}
 	const inline glm::mat4 createTransformMat(const glm::vec3 &p_position, const glm::quat &p_rotation, const glm::vec3 &p_scale)
 	const inline glm::mat4 createTransformMat(const glm::vec3 &p_position, const glm::quat &p_rotation, const glm::vec3 &p_scale)
 	{
 	{
 		glm::mat4 returnMatrix(1.0f);
 		glm::mat4 returnMatrix(1.0f);
@@ -75,6 +85,8 @@ namespace Math
 
 
 	const inline btVector3 toBtVector3(const glm::vec3 p_vec) { return btVector3(p_vec.x, p_vec.y, p_vec.z); }
 	const inline btVector3 toBtVector3(const glm::vec3 p_vec) { return btVector3(p_vec.x, p_vec.y, p_vec.z); }
 
 
+	const inline btVector3 toBtVector3(const glm::vec4 p_vec) { return btVector3(p_vec.x, p_vec.y, p_vec.z); }
+
 	const inline glm::vec3 toGlmVec3(const btVector3 &p_vec) { return glm::vec3(p_vec.getX(), p_vec.getY(), p_vec.getZ()); }
 	const inline glm::vec3 toGlmVec3(const btVector3 &p_vec) { return glm::vec3(p_vec.getX(), p_vec.getY(), p_vec.getZ()); }
 
 
 	//const inline btVector3 glmToBullet(const glm::vec3 &p_vec) { return btVector3(p_vec.x, p_vec.y, p_vec.z); }
 	//const inline btVector3 glmToBullet(const glm::vec3 &p_vec) { return btVector3(p_vec.x, p_vec.y, p_vec.z); }

+ 1 - 0
Praxis3D/Source/NullObjects.cpp

@@ -19,6 +19,7 @@ constexpr NullObserver nullObserver;
 const glm::quat				NullObjects::NullQuaterion = glm::quat();
 const glm::quat				NullObjects::NullQuaterion = glm::quat();
 const glm::vec3				NullObjects::NullVec3f = glm::vec3(1.0f);
 const glm::vec3				NullObjects::NullVec3f = glm::vec3(1.0f);
 const glm::vec4				NullObjects::NullVec4f = glm::vec4(1.0f);
 const glm::vec4				NullObjects::NullVec4f = glm::vec4(1.0f);
+const glm::mat3				NullObjects::NullMat3f = glm::mat3();
 const glm::mat4				NullObjects::NullMat4f = glm::mat4();
 const glm::mat4				NullObjects::NullMat4f = glm::mat4();
 const bool					NullObjects::NullBool = false;
 const bool					NullObjects::NullBool = false;
 const int					NullObjects::NullInt = 0;
 const int					NullObjects::NullInt = 0;

+ 1 - 0
Praxis3D/Source/NullObjects.h

@@ -16,6 +16,7 @@ namespace NullObjects
 	const extern glm::quat				NullQuaterion;
 	const extern glm::quat				NullQuaterion;
 	const extern glm::vec3				NullVec3f;
 	const extern glm::vec3				NullVec3f;
 	const extern glm::vec4				NullVec4f;
 	const extern glm::vec4				NullVec4f;
+	const extern glm::mat3				NullMat3f;
 	const extern glm::mat4				NullMat4f;
 	const extern glm::mat4				NullMat4f;
 	const extern bool					NullBool;
 	const extern bool					NullBool;
 	const extern int					NullInt;
 	const extern int					NullInt;

+ 1 - 0
Praxis3D/Source/ObserverBase.h

@@ -64,6 +64,7 @@ public:
 	const virtual glm::quat				&getQuaternion(const Observer *p_observer, BitMask p_changedBits)			const { return NullObjects::NullQuaterion;				}
 	const virtual glm::quat				&getQuaternion(const Observer *p_observer, BitMask p_changedBits)			const { return NullObjects::NullQuaterion;				}
 	const virtual glm::vec3				&getVec3(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullVec3f;					}
 	const virtual glm::vec3				&getVec3(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullVec3f;					}
 	const virtual glm::vec4				&getVec4(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullVec4f;					}
 	const virtual glm::vec4				&getVec4(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullVec4f;					}
+	const virtual glm::mat3				&getMat3(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullMat3f;					}
 	const virtual glm::mat4				&getMat4(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullMat4f;					}
 	const virtual glm::mat4				&getMat4(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullMat4f;					}
 	const virtual bool					getBool(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullBool;					}
 	const virtual bool					getBool(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullBool;					}
 	const virtual int					getInt(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullInt;					}
 	const virtual int					getInt(const Observer *p_observer, BitMask p_changedBits)					const { return NullObjects::NullInt;					}

+ 29 - 1
Praxis3D/Source/PhysicsMotionState.h

@@ -31,11 +31,36 @@ public:
 	}
 	}
 
 
 	// Get the world transform in the form of btTransform
 	// Get the world transform in the form of btTransform
-	void getWorldTransform(btTransform &p_worldTrans) const { p_worldTrans = m_centerOfMassWorldTrans; }
+	void getWorldTransform(btTransform &p_worldTrans) const 
+	{ 
+		p_worldTrans = m_centerOfMassWorldTrans; 
+	}
 
 
 	// Get the world transform in the form of glm::mat4
 	// Get the world transform in the form of glm::mat4
 	const inline glm::mat4 &getWorldTransform() const { return m_graphicsWorldTrans; }
 	const inline glm::mat4 &getWorldTransform() const { return m_graphicsWorldTrans; }
 
 
+	const glm::vec3 getPosition()		const { return Math::toGlmVec3(m_centerOfMassWorldTrans.getOrigin());	}
+	const glm::quat getRotation()		const { return Math::toGlmQuat(m_centerOfMassWorldTrans.getRotation()); }
+
+	void setPosition(const glm::vec3 &p_position)
+	{
+		m_centerOfMassWorldTrans.setOrigin(Math::toBtVector3(p_position));
+		m_graphicsWorldTransUpToDate = false;
+		m_motionStateDirty = true;
+	}	
+	void setPosition(const glm::mat4 &p_worldTrans)
+	{
+		m_centerOfMassWorldTrans.setOrigin(Math::toBtVector3(p_worldTrans[3]));
+		m_graphicsWorldTransUpToDate = false;
+		m_motionStateDirty = true;
+	}
+	void setRotation(const glm::quat &p_rotation)
+	{
+		m_centerOfMassWorldTrans.setRotation(Math::toBtQuaternion(p_rotation));
+		m_graphicsWorldTransUpToDate = false;
+		m_motionStateDirty = true;
+	}
+
 	//Bullet only calls the update of world transform for active objects
 	//Bullet only calls the update of world transform for active objects
 	void setWorldTransform(const btTransform &p_worldTrans) 
 	void setWorldTransform(const btTransform &p_worldTrans) 
 	{
 	{
@@ -45,8 +70,11 @@ public:
 	}
 	}
 	void setWorldTransform(const glm::mat4 &p_worldTrans)
 	void setWorldTransform(const glm::mat4 &p_worldTrans)
 	{
 	{
+		//setPosition(glm::vec3(p_worldTrans[3][0], p_worldTrans[3][1], p_worldTrans[3][2]));
+		auto test = p_worldTrans[0];
 		m_graphicsWorldTrans = p_worldTrans;
 		m_graphicsWorldTrans = p_worldTrans;
 		m_centerOfMassWorldTrans = Math::toBtTransform(p_worldTrans);
 		m_centerOfMassWorldTrans = Math::toBtTransform(p_worldTrans);
+		m_graphicsWorldTransUpToDate = true;
 		m_motionStateDirty = true;
 		m_motionStateDirty = true;
 	}
 	}
 
 

+ 111 - 32
Praxis3D/Source/PhysicsScene.cpp

@@ -1,6 +1,7 @@
 #include "NullSystemObjects.h"
 #include "NullSystemObjects.h"
 #include "PhysicsScene.h"
 #include "PhysicsScene.h"
 #include "TaskManagerLocator.h"
 #include "TaskManagerLocator.h"
+#include "WorldScene.h"
 
 
 PhysicsScene::PhysicsScene(SystemBase *p_system, SceneLoader *p_sceneLoader) : SystemScene(p_system, p_sceneLoader)
 PhysicsScene::PhysicsScene(SystemBase *p_system, SceneLoader *p_sceneLoader) : SystemScene(p_system, p_sceneLoader)
 {
 {
@@ -10,9 +11,6 @@ PhysicsScene::PhysicsScene(SystemBase *p_system, SceneLoader *p_sceneLoader) : S
 	m_collisionDispatcher = nullptr;
 	m_collisionDispatcher = nullptr;
 	m_collisionBroadphase = nullptr;
 	m_collisionBroadphase = nullptr;
 	m_dynamicsWorld = nullptr;
 	m_dynamicsWorld = nullptr;
-
-	// Bullet world
-	btDiscreteDynamicsWorld *m_physicsWorld;
 }
 }
 
 
 PhysicsScene::~PhysicsScene()
 PhysicsScene::~PhysicsScene()
@@ -76,24 +74,21 @@ ErrorCode PhysicsScene::init()
 	m_collisionBroadphase = new btDbvtBroadphase();
 	m_collisionBroadphase = new btDbvtBroadphase();
 
 
 	// the default constraint solver . For parallel processing you can use a different solver (see Extras / BulletMultiThreaded)
 	// the default constraint solver . For parallel processing you can use a different solver (see Extras / BulletMultiThreaded)
-	m_collisionSolver = new btSequentialImpulseConstraintSolver;
+	m_collisionSolver = new btSequentialImpulseConstraintSolver();
 
 
 	m_dynamicsWorld = new btDiscreteDynamicsWorld(m_collisionDispatcher, m_collisionBroadphase, m_collisionSolver, m_collisionConfiguration);
 	m_dynamicsWorld = new btDiscreteDynamicsWorld(m_collisionDispatcher, m_collisionBroadphase, m_collisionSolver, m_collisionConfiguration);
 	
 	
-	return ErrorCode();
+	return ErrorCode::Success;
 }
 }
 
 
 ErrorCode PhysicsScene::setup(const PropertySet &p_properties)
 ErrorCode PhysicsScene::setup(const PropertySet &p_properties)
 {	
 {	
-	// Get default object pool size
-	decltype(m_physicsObjects.getPoolSize()) objectPoolSize = Config::objectPoolVar().object_pool_size;
-
 	for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
 	for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
 	{
 	{
 		switch(p_properties[i].getPropertyID())
 		switch(p_properties[i].getPropertyID())
 		{
 		{
 		case Properties::ObjectPoolSize:
 		case Properties::ObjectPoolSize:
-			objectPoolSize = p_properties[i].getInt();
+
 			break;
 			break;
 		case Properties::Gravity:
 		case Properties::Gravity:
 			m_dynamicsWorld->setGravity(Math::toBtVector3(p_properties[i].getVec3f()));
 			m_dynamicsWorld->setGravity(Math::toBtVector3(p_properties[i].getVec3f()));
@@ -101,32 +96,27 @@ ErrorCode PhysicsScene::setup(const PropertySet &p_properties)
 		}
 		}
 	}
 	}
 
 
-	// Initialize object pools
-	m_physicsObjects.init(objectPoolSize);
-
 	return ErrorCode::Success;
 	return ErrorCode::Success;
 }
 }
 
 
 void PhysicsScene::update(const float p_deltaTime)
 void PhysicsScene::update(const float p_deltaTime)
 {
 {
-	for(decltype(m_physicsObjects.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_physicsObjects.getNumAllocated(),
-		size = m_physicsObjects.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
-	{
-		// Check if the physics object is allocated inside the pool container
-		if(m_physicsObjects[i].allocated())
-		{
-			auto *currentPhysicsObject = m_physicsObjects[i].getObject();
+	// Perform the physics simulation for the time step of the last frame
+	m_dynamicsWorld->stepSimulation(p_deltaTime);
 
 
-			// Increment the number of allocated objects (early bail mechanism)
-			numAllocObjecs++;
+	// Get the world scene required for getting the entity registry
+	WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
 
 
-			// Check if the GUI object is enabled
-			if(currentPhysicsObject->isObjectActive())
-			{
-				// Update the object
-				currentPhysicsObject->update(p_deltaTime);
-			}
-		}
+	// Get the entity registry 
+	auto &entityRegistry = worldScene->getEntityRegistry();
+
+	// Get the rigid body component view and iterate every entity that contains is
+	auto rigidBodyView = worldScene->getEntityRegistry().view<RigidBodyComponent>();
+	for(auto entity : rigidBodyView)
+	{
+		auto &component = rigidBodyView.get<RigidBodyComponent>(entity);
+
+		component.update(p_deltaTime);
 	}
 	}
 }
 }
 
 
@@ -134,13 +124,13 @@ ErrorCode PhysicsScene::preload()
 {	
 {	
 	// Load every physics object. It still works in parallel, however,
 	// Load every physics object. It still works in parallel, however,
 	// it returns only when all objects have finished loading (simulating sequential call)
 	// it returns only when all objects have finished loading (simulating sequential call)
-	TaskManagerLocator::get().parallelFor(size_t(0), m_physicsObjects.getPoolSize(), size_t(1), [=](size_t i)
+	/*TaskManagerLocator::get().parallelFor(size_t(0), m_physicsObjects.getPoolSize(), size_t(1), [=](size_t i)
 		{
 		{
 			if(m_physicsObjects[i].allocated())
 			if(m_physicsObjects[i].allocated())
 			{
 			{
 				m_physicsObjects[i].getObject()->loadToMemory();
 				m_physicsObjects[i].getObject()->loadToMemory();
 			}
 			}
-		});
+		});*/
 
 
 	return ErrorCode::Success;
 	return ErrorCode::Success;
 }
 }
@@ -149,10 +139,99 @@ void PhysicsScene::loadInBackground()
 {
 {
 }
 }
 
 
-SystemObject *PhysicsScene::createObject(const PropertySet &p_properties)
+SystemObject *PhysicsScene::createComponent(const EntityID &p_entityID, const std::string &p_entityName, const PropertySet &p_properties)
 {	
 {	
+	// If valid type was not specified, or object creation failed, return a null object instead
+	SystemObject *returnObject = g_nullSystemBase.getScene()->createObject(p_properties);
+
 	// Check if property set node is present
 	// Check if property set node is present
 	if(p_properties)
 	if(p_properties)
+	{
+		// Get the world scene required for attaching components to the entity
+		WorldScene *worldScene = static_cast<WorldScene *>(m_sceneLoader->getSystemScene(Systems::World));
+
+		switch(p_properties.getPropertyID())
+		{
+		case Properties::PropertyID::RigidBodyComponent:
+			{
+				auto &component = worldScene->addComponent<RigidBodyComponent>(p_entityID, this, p_entityName + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::RigidBodyComponent), p_entityID);
+
+				// Try to initialize the camera component
+				auto componentInitError = component.init();
+				if(componentInitError == ErrorCode::Success)
+				{
+					// Try to import the component
+					auto const &componentImportError = component.importObject(p_properties);
+
+					// Create the rigid body inside the dynamics world, if it was imported successfully
+					if(componentImportError == ErrorCode::Success)
+					{
+						//btCollisionShape *collisionShape = component.getCollisionShape();
+
+
+						//btVector3 localInertia(0, 0, 0);
+						// If mass is not zero, rigid body is dynamic; in that case, calculate local inertia 
+						//if(component.m_mass != 0.0f)
+						//	collisionShape->calculateLocalInertia(component.m_mass, localInertia);
+
+						// Set the body origin in space to the position in Spatial Component, if the Spatial Component is present
+						auto *spatialComponent = worldScene->getEntityRegistry().try_get<SpatialComponent>(p_entityID);
+						if(spatialComponent != nullptr)
+						{
+							btTransform groundTransform;
+							groundTransform.setIdentity();
+							groundTransform.setOrigin(Math::toBtVector3(spatialComponent->getSpatialDataChangeManager().getLocalSpaceData().m_spatialData.m_position));
+							groundTransform.setRotation(Math::toBtQuaternion(spatialComponent->getSpatialDataChangeManager().getLocalSpaceData().m_spatialData.m_rotationQuat));
+							//groundTransform.setFromOpenGLMatrix(&spatialComponent->getSpatialDataChangeManager().getLocalSpaceData().m_transformMat[0][0]);
+							component.m_motionState.setWorldTransform(groundTransform);
+
+							component.m_motionState.updateMotionStateTrans();
+						}
+						
+						// Set the required information for the rigid body constructor and create the rigid body
+						//btRigidBody::btRigidBodyConstructionInfo rigidBodyConstructor(component.m_mass, &component.m_motionState, collisionShape, localInertia);
+
+						// Add the collision shape
+						m_collisionShapes.push_back(component.getCollisionShape());
+
+						// Create the rigid body by passing the rigid body construction info
+						component.m_rigidBody = new btRigidBody(*component.m_constructionInfo);
+
+						if(component.m_kinematic)
+						{
+							component.m_rigidBody->setCollisionFlags(component.m_rigidBody->getCollisionFlags() | btCollisionObject::CollisionFlags::CF_KINEMATIC_OBJECT);
+							component.m_rigidBody->setActivationState(DISABLE_DEACTIVATION);						
+						}
+
+						// Add the rigid body to the dynamics world, essentially loading it into the physics system
+						m_dynamicsWorld->addRigidBody(component.m_rigidBody);
+
+						returnObject = &component;
+					}
+					else // Remove the component if it failed to import
+					{
+						worldScene->removeComponent<RigidBodyComponent>(p_entityID);
+						ErrHandlerLoc().get().log(componentImportError, ErrorSource::Source_RigidBodyComponent, p_entityName);
+					}
+				}
+				else // Remove the component if it failed to initialize
+				{
+					worldScene->removeComponent<RigidBodyComponent>(p_entityID);
+					ErrHandlerLoc().get().log(componentInitError, ErrorSource::Source_RigidBodyComponent, p_entityName);
+				}
+			}
+			break;
+
+		}
+	}
+
+	return returnObject;
+}
+
+SystemObject *PhysicsScene::createObject(const PropertySet &p_properties)
+{	
+	/*/ Check if property set node is present
+	if(p_properties)
 	{
 	{
 		// Check if the Physics property is present
 		// Check if the Physics property is present
 		auto &physicsProperty = p_properties.getPropertySetByID(Properties::Physics);
 		auto &physicsProperty = p_properties.getPropertySetByID(Properties::Physics);
@@ -189,7 +268,7 @@ SystemObject *PhysicsScene::createObject(const PropertySet &p_properties)
 				ErrHandlerLoc::get().log(ErrorCode::ObjectPool_full, ErrorSource::Source_GUIObject, "Failed to add PhysicsObject - \'" + nameProperty.getString() + "\'");
 				ErrHandlerLoc::get().log(ErrorCode::ObjectPool_full, ErrorSource::Source_GUIObject, "Failed to add PhysicsObject - \'" + nameProperty.getString() + "\'");
 			}
 			}
 		}
 		}
-	}
+	}*/
 
 
 	// If valid type was not specified, or object creation failed, return a null object instead
 	// If valid type was not specified, or object creation failed, return a null object instead
 	return g_nullSystemBase.getScene()->createObject(p_properties);
 	return g_nullSystemBase.getScene()->createObject(p_properties);

+ 4 - 5
Praxis3D/Source/PhysicsScene.h

@@ -1,5 +1,6 @@
 #pragma once
 #pragma once
 
 
+// TODO: add release and debug libs based on compile configuration
 #pragma comment(lib, "bullet/Bullet2FileLoader_Debug.lib")
 #pragma comment(lib, "bullet/Bullet2FileLoader_Debug.lib")
 #pragma comment(lib, "bullet/Bullet3Collision_Debug.lib")
 #pragma comment(lib, "bullet/Bullet3Collision_Debug.lib")
 #pragma comment(lib, "bullet/Bullet3Common_Debug.lib")
 #pragma comment(lib, "bullet/Bullet3Common_Debug.lib")
@@ -55,6 +56,7 @@ public:
 	// Exports all the data of the scene (including all objects within) as a PropertySet (for example, used for saving to map file)
 	// Exports all the data of the scene (including all objects within) as a PropertySet (for example, used for saving to map file)
 	PropertySet exportObject() { return PropertySet(); }
 	PropertySet exportObject() { return PropertySet(); }
 
 
+	SystemObject *createComponent(const EntityID &p_entityID, const std::string &p_entityName, const PropertySet &p_properties);
 	SystemObject *createObject(const PropertySet &p_properties);
 	SystemObject *createObject(const PropertySet &p_properties);
 	ErrorCode destroyObject(SystemObject *p_systemObject);
 	ErrorCode destroyObject(SystemObject *p_systemObject);
 
 
@@ -69,7 +71,7 @@ private:
 	// Removes an object from a pool, by iterating checking each pool for matched index; returns true if the object was found and removed
 	// Removes an object from a pool, by iterating checking each pool for matched index; returns true if the object was found and removed
 	inline bool removeObjectFromPool(PhysicsObject &p_object)
 	inline bool removeObjectFromPool(PhysicsObject &p_object)
 	{
 	{
-		// Go over each physics object
+		/*/ Go over each physics object
 		for(decltype(m_physicsObjects.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_physicsObjects.getNumAllocated(),
 		for(decltype(m_physicsObjects.getPoolSize()) i = 0, numAllocObjecs = 0, totalNumAllocObjs = m_physicsObjects.getNumAllocated(),
 			size = m_physicsObjects.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
 			size = m_physicsObjects.getPoolSize(); i < size && numAllocObjecs < totalNumAllocObjs; i++)
 		{
 		{
@@ -86,7 +88,7 @@ private:
 					return true;
 					return true;
 				}
 				}
 			}
 			}
-		}
+		}*/
 
 
 		return false;
 		return false;
 	}
 	}
@@ -98,9 +100,6 @@ private:
 
 
 	PhysicsTask *m_physicsTask;
 	PhysicsTask *m_physicsTask;
 
 
-	// Object pools
-	ObjectPool<PhysicsObject> m_physicsObjects;
-
 	// Collision configuration
 	// Collision configuration
 	btDefaultCollisionConfiguration *m_collisionConfiguration;
 	btDefaultCollisionConfiguration *m_collisionConfiguration;
 	btSequentialImpulseConstraintSolver *m_collisionSolver;
 	btSequentialImpulseConstraintSolver *m_collisionSolver;

+ 2 - 5
Praxis3D/Source/PhysicsSystem.h

@@ -18,6 +18,8 @@ public:
 	{
 	{
 		ErrorCode returnCode = ErrorCode::Success;
 		ErrorCode returnCode = ErrorCode::Success;
 
 
+		ErrHandlerLoc::get().log(ErrorCode::Initialize_success, ErrorSource::Source_Physics);
+
 		return returnCode;
 		return returnCode;
 	}
 	}
 
 
@@ -51,11 +53,6 @@ public:
 			{
 			{
 				ErrHandlerLoc::get().log(sceneError);
 				ErrHandlerLoc::get().log(sceneError);
 			}
 			}
-			else
-			{
-				// Check for errors
-				GLenum glError = glGetError();
-			}
 		}
 		}
 
 
 		return m_physicsScene;
 		return m_physicsScene;

+ 1 - 2
Praxis3D/Source/RendererScene.cpp

@@ -271,7 +271,7 @@ void RendererScene::update(const float p_deltaTime)
 	m_sceneObjects.m_spotLights.clear();
 	m_sceneObjects.m_spotLights.clear();
 	m_sceneObjects.m_loadToVideoMemory.clear();
 	m_sceneObjects.m_loadToVideoMemory.clear();
 
 
-	// Get the world scene required for attaching components to the entity
+	// Get the world scene required for getting the entity registry
 	WorldScene *worldScene = static_cast<WorldScene*>(m_sceneLoader->getSystemScene(Systems::World));
 	WorldScene *worldScene = static_cast<WorldScene*>(m_sceneLoader->getSystemScene(Systems::World));
 
 
 	// Get the entity registry 
 	// Get the entity registry 
@@ -914,7 +914,6 @@ SystemObject *RendererScene::createComponent(const EntityID &p_entityID, const s
 		{
 		{
 			case Properties::PropertyID::CameraComponent:
 			case Properties::PropertyID::CameraComponent:
 			{
 			{
-				//auto &component = worldScene->addComponent<CameraComponent>(p_entityID, this, p_entityName + Config::componentVar().camera_component_name);
 				auto &component = worldScene->addComponent<CameraComponent>(p_entityID, this, p_entityName + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::CameraComponent), p_entityID);
 				auto &component = worldScene->addComponent<CameraComponent>(p_entityID, this, p_entityName + Config::componentVar().component_name_separator + GetString(Properties::PropertyID::CameraComponent), p_entityID);
 
 
 				// Try to initialize the camera component
 				// Try to initialize the camera component

+ 1 - 1
Praxis3D/Source/RendererSystem.cpp

@@ -24,7 +24,7 @@ ErrorCode RendererSystem::init()
 	// Check if the renderer initialization was successful
 	// Check if the renderer initialization was successful
 	if(returnCode == ErrorCode::Success)
 	if(returnCode == ErrorCode::Success)
 	{
 	{
-		ErrHandlerLoc::get().log(ErrorType::Info, ErrorSource::Source_Renderer, "Renderer has been initialized");
+		ErrHandlerLoc::get().log(ErrorCode::Initialize_success, ErrorSource::Source_RendererSystem);
 	}
 	}
 
 
 	return returnCode;
 	return returnCode;

+ 123 - 23
Praxis3D/Source/RigidBodyComponent.h

@@ -5,6 +5,7 @@
 
 
 class RigidBodyComponent : public SystemObject, public LoadableGraphicsObject
 class RigidBodyComponent : public SystemObject, public LoadableGraphicsObject
 {
 {
+	friend class PhysicsScene;
 public:
 public:
 	enum CollisionShapeType : unsigned int
 	enum CollisionShapeType : unsigned int
 	{
 	{
@@ -17,9 +18,13 @@ public:
 		CollisionShapeType_Sphere
 		CollisionShapeType_Sphere
 	};
 	};
 
 
-	RigidBodyComponent(SystemScene *p_systemScene, std::string p_name, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::RigidBodyComponent)
+	RigidBodyComponent(SystemScene *p_systemScene, std::string p_name, const EntityID p_entityID, std::size_t p_id = 0) : SystemObject(p_systemScene, p_name, Properties::PropertyID::RigidBodyComponent, p_entityID)
 	{
 	{
 		m_collisionShapeType = CollisionShapeType::CollisionShapeType_Null;
 		m_collisionShapeType = CollisionShapeType::CollisionShapeType_Null;
+		m_collisionShape.m_boxShape = nullptr;
+		m_constructionInfo = nullptr;
+		m_rigidBody = nullptr;
+		m_kinematic = false;
 	}
 	}
 	~RigidBodyComponent()
 	~RigidBodyComponent()
 	{
 	{
@@ -48,6 +53,15 @@ public:
 
 
 	void update(const float p_deltaTime)
 	void update(const float p_deltaTime)
 	{
 	{
+		if(m_motionState.getMotionStateDirtyFlagAndReset())
+		{
+			m_motionState.updateMotionStateTrans();
+
+			postChanges(Systems::Changes::Spatial::LocalTransformNoScale);
+		}
+
+		//std::cout << m_motionState.getWorldTransform()[3].x << " : " << m_motionState.getWorldTransform()[3].y << " : " << m_motionState.getWorldTransform()[3].z << std::endl;
+
 		/*/ Perform updates only the if the script is loaded
 		/*/ Perform updates only the if the script is loaded
 		if(m_luaScriptLoaded)
 		if(m_luaScriptLoaded)
 		{
 		{
@@ -72,21 +86,8 @@ public:
 		// Check if PropertySet isn't empty and the component hasn't been loaded already
 		// Check if PropertySet isn't empty and the component hasn't been loaded already
 		if(p_properties && !isLoadedToMemory())
 		if(p_properties && !isLoadedToMemory())
 		{
 		{
-			if(p_properties.getPropertyID() == Properties::RigidBody)
+			if(p_properties.getPropertyID() == Properties::RigidBodyComponent)
 			{
 			{
-				// -----------------------------
-				// Load individual property data
-				// -----------------------------
-				for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
-				{
-					switch(p_properties[i].getPropertyID())
-					{
-					case Properties::Mass:
-
-					break;
-					}
-				}
-
 				// --------------------
 				// --------------------
 				// Load collision shape
 				// Load collision shape
 				// --------------------
 				// --------------------
@@ -109,7 +110,7 @@ public:
 							if(sizeProperty)
 							if(sizeProperty)
 								boxHalfExtents = Math::toBtVector3(sizeProperty.getVec3f());
 								boxHalfExtents = Math::toBtVector3(sizeProperty.getVec3f());
 							else
 							else
-								ErrHandlerLoc().get().log(ErrorType::Warning, ErrorSource::Source_CallisionShapeComponent, m_name + " - Missing \'" + GetString(Properties::Size) + "\' property");
+								ErrHandlerLoc().get().log(ErrorCode::Property_missing_size, m_name, ErrorSource::Source_RigidBodyComponent);
 
 
 							m_collisionShape.m_boxShape = new btBoxShape(boxHalfExtents);
 							m_collisionShape.m_boxShape = new btBoxShape(boxHalfExtents);
 							m_collisionShapeType = CollisionShapeType::CollisionShapeType_Box;
 							m_collisionShapeType = CollisionShapeType::CollisionShapeType_Box;
@@ -126,7 +127,7 @@ public:
 							if(radiusProperty)
 							if(radiusProperty)
 								radius = radiusProperty.getFloat();
 								radius = radiusProperty.getFloat();
 							else
 							else
-								ErrHandlerLoc().get().log(ErrorType::Warning, ErrorSource::Source_CallisionShapeComponent, m_name + " - Missing \'" + GetString(Properties::Radius) + "\' property");
+								ErrHandlerLoc().get().log(ErrorCode::Property_missing_radius, m_name, ErrorSource::Source_RigidBodyComponent);
 
 
 							m_collisionShape.m_sphereShape = new btSphereShape(radius);
 							m_collisionShape.m_sphereShape = new btSphereShape(radius);
 							m_collisionShapeType = CollisionShapeType::CollisionShapeType_Sphere;
 							m_collisionShapeType = CollisionShapeType::CollisionShapeType_Sphere;
@@ -137,22 +138,72 @@ public:
 							
 							
 							// If this is reached, the collision shape type was not valid
 							// If this is reached, the collision shape type was not valid
 							importError = ErrorCode::Failure;
 							importError = ErrorCode::Failure;
-							ErrHandlerLoc().get().log(ErrorType::Info, ErrorSource::Source_CallisionShapeComponent, m_name + " - Invalid collision type");
+							ErrHandlerLoc().get().log(ErrorCode::Collision_invalid, m_name, ErrorSource::Source_RigidBodyComponent);
 							break;
 							break;
 						}
 						}
 
 
 						// Success on the loaded collision shape
 						// Success on the loaded collision shape
 						importError = ErrorCode::Success;
 						importError = ErrorCode::Success;
-						ErrHandlerLoc().get().log(ErrorType::Info, ErrorSource::Source_CallisionShapeComponent, m_name + " - Collision shape loaded");
+						ErrHandlerLoc().get().log(ErrorType::Info, ErrorSource::Source_RigidBodyComponent, m_name + " - Collision shape loaded");
 
 
 					}
 					}
 					else
 					else
 					{
 					{
 						// Missing the Type property entirely
 						// Missing the Type property entirely
 						importError = ErrorCode::Failure;
 						importError = ErrorCode::Failure;
-						ErrHandlerLoc().get().log(ErrorType::Warning, ErrorSource::Source_CallisionShapeComponent, m_name + " - Missing \'" + GetString(Properties::Type) + "\' property");
+						ErrHandlerLoc().get().log(ErrorCode::Property_missing_type, m_name, ErrorSource::Source_RigidBodyComponent);
 					}
 					}
 				}
 				}
+
+				// Continue only if collision shape was created
+				if(m_collisionShapeType != CollisionShapeType::CollisionShapeType_Null)
+				{
+					// Create the struct that holds all the required information for constructing a rigid body
+					m_constructionInfo = new btRigidBody::btRigidBodyConstructionInfo(0.0f, &m_motionState, getCollisionShape());
+
+					// -----------------------------
+					// Load individual property data
+					// -----------------------------
+					for(decltype(p_properties.getNumProperties()) i = 0, size = p_properties.getNumProperties(); i < size; i++)
+					{
+						switch(p_properties[i].getPropertyID())
+						{
+						case Properties::Friction:
+							m_constructionInfo->m_friction = p_properties[i].getFloat();
+							break;
+						case Properties::Kinematic:
+							m_kinematic = p_properties[i].getBool();
+							break;
+						case Properties::Mass:
+							m_constructionInfo->m_mass = p_properties[i].getFloat();
+							break;
+						case Properties::Restitution:
+							m_constructionInfo->m_restitution = p_properties[i].getFloat();
+							break;
+						}
+					}
+
+					// If mass is not zero, rigid body is dynamic; in that case, calculate the local inertia 
+					if(m_constructionInfo->m_mass != 0.0f)
+					{
+						// Kinematic objects must have a mass of zero
+						if(m_kinematic)
+						{
+							m_constructionInfo->m_mass = 0.0f;
+							ErrHandlerLoc().get().log(ErrorCode::Kinematic_has_mass, m_name, ErrorSource::Source_RigidBodyComponent);
+						}
+						else
+							getCollisionShape()->calculateLocalInertia(m_constructionInfo->m_mass, m_constructionInfo->m_localInertia);
+					}
+				}
+				else
+				{
+					// Missing the collision shape
+					importError = ErrorCode::Failure;
+					ErrHandlerLoc().get().log(ErrorCode::Collision_missing, m_name, ErrorSource::Source_RigidBodyComponent);
+				}
+
+
 			}
 			}
 
 
 			if(importError == ErrorCode::Success)
 			if(importError == ErrorCode::Success)
@@ -176,8 +227,8 @@ public:
 	// System type is Physics
 	// System type is Physics
 	BitMask getSystemType() final override { return Systems::Physics; }
 	BitMask getSystemType() final override { return Systems::Physics; }
 
 
-	BitMask getDesiredSystemChanges() final override { return Systems::Changes::None; }
-	BitMask getPotentialSystemChanges() final override { return Systems::Changes::All; }
+	BitMask getDesiredSystemChanges() final override { return Systems::Changes::Spatial::AllLocal; }
+	BitMask getPotentialSystemChanges() final override { return Systems::Changes::Spatial::AllLocal; }
 
 
 	const inline CollisionShapeType getCollisionShapeType() const { return m_collisionShapeType; }
 	const inline CollisionShapeType getCollisionShapeType() const { return m_collisionShapeType; }
 	inline btCollisionShape *getCollisionShape()
 	inline btCollisionShape *getCollisionShape()
@@ -215,7 +266,49 @@ public:
 	inline btCylinderShape *getCollisionShapeCylinder()     { return m_collisionShapeType == CollisionShapeType::CollisionShapeType_Cylinder   ? m_collisionShape.m_cylinderShape   : nullptr; }
 	inline btCylinderShape *getCollisionShapeCylinder()     { return m_collisionShapeType == CollisionShapeType::CollisionShapeType_Cylinder   ? m_collisionShape.m_cylinderShape   : nullptr; }
 	inline btSphereShape *getCollisionShapeSphere()         { return m_collisionShapeType == CollisionShapeType::CollisionShapeType_Sphere     ? m_collisionShape.m_sphereShape     : nullptr; }
 	inline btSphereShape *getCollisionShapeSphere()         { return m_collisionShapeType == CollisionShapeType::CollisionShapeType_Sphere     ? m_collisionShape.m_sphereShape     : nullptr; }
 
 
-	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType) { }
+	void changeOccurred(ObservedSubject *p_subject, BitMask p_changeType)
+	{
+		// Track what data has been modified
+		BitMask newChanges = Systems::Changes::None;
+
+		// Consider ignoring LocalTransform change, as Bullet can only accept a transform matrix that does not have scale applied to it. LocalTransform however includes scaling.
+		// To avoid scaled transform, only the position is retrieved from the LocalTransform, and the rotation is retrieved by getting a LocalRotation quaternion.
+		// This might cause a problem of getting an out-of-date rotation, as it is not certain if the LocalRotation quaternion has been updated.
+		if(CheckBitmask(p_changeType, Systems::Changes::Spatial::LocalTransform))
+		{
+			m_motionState.setPosition(p_subject->getMat4(this, Systems::Changes::Spatial::LocalTransform));
+			m_motionState.setRotation(p_subject->getQuaternion(this, Systems::Changes::Spatial::LocalRotation));
+
+			newChanges |= Systems::Changes::Spatial::LocalTransformNoScale;
+		}
+
+		if(CheckBitmask(p_changeType, Systems::Changes::Spatial::LocalTransformNoScale))
+		{
+			m_motionState.setWorldTransform(p_subject->getMat4(this, Systems::Changes::Spatial::LocalTransformNoScale));
+
+			newChanges |= Systems::Changes::Spatial::LocalTransformNoScale;
+		}
+		
+		if(CheckBitmask(p_changeType, Systems::Changes::Spatial::LocalPosition))
+		{
+			m_motionState.setPosition(p_subject->getVec3(this, Systems::Changes::Spatial::LocalPosition));
+
+			newChanges |= Systems::Changes::Spatial::LocalPosition;
+		}
+
+		if(CheckBitmask(p_changeType, Systems::Changes::Spatial::LocalRotation))
+		{
+			m_motionState.setRotation(p_subject->getQuaternion(this, Systems::Changes::Spatial::LocalRotation));
+
+			newChanges |= Systems::Changes::Spatial::LocalRotation;
+		}
+
+		postChanges(newChanges);
+	}
+
+	const glm::mat4 &getMat4(const Observer *p_observer, BitMask p_changedBits)								const override { return m_motionState.getWorldTransform(); }
+	const glm::quat &getQuaternion(const Observer *p_observer, BitMask p_changedBits)						const override { return m_motionState.getRotation(); }
+	const glm::vec3 &getVec3(const Observer *p_observer, BitMask p_changedBits)								const override { return m_motionState.getPosition(); }
 
 
 private:
 private:
 	union
 	union
@@ -230,4 +323,11 @@ private:
 
 
 	CollisionShapeType m_collisionShapeType;
 	CollisionShapeType m_collisionShapeType;
 
 
+	btRigidBody *m_rigidBody; 
+	
+	btRigidBody::btRigidBodyConstructionInfo *m_constructionInfo;
+
+	PhysicsMotionState m_motionState;
+
+	bool m_kinematic;
 };
 };

+ 90 - 75
Praxis3D/Source/SceneLoader.cpp

@@ -7,104 +7,119 @@
 
 
 ErrorCode SceneLoader::loadFromFile(const std::string &p_filename)
 ErrorCode SceneLoader::loadFromFile(const std::string &p_filename)
 {
 {
+	ErrorCode returnError = ErrorCode::Success;
+
 	// Load properties from file
 	// Load properties from file
 	PropertyLoader loadedProperties(Config::filepathVar().map_path + p_filename);
 	PropertyLoader loadedProperties(Config::filepathVar().map_path + p_filename);
-	const ErrorCode loaderError = loadedProperties.loadFromFile();
+	returnError = loadedProperties.loadFromFile();
 
 
 	// Check if loading was successful, return an error, if not
 	// Check if loading was successful, return an error, if not
-	if(loaderError != ErrorCode::Success)
-		return loaderError;
-
-	std::vector<std::pair<const std::string&, SystemObject*>> createdObjects;
+	if(returnError != ErrorCode::Success)
+	{
+		ErrHandlerLoc().get().log(returnError, ErrorSource::Source_SceneLoader);
+	}
+	else
+	{
 
 
-	// Get systems property set
-	auto &systemProperties = loadedProperties.getPropertySet().getPropertySetByID(Properties::Systems);
+		std::vector<std::pair<const std::string &, SystemObject *>> createdObjects;
 
 
-	// Iterate over all systems scenes
-	for(int sysIndex = 0; sysIndex < Systems::NumberOfSystems; sysIndex++)
-	{
-		// Create an empty property set, in case there is none in the loaded file, because a system scene setup must be called either way
-		PropertySet scenePropertySet;
+		// Get systems property set
+		auto &systemProperties = loadedProperties.getPropertySet().getPropertySetByID(Properties::Systems);
 
 
-		// Iterate over each system property set
-		for(decltype(systemProperties.getNumPropertySets()) propIndex = 0, propSize = systemProperties.getNumPropertySets(); propIndex < propSize; propIndex++)
+		// Iterate over all systems scenes
+		for(int sysIndex = 0; sysIndex < Systems::NumberOfSystems; sysIndex++)
 		{
 		{
-			// If the system scene property matches in the loaded file, retrieve it so it can be passed to the corresponding scene
-			if(Systems::SystemNames[m_systemScenes[sysIndex]->getSystemType()] == GetString(systemProperties.getPropertySetUnsafe(propIndex).getPropertyID()))
-				scenePropertySet = systemProperties.getPropertySetUnsafe(propIndex).getPropertySetByID(Properties::Scene);
-		}
+			// Create an empty property set, in case there is none in the loaded file, because a system scene setup must be called either way
+			PropertySet scenePropertySet;
 
 
-		// Pass the scene propertySet parameters
-		m_systemScenes[sysIndex]->setup(scenePropertySet);
-	}
+			// Iterate over each system property set
+			for(decltype(systemProperties.getNumPropertySets()) propIndex = 0, propSize = systemProperties.getNumPropertySets(); propIndex < propSize; propIndex++)
+			{
+				// If the system scene property matches in the loaded file, retrieve it so it can be passed to the corresponding scene
+				if(Systems::SystemNames[m_systemScenes[sysIndex]->getSystemType()] == GetString(systemProperties.getPropertySetUnsafe(propIndex).getPropertyID()))
+					scenePropertySet = systemProperties.getPropertySetUnsafe(propIndex).getPropertySetByID(Properties::Scene);
+			}
 
 
-	// Get Game Objects
-	auto &gameObjects = loadedProperties.getPropertySet().getPropertySetByID(Properties::GameObject);
+			// Pass the scene propertySet parameters
+			m_systemScenes[sysIndex]->setup(scenePropertySet);
+		}
 
 
-	// Iterate over all game object
-	for(decltype(gameObjects.getNumPropertySets()) objIndex = 0, objSize = gameObjects.getNumPropertySets(); objIndex < objSize; objIndex++)
-	{
-		// Create each game object by passing its PropertySet
-		m_systemScenes[Systems::World]->createObject(gameObjects.getPropertySetUnsafe(objIndex));
-	}
+		// Get Game Objects
+		auto &gameObjects = loadedProperties.getPropertySet().getPropertySetByID(Properties::GameObject);
+
+		if(gameObjects)
+		{
+			// Iterate over all game object
+			for(decltype(gameObjects.getNumPropertySets()) objIndex = 0, objSize = gameObjects.getNumPropertySets(); objIndex < objSize; objIndex++)
+			{
+				// Create each game object by passing its PropertySet
+				m_systemScenes[Systems::World]->createObject(gameObjects.getPropertySetUnsafe(objIndex));
+			}
+		}
+		else
+		{
+			returnError = ErrorCode::GameObjects_missing;
+			ErrHandlerLoc().get().log(ErrorCode::GameObjects_missing, ErrorSource::Source_SceneLoader);
+		}
 
 
-	/*/ Get the object link property sets
-	auto &objLinkProperties = loadedProperties.getPropertySet().getPropertySetByID(Properties::ObjectLinks);
+		/*/ Get the object link property sets
+		auto &objLinkProperties = loadedProperties.getPropertySet().getPropertySetByID(Properties::ObjectLinks);
 
 
-	// Iterate over all object link property sets
-	for(decltype(objLinkProperties.getNumPropertySets()) linkIndex = 0, linkSize = objLinkProperties.getNumPropertySets(); linkIndex < linkSize; linkIndex++)
-	{
-		// Get subject name
-		const auto &subjectName = objLinkProperties.getPropertySetUnsafe(linkIndex).getPropertyByID(Properties::Subject).getString();
-		if(subjectName.empty()) // Make sure subject's name is not empty
-			continue;
-
-		// Get observer name
-		const auto &observerName = objLinkProperties.getPropertySetUnsafe(linkIndex).getPropertyByID(Properties::Observer).getString();
-		if(observerName.empty()) // Make sure observer's name is not empty
-			continue;
-
-		// Iterate over created objects and match subject's name
-		for(decltype(createdObjects.size()) subjIndex = 0, subjSize = createdObjects.size(); subjIndex < subjSize; subjIndex++)
+		// Iterate over all object link property sets
+		for(decltype(objLinkProperties.getNumPropertySets()) linkIndex = 0, linkSize = objLinkProperties.getNumPropertySets(); linkIndex < linkSize; linkIndex++)
 		{
 		{
-			// Compare subject name
-			if(createdObjects[subjIndex].first == subjectName)
+			// Get subject name
+			const auto &subjectName = objLinkProperties.getPropertySetUnsafe(linkIndex).getPropertyByID(Properties::Subject).getString();
+			if(subjectName.empty()) // Make sure subject's name is not empty
+				continue;
+
+			// Get observer name
+			const auto &observerName = objLinkProperties.getPropertySetUnsafe(linkIndex).getPropertyByID(Properties::Observer).getString();
+			if(observerName.empty()) // Make sure observer's name is not empty
+				continue;
+
+			// Iterate over created objects and match subject's name
+			for(decltype(createdObjects.size()) subjIndex = 0, subjSize = createdObjects.size(); subjIndex < subjSize; subjIndex++)
 			{
 			{
-				// Iterate over created objects and match observer's name
-				for(decltype(createdObjects.size()) observIndex = 0, observSize = createdObjects.size(); observIndex < observSize; observIndex++)
+				// Compare subject name
+				if(createdObjects[subjIndex].first == subjectName)
 				{
 				{
-					// Compare observer name
-					if(createdObjects[observIndex].first == observerName)
+					// Iterate over created objects and match observer's name
+					for(decltype(createdObjects.size()) observIndex = 0, observSize = createdObjects.size(); observIndex < observSize; observIndex++)
 					{
 					{
-						// Create object link between subject and observer in the change controller
-						m_changeController->createObjectLink(createdObjects[subjIndex].second, createdObjects[observIndex].second);
-						
-						// Exit the inner loop
-						break;
+						// Compare observer name
+						if(createdObjects[observIndex].first == observerName)
+						{
+							// Create object link between subject and observer in the change controller
+							m_changeController->createObjectLink(createdObjects[subjIndex].second, createdObjects[observIndex].second);
+
+							// Exit the inner loop
+							break;
+						}
 					}
 					}
-				}
 
 
-				// Exit the outer loop
-				break;
+					// Exit the outer loop
+					break;
+				}
 			}
 			}
-		}
-	}*/
+		}*/
 
 
-	// Check if the scene should be loaded in background
-	if(loadedProperties.getPropertySet().getPropertyByID(Properties::LoadInBackground).getBool())
-	{
-		// Start loading in background threads in all scenes
-		for(int i = 0; i < Systems::NumberOfSystems; i++)
-			m_systemScenes[i]->loadInBackground();
-	}
-	else
-	{
-		// Preload all scenes sequentially
-		for(int i = 0; i < Systems::NumberOfSystems; i++)
-			m_systemScenes[i]->preload();
+		// Check if the scene should be loaded in background
+		if(loadedProperties.getPropertySet().getPropertyByID(Properties::LoadInBackground).getBool())
+		{
+			// Start loading in background threads in all scenes
+			for(int i = 0; i < Systems::NumberOfSystems; i++)
+				m_systemScenes[i]->loadInBackground();
+		}
+		else
+		{
+			// Preload all scenes sequentially
+			for(int i = 0; i < Systems::NumberOfSystems; i++)
+				m_systemScenes[i]->preload();
+		}
 	}
 	}
 
 
-	return ErrorCode::Success;
+	return returnError;
 }
 }
 
 
 ErrorCode SceneLoader::saveToFile(const std::string p_filename)
 ErrorCode SceneLoader::saveToFile(const std::string p_filename)

+ 1 - 1
Praxis3D/Source/ScriptScene.cpp

@@ -66,7 +66,7 @@ void ScriptScene::update(const float p_deltaTime)
 		if(luaComponent.isObjectActive())
 		if(luaComponent.isObjectActive())
 		{
 		{
 			// Update the object
 			// Update the object
-			luaComponent.update(p_deltaTime, spatialComponent);
+  			luaComponent.update(p_deltaTime, spatialComponent);
 		}
 		}
 	}
 	}
 
 

+ 1 - 1
Praxis3D/Source/ScriptSystem.cpp

@@ -19,7 +19,7 @@ ErrorCode ScriptSystem::init()
 {
 {
 	ErrorCode returnCode = ErrorCode::Success;
 	ErrorCode returnCode = ErrorCode::Success;
 	
 	
-	ErrHandlerLoc::get().log(ErrorType::Info, ErrorSource::Source_Script, "Script system has been initialized");
+	ErrHandlerLoc::get().log(ErrorCode::Initialize_success, ErrorSource::Source_Script);
 	
 	
 	return returnCode;
 	return returnCode;
 }
 }

+ 9 - 3
Praxis3D/Source/SpatialComponent.h

@@ -9,8 +9,8 @@ class SpatialComponent : public SystemObject
 {
 {
 	friend class WorldScene;
 	friend class WorldScene;
 public:
 public:
-	SpatialComponent(SystemScene *p_systemScene, const std::string &p_name)
-		: SystemObject(p_systemScene, p_name, Properties::SpatialComponent), m_spatialData(*this) //m_spatialData{*this, *this}
+	SpatialComponent(SystemScene *p_systemScene, const std::string &p_name, EntityID p_entityID)
+		: SystemObject(p_systemScene, p_name, Properties::SpatialComponent, p_entityID), m_spatialData(*this) //m_spatialData{*this, *this}
 	{
 	{
 	}
 	}
 	~SpatialComponent()
 	~SpatialComponent()
@@ -62,7 +62,13 @@ public:
 		BitMask newChanges = Systems::Changes::None;
 		BitMask newChanges = Systems::Changes::None;
 
 
 		// Process the spatial changes and record the world-space changes
 		// Process the spatial changes and record the world-space changes
-		newChanges = m_spatialData.changeOccurred(*p_subject, p_changeType & Systems::Changes::Spatial::All);
+		/*newChanges = */m_spatialData.changeOccurred(*p_subject, p_changeType & Systems::Changes::Spatial::All);
+
+		// Update spatial data
+		m_spatialData.update();
+
+		// Get any changes of the spatial data
+		newChanges = m_spatialData.getCurrentChangesAndReset();
 
 
 		// If any data has been updated, post the changes to listeners
 		// If any data has been updated, post the changes to listeners
 		if(newChanges != Systems::Changes::None)
 		if(newChanges != Systems::Changes::None)

+ 14 - 1
Praxis3D/Source/SpatialDataManager.h

@@ -182,6 +182,13 @@ public:
 						setLocalTransform(p_subject.getMat4(&m_parent, Systems::Changes::Spatial::LocalTransform));
 						setLocalTransform(p_subject.getMat4(&m_parent, Systems::Changes::Spatial::LocalTransform));
 						localOrWorldTransformChanged = true;
 						localOrWorldTransformChanged = true;
 					}
 					}
+
+					if(CheckBitmask(p_changeType, Systems::Changes::Spatial::LocalTransformNoScale))
+					{
+						// Scale the local transform before assigning it
+						setLocalTransform(glm::scale(p_subject.getMat4(&m_parent, Systems::Changes::Spatial::LocalTransform), m_localSpace.m_spatialData.m_scale));
+						localOrWorldTransformChanged = true;
+					}
 				}
 				}
 			}
 			}
 
 
@@ -195,7 +202,7 @@ public:
 			{
 			{
 				if(CheckBitmask(p_changeType, Systems::Changes::Spatial::WorldTransform))
 				if(CheckBitmask(p_changeType, Systems::Changes::Spatial::WorldTransform))
 				{
 				{
-					setWorldTransform(p_subject.getMat4(&m_parent, Systems::Changes::Spatial::WorldTransform));
+					setParentTransform(p_subject.getMat4(&m_parent, Systems::Changes::Spatial::WorldTransform));
 					localOrWorldTransformChanged = true;
 					localOrWorldTransformChanged = true;
 				}
 				}
 			}
 			}
@@ -257,6 +264,12 @@ public:
 		case Systems::Changes::Spatial::LocalTransform:
 		case Systems::Changes::Spatial::LocalTransform:
 			return m_localSpace.m_transformMat;
 			return m_localSpace.m_transformMat;
 
 
+		// Construct a local transform matrix without scaling it
+		case Systems::Changes::Spatial::LocalTransformNoScale:
+			return Math::createTransformMat(
+				m_localSpace.m_spatialData.m_position,
+				m_localSpace.m_spatialData.m_rotationQuat);
+		
 		case Systems::Changes::Spatial::WorldTransform:
 		case Systems::Changes::Spatial::WorldTransform:
 			return m_worldTransform;
 			return m_worldTransform;
 		}
 		}

+ 47 - 7
Praxis3D/Source/WorldScene.cpp

@@ -140,16 +140,18 @@ SystemObject *WorldScene::createObject(const PropertySet &p_properties)
 		}
 		}
 	}
 	}
 
 
+	SpatialComponent *spatialComponent = nullptr;
+
 	// Add WORLD components
 	// Add WORLD components
 	auto &worldProperty = p_properties.getPropertySetByID(Properties::World);
 	auto &worldProperty = p_properties.getPropertySetByID(Properties::World);
 	if(worldProperty)
 	if(worldProperty)
 	{
 	{
-		// Add SPACIAL COMPONENT
+		// Add SPATIAL COMPONENT
 		auto &spatialComponentProperty = worldProperty.getPropertySetByID(Properties::SpatialComponent);
 		auto &spatialComponentProperty = worldProperty.getPropertySetByID(Properties::SpatialComponent);
 		if(spatialComponentProperty)
 		if(spatialComponentProperty)
 		{
 		{
 			//auto spatial = m_entityRegistry.emplace<SpatialComponent>(newEntity, this, name);
 			//auto spatial = m_entityRegistry.emplace<SpatialComponent>(newEntity, this, name);
-			SpatialComponent &newSpatialComponent = addComponent<SpatialComponent>(newEntity, this, name + Config::componentVar().component_name_separator + GetString(Properties::SpatialComponent));
+			SpatialComponent &newSpatialComponent = addComponent<SpatialComponent>(newEntity, this, name + Config::componentVar().component_name_separator + GetString(Properties::SpatialComponent), newEntity);
 
 
 			// Load property data
 			// Load property data
 			for(decltype(spatialComponentProperty.getNumProperties()) i = 0, size = spatialComponentProperty.getNumProperties(); i < size; i++)
 			for(decltype(spatialComponentProperty.getNumProperties()) i = 0, size = spatialComponentProperty.getNumProperties(); i < size; i++)
@@ -173,6 +175,8 @@ SystemObject *WorldScene::createObject(const PropertySet &p_properties)
 
 
 			// Perform a spatial data update, so that all the transform matrices are calculated
 			// Perform a spatial data update, so that all the transform matrices are calculated
 			newSpatialComponent.m_spatialData.update();
 			newSpatialComponent.m_spatialData.update();
+
+			spatialComponent = &newSpatialComponent;
 		}
 		}
 	}
 	}
 
 
@@ -229,19 +233,55 @@ SystemObject *WorldScene::createObject(const PropertySet &p_properties)
 			{
 			{
 				auto *component = scene->createComponent(newEntity, name, sceneProperty.getPropertySet(i));
 				auto *component = scene->createComponent(newEntity, name, sceneProperty.getPropertySet(i));
 
 
-				auto *spatialComponent = m_entityRegistry.try_get<SpatialComponent>(newEntity);
-				if(spatialComponent != nullptr)
-					m_sceneLoader->getChangeController()->createObjectLink(component, spatialComponent);
+				//auto *spatialComponent = m_entityRegistry.try_get<SpatialComponent>(newEntity);
+				//if(spatialComponent != nullptr)
+				//	m_sceneLoader->getChangeController()->createObjectLink(component, spatialComponent);
 
 
 				// Create subject-observer object links between scripting components (subject) and GUI components (observers)
 				// Create subject-observer object links between scripting components (subject) and GUI components (observers)
-				for(decltype(guiComponents.size()) size = guiComponents.size(), i = 0; i < size; i++)
-					m_sceneLoader->getChangeController()->createObjectLink(component, guiComponents[i]);
+				//for(decltype(guiComponents.size()) size = guiComponents.size(), i = 0; i < size; i++)
+				//	m_sceneLoader->getChangeController()->createObjectLink(component, guiComponents[i]);
 
 
 				scriptingComponents.push_back(component);
 				scriptingComponents.push_back(component);
 			}
 			}
 		}
 		}
 	}
 	}
 
 
+	// Link subjects and observers of different components
+
+	if(spatialComponent != nullptr)
+	{
+		// Link PHYSICS -> SPATIAL
+		for(decltype(physicsComponents.size()) i = 0, size = physicsComponents.size(); i < size; i++)
+		{
+			m_sceneLoader->getChangeController()->createObjectLink(physicsComponents[i], spatialComponent);
+		}
+	}
+
+	// Link SCRIPTING
+	for(decltype(scriptingComponents.size()) scriptingIndex = 0, scriptingSize = scriptingComponents.size(); scriptingIndex < scriptingSize; scriptingIndex++)
+	{
+		// If there are no physics components, link to spatial directly. If there are physics components, link to physics components instead
+		if(physicsComponents.empty())
+		{
+			// Link SCRIPTING -> SPATIAL
+			if(spatialComponent != nullptr)
+				m_sceneLoader->getChangeController()->createObjectLink(scriptingComponents[scriptingIndex], spatialComponent);
+		}
+		else
+		{
+			// Link SCRIPTING -> PHYSICS
+			for(decltype(physicsComponents.size()) physicsIndex = 0, physicsSize = physicsComponents.size(); physicsIndex < physicsSize; physicsIndex++)
+				m_sceneLoader->getChangeController()->createObjectLink(scriptingComponents[scriptingIndex], physicsComponents[physicsIndex]);
+		}
+			
+		// Link SCRIPTING -> GUI
+		for(decltype(guiComponents.size()) guiIndex = 0, guiSize = guiComponents.size(); guiIndex < guiSize; guiIndex++)
+		{
+			m_sceneLoader->getChangeController()->createObjectLink(scriptingComponents[scriptingIndex], guiComponents[guiIndex]);
+		}
+	}
+
+
 	return newGameObject;
 	return newGameObject;
 
 
 
 

+ 2 - 0
Praxis3D/Source/WorldSystem.h

@@ -17,6 +17,8 @@ public:
 	{
 	{
 		ErrorCode returnCode = ErrorCode::Success;
 		ErrorCode returnCode = ErrorCode::Success;
 
 
+		ErrHandlerLoc::get().log(ErrorCode::Initialize_success, ErrorSource::Source_WorldSystem);
+
 		return returnCode;
 		return returnCode;
 	}
 	}