From 2a9f4d779da6f3f9d25a132fa233d8cb6efe23fd Mon Sep 17 00:00:00 2001 From: jonpas <jonpas33@gmail.com> Date: Sat, 9 May 2015 03:09:26 +0200 Subject: [PATCH 01/51] Lowercased beginning of function names --- .../{fnc_AddSelectableItem.sqf => fnc_addSelectableItem.sqf} | 0 .../interaction/functions/{fnc_MoveDown.sqf => fnc_moveDown.sqf} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename addons/interaction/functions/{fnc_AddSelectableItem.sqf => fnc_addSelectableItem.sqf} (100%) rename addons/interaction/functions/{fnc_MoveDown.sqf => fnc_moveDown.sqf} (100%) diff --git a/addons/interaction/functions/fnc_AddSelectableItem.sqf b/addons/interaction/functions/fnc_addSelectableItem.sqf similarity index 100% rename from addons/interaction/functions/fnc_AddSelectableItem.sqf rename to addons/interaction/functions/fnc_addSelectableItem.sqf diff --git a/addons/interaction/functions/fnc_MoveDown.sqf b/addons/interaction/functions/fnc_moveDown.sqf similarity index 100% rename from addons/interaction/functions/fnc_MoveDown.sqf rename to addons/interaction/functions/fnc_moveDown.sqf From 50d5e845ee517ca28d10393adfe6cf399d8ea0f3 Mon Sep 17 00:00:00 2001 From: jonpas <jonpas33@gmail.com> Date: Sat, 9 May 2015 03:12:28 +0200 Subject: [PATCH 02/51] Lowercased beginning of functions pt2 --- addons/interaction/functions/fnc_moveDown.sqf | 4 ++-- addons/interaction/functions/fnc_openMenuSelectUI.sqf | 2 +- addons/interaction/functions/fnc_prepareSelectMenu.sqf | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/addons/interaction/functions/fnc_moveDown.sqf b/addons/interaction/functions/fnc_moveDown.sqf index eac30e4008..3b7a7074e9 100644 --- a/addons/interaction/functions/fnc_moveDown.sqf +++ b/addons/interaction/functions/fnc_moveDown.sqf @@ -11,8 +11,8 @@ Nothing Example: - 1 call FUNC(MoveDown); - -1 call FUNC(MoveDown); + 1 call FUNC(moveDown); + -1 call FUNC(moveDown); */ #include "script_component.hpp" diff --git a/addons/interaction/functions/fnc_openMenuSelectUI.sqf b/addons/interaction/functions/fnc_openMenuSelectUI.sqf index a13fa6a9f0..55eaba6423 100644 --- a/addons/interaction/functions/fnc_openMenuSelectUI.sqf +++ b/addons/interaction/functions/fnc_openMenuSelectUI.sqf @@ -26,7 +26,7 @@ _actions = [localize "STR_ACE_Interaction_InteractionMenu", localize "STR_ACE_In [_x] call EFUNC(common,getName), QUOTE(PATHTOF(UI\dot_ca.paa)), _forEachIndex - ] call FUNC(AddSelectableItem); + ] call FUNC(addSelectableItem); }; } forEach _cargo; diff --git a/addons/interaction/functions/fnc_prepareSelectMenu.sqf b/addons/interaction/functions/fnc_prepareSelectMenu.sqf index 593f0d4c47..34a1bfea5b 100644 --- a/addons/interaction/functions/fnc_prepareSelectMenu.sqf +++ b/addons/interaction/functions/fnc_prepareSelectMenu.sqf @@ -9,7 +9,7 @@ 1: TEXT - Approve button text Returns: - ARRAY/NUMBER - container object for use with AddSelectableItem. + ARRAY/NUMBER - container object for use with addSelectableItem. Example: ["Select Explosive", "Place"] call FUNC(prepareSelectMenu); From 2ff372e2a1f56801935340684018dbd4c68a870c Mon Sep 17 00:00:00 2001 From: jonpas <jonpas33@gmail.com> Date: Sat, 9 May 2015 04:47:15 +0200 Subject: [PATCH 03/51] Function headers per Coding Guidelines for Interaction --- .../functions/fnc_addPassengerActions.sqf | 5 +- .../functions/fnc_addPassengersActions.sqf | 7 ++- .../functions/fnc_addSelectableItem.sqf | 34 ++++++------- .../functions/fnc_applyButtons.sqf | 17 ++++++- .../functions/fnc_canBecomeLeader.sqf | 4 +- .../functions/fnc_canInteractWithCivilian.sqf | 19 +++++-- .../functions/fnc_canJoinGroup.sqf | 17 ++++++- .../interaction/functions/fnc_canJoinTeam.sqf | 17 ++++++- .../functions/fnc_canTapShoulder.sqf | 18 ++++++- .../functions/fnc_doBecomeLeader.sqf | 4 +- addons/interaction/functions/fnc_getDoor.sqf | 18 ++++++- .../functions/fnc_getDoorAnimations.sqf | 19 ++++++- addons/interaction/functions/fnc_getDown.sqf | 12 +++-- .../functions/fnc_getSelectedButton.sqf | 16 +++++- .../functions/fnc_getWeaponPos.sqf | 5 +- addons/interaction/functions/fnc_hideMenu.sqf | 30 +++++------ .../functions/fnc_hideMouseHint.sqf | 31 ++++++----- .../interaction/functions/fnc_isInRange.sqf | 14 +++-- addons/interaction/functions/fnc_joinTeam.sqf | 17 ++++++- .../functions/fnc_moduleInteraction.sqf | 14 +++-- addons/interaction/functions/fnc_moveDown.sqf | 29 +++++------ .../interaction/functions/fnc_onButtonUp.sqf | 16 +++++- addons/interaction/functions/fnc_onClick.sqf | 16 +++++- .../functions/fnc_onSelectMenuDblClick.sqf | 16 +++++- addons/interaction/functions/fnc_openDoor.sqf | 17 ++++++- .../functions/fnc_openMenuSelectUI.sqf | 51 ++++++++++++------- .../functions/fnc_openSelectMenu.sqf | 45 ++++++++-------- .../functions/fnc_prepareSelectMenu.sqf | 30 +++++------ addons/interaction/functions/fnc_push.sqf | 15 ++++-- .../interaction/functions/fnc_removeTag.sqf | 16 +++++- addons/interaction/functions/fnc_sendAway.sqf | 32 +++++++----- .../functions/fnc_showMouseHint.sqf | 35 +++++++------ .../functions/fnc_sortOptionsByPriority.sqf | 16 +++++- .../interaction/functions/fnc_tapShoulder.sqf | 17 ++++++- .../functions/fnc_updateTooltipPosition.sqf | 18 ++++++- 35 files changed, 490 insertions(+), 197 deletions(-) diff --git a/addons/interaction/functions/fnc_addPassengerActions.sqf b/addons/interaction/functions/fnc_addPassengerActions.sqf index 82e3b3b4fb..f17ca649c2 100644 --- a/addons/interaction/functions/fnc_addPassengerActions.sqf +++ b/addons/interaction/functions/fnc_addPassengerActions.sqf @@ -2,7 +2,7 @@ * Author: esteldunedain * Mount unit actions inside passenger submenu * - * Argument: + * Arguments: * 0: Vehicle <OBJECT> * 1: Player <OBJECT> * 3: Parameters <ARRAY> @@ -10,6 +10,9 @@ * Return value: * Children actions <ARRAY> * + * Example: + * _array = [vehicle, player, [params]] call ace_interaction_fnc_addPassengerAction + * * Public: No */ #include "script_component.hpp" diff --git a/addons/interaction/functions/fnc_addPassengersActions.sqf b/addons/interaction/functions/fnc_addPassengersActions.sqf index c446be3737..661c43a643 100644 --- a/addons/interaction/functions/fnc_addPassengersActions.sqf +++ b/addons/interaction/functions/fnc_addPassengersActions.sqf @@ -2,7 +2,7 @@ * Author: esteldunedain * Create one action per passenger * - * Argument: + * Arguments: * 0: Vehicle <OBJECT> * 1: Player <OBJECT> * 3: Parameters <ARRAY> @@ -10,6 +10,9 @@ * Return value: * Children actions <ARRAY> * + * Example: + * _array = [vehicle, player, [params]] call ace_interaction_fnc_addPassengersActions + * * Public: No */ #include "script_component.hpp" @@ -39,4 +42,4 @@ _actions = []; }; } forEach crew _vehicle; -_actions \ No newline at end of file +_actions diff --git a/addons/interaction/functions/fnc_addSelectableItem.sqf b/addons/interaction/functions/fnc_addSelectableItem.sqf index 498b852635..8f5676b4ca 100644 --- a/addons/interaction/functions/fnc_addSelectableItem.sqf +++ b/addons/interaction/functions/fnc_addSelectableItem.sqf @@ -1,21 +1,21 @@ /* - Author: Garth de Wet (LH) - - Description: - Adds an item to the select menu - - Parameters: - 0: ARRAY/NUMBER - List container - 1: String - Display Name - 2: String - Picture - 3: String/code - data - - Returns: - ARRAY/Number - - Example: -*/ - + * Author: Garth de Wet (LH) + * Adds an item to the select menu + * + * Arguments: + * 0: List container <ARRAY/NUMBER> + * 1: Display name <STRING> + * 2: Picture <STRING> + * 3: Data <STRING/CODE> + * + * Return value: + * Container <ARRAY/NUMBER> + * + * Example: + * _array = [_actions, "Banana", "UI\dot_ca.paa", data] call ace_interaction_fnc_addSelectableItem + * + * Public: No + */ #include "script_component.hpp" private ["_container", "_displayName", "_picture", "_data", "_index"]; diff --git a/addons/interaction/functions/fnc_applyButtons.sqf b/addons/interaction/functions/fnc_applyButtons.sqf index be35b34877..5baa158eb5 100644 --- a/addons/interaction/functions/fnc_applyButtons.sqf +++ b/addons/interaction/functions/fnc_applyButtons.sqf @@ -1,5 +1,18 @@ -// by commy2 - +/* + * Author: commy2 + * Applies buttons + * + * Arguments: + * None + * + * Return value: + * None + * + * Example: + * call ace_interaction_fnc_applyButtons + * + * Public: No + */ #include "script_component.hpp" private ["_object", "_actions", "_dlgInteractionDialog", "_ctrlInteractionDialog", "_index", "_ctrlInteractionDialogIcon"]; diff --git a/addons/interaction/functions/fnc_canBecomeLeader.sqf b/addons/interaction/functions/fnc_canBecomeLeader.sqf index 11234ad6d7..0bb555c49a 100644 --- a/addons/interaction/functions/fnc_canBecomeLeader.sqf +++ b/addons/interaction/functions/fnc_canBecomeLeader.sqf @@ -7,10 +7,10 @@ * 1: player <OBJECT> * * Return Value: - * <BOOL> + * Able to become leader of group <BOOL> * * Example: - * [player, player] call ace_interaction_fnc_canBecomeLeader + * _bool = [player, player] call ace_interaction_fnc_canBecomeLeader * * Public: No */ diff --git a/addons/interaction/functions/fnc_canInteractWithCivilian.sqf b/addons/interaction/functions/fnc_canInteractWithCivilian.sqf index 6408d66aa8..c89f4c9868 100644 --- a/addons/interaction/functions/fnc_canInteractWithCivilian.sqf +++ b/addons/interaction/functions/fnc_canInteractWithCivilian.sqf @@ -1,5 +1,18 @@ -// by commy2 - +/* + * Author: commy2 + * Checks if the player can interact with civilian + * + * Arguments: + * 0: Target <OBJECT> + * + * Return value: + * Able to interact with civilian <BOOL> + * + * Example: + * _bool = [target] call ace_interaction_fnc_canInteractWithCivilian + * + * Public: No + */ #include "script_component.hpp" EXPLODE_2_PVT(_this,_unit,_isCivilian); @@ -8,4 +21,4 @@ if (isNil "_isCivilian") then {_isCivilian = true}; alive _unit && [side _unit != side ACE_player, side group _unit == civilian] select _isCivilian -//&& {count (weapons _unit) == 0} \ No newline at end of file +//&& {count (weapons _unit) == 0} diff --git a/addons/interaction/functions/fnc_canJoinGroup.sqf b/addons/interaction/functions/fnc_canJoinGroup.sqf index d299524925..26597ca0a0 100644 --- a/addons/interaction/functions/fnc_canJoinGroup.sqf +++ b/addons/interaction/functions/fnc_canJoinGroup.sqf @@ -1,4 +1,19 @@ -// by commy2 +/* + * Author: commy2 + * Checks if the player can join a group + * + * Arguments: + * 0: Player <OBJECT> + * 1: Target <OBJECT> + * + * Return value: + * Able to join a group <BOOL> + * + * Example: + * _bool = [player, target] call ace_interaction_fnc_canJoinGroup + * + * Public: No + */ #include "script_component.hpp" private ["_unit", "_target"]; diff --git a/addons/interaction/functions/fnc_canJoinTeam.sqf b/addons/interaction/functions/fnc_canJoinTeam.sqf index 45f96393a9..4312981978 100644 --- a/addons/interaction/functions/fnc_canJoinTeam.sqf +++ b/addons/interaction/functions/fnc_canJoinTeam.sqf @@ -1,4 +1,19 @@ -// by commy2 +/* + * Author: commy2 + * Checks if the player can join a team + * + * Arguments: + * 0: Player <OBJECT> + * 1: Target <OBJECT> + * + * Return value: + * Able to join a team <BOOL> + * + * Example: + * _bool = [player, target] call ace_interaction_fnc_canJoinTeam + * + * Public: No + */ #include "script_component.hpp" private ["_unit", "_target"]; diff --git a/addons/interaction/functions/fnc_canTapShoulder.sqf b/addons/interaction/functions/fnc_canTapShoulder.sqf index 4ea9836117..2be9bf70a9 100644 --- a/addons/interaction/functions/fnc_canTapShoulder.sqf +++ b/addons/interaction/functions/fnc_canTapShoulder.sqf @@ -1,5 +1,19 @@ -// by commy2 - +/* + * Author: commy2 + * Checks if the player can tap a shoulder + * + * Arguments: + * 0: Player <OBJECT> + * 1: Target <OBJECT> + * + * Return value: + * Able to tap a shoulder <BOOL> + * + * Example: + * _bool = [player, target] call ace_interaction_fnc_canTapShoulder + * + * Public: No + */ #include "script_component.hpp" private ["_unit", "_target"]; diff --git a/addons/interaction/functions/fnc_doBecomeLeader.sqf b/addons/interaction/functions/fnc_doBecomeLeader.sqf index 24bfa66c11..0fd81cbc96 100644 --- a/addons/interaction/functions/fnc_doBecomeLeader.sqf +++ b/addons/interaction/functions/fnc_doBecomeLeader.sqf @@ -3,8 +3,8 @@ * Become Leader of group * * Arguments: - * 0: target <OBJECT> - * 1: player <OBJECT> + * 0: Target <OBJECT> + * 1: Player <OBJECT> * * Return Value: * None diff --git a/addons/interaction/functions/fnc_getDoor.sqf b/addons/interaction/functions/fnc_getDoor.sqf index 91c2161d9f..460a325954 100644 --- a/addons/interaction/functions/fnc_getDoor.sqf +++ b/addons/interaction/functions/fnc_getDoor.sqf @@ -1,4 +1,20 @@ -// by commy2 +/* + * Author: commy2 + * Get door + * + * Arguments: + * 0: Distance <NUMBER> + * + * Return value: + * House objects and door <ARRAY> + * 0: House <OBJECT> + * 1: Door Name <STRING> + * + * Example: + * _array = [player, target] call ace_interaction_fnc_getDoor + * + * Public: No + */ #include "script_component.hpp" private ["_distance", "_position0", "_position1", "_intersections", "_count", "_house", "_door", "_index", "_id"]; diff --git a/addons/interaction/functions/fnc_getDoorAnimations.sqf b/addons/interaction/functions/fnc_getDoorAnimations.sqf index ca59ec177c..cb0b7122b0 100644 --- a/addons/interaction/functions/fnc_getDoorAnimations.sqf +++ b/addons/interaction/functions/fnc_getDoorAnimations.sqf @@ -1,4 +1,21 @@ -// by commy2 +/* + * Author: commy2 + * Get door animations + * + * Arguments: + * 0: House <OBJECT> + * 1: Door <STRING> + * + * Return value: + * Animation and Locked variable <ARRAY> + * 0: Animation <STRING> + * 1: Locked variable <STRING> + * + * Example: + * _array = [target, "door"] call ace_interaction_fnc_getDoorAnimations + * + * Public: No + */ #include "script_component.hpp" private ["_house", "_door", "_animations", "_lockedVariable"]; diff --git a/addons/interaction/functions/fnc_getDown.sqf b/addons/interaction/functions/fnc_getDown.sqf index ead5dcd290..9e7daecb46 100644 --- a/addons/interaction/functions/fnc_getDown.sqf +++ b/addons/interaction/functions/fnc_getDown.sqf @@ -1,13 +1,17 @@ /* * Author: KoffeinFlummi - * - * Forces a civilian to the ground. (chance of failure). + * Forces a civilian to the ground (with a chance of failure) * * Arguments: - * 0: Unit to be sent away (Object) + * 0: Unit <OBJECT> * * Return value: - * none + * None + * + * Example: + * [target] call ace_interaction_fnc_getDown + * + * Public: No */ #include "script_component.hpp" diff --git a/addons/interaction/functions/fnc_getSelectedButton.sqf b/addons/interaction/functions/fnc_getSelectedButton.sqf index d1c801e1dc..52ba3d67e0 100644 --- a/addons/interaction/functions/fnc_getSelectedButton.sqf +++ b/addons/interaction/functions/fnc_getSelectedButton.sqf @@ -1,4 +1,18 @@ -// by commy2 +/* + * Author: commy2 + * Get selected button + * + * Arguments: + * None + * + * Return value: + * Angle <NUMBER> + * + * Example: + * _number = call ace_interaction_fnc_getSelectedButton + * + * Public: No + */ #include "script_component.hpp" #define MIN_DISTANCE 0.0065 diff --git a/addons/interaction/functions/fnc_getWeaponPos.sqf b/addons/interaction/functions/fnc_getWeaponPos.sqf index 477e74f9bf..35ea202b1d 100644 --- a/addons/interaction/functions/fnc_getWeaponPos.sqf +++ b/addons/interaction/functions/fnc_getWeaponPos.sqf @@ -2,12 +2,15 @@ * Author: esteldunedain * Return a suitable position for the action point for the current weapon * - * Argument: + * Arguments: * None * * Return value: * Children actions <ARRAY> * + * Example: + * _array = call ace_interaction_fnc_getWeaponPos + * * Public: No */ #include "script_component.hpp" diff --git a/addons/interaction/functions/fnc_hideMenu.sqf b/addons/interaction/functions/fnc_hideMenu.sqf index 54263ef032..89dc49be40 100644 --- a/addons/interaction/functions/fnc_hideMenu.sqf +++ b/addons/interaction/functions/fnc_hideMenu.sqf @@ -1,22 +1,22 @@ /* - Author: Garth de Wet (LH) - - Description: - Closes the Interaction menu - - Parameters: - Nothing - - Returns: - Nothing - - Example: - call FUNC(hideMenu); -*/ + * Author: Garth de Wet (LH) + * Closes the Interaction menu + * + * Arguments: + * None + * + * Return value: + * None + * + * Example: + * call ace_interaction_fnc_hideMenu + * + * Public: No + */ #include "script_component.hpp" closeDialog 0; (findDisplay 1713999) closeDisplay 1; (uiNameSpace getVariable QGVAR(Flow_Display)) closeDisplay 0; GVAR(MainButton) = nil; -call FUNC(hideMouseHint); \ No newline at end of file +call FUNC(hideMouseHint); diff --git a/addons/interaction/functions/fnc_hideMouseHint.sqf b/addons/interaction/functions/fnc_hideMouseHint.sqf index d910352076..69acba25a2 100644 --- a/addons/interaction/functions/fnc_hideMouseHint.sqf +++ b/addons/interaction/functions/fnc_hideMouseHint.sqf @@ -1,22 +1,21 @@ /* - Author(s): - Garth de Wet (LH) - - Description: - Hides the interaction helper text with the mouse buttons at the bottom middle of the screen - - Parameters: - Nothing - - Returns: - Nothing - - Example: - call FUNC(hideMouseHint); -*/ + * Author: Garth de Wet (LH) + * Hides the interaction helper text with the mouse buttons at the bottom middle of the screen + * + * Arguments: + * None + * + * Return value: + * None + * + * Example: + * call ace_interaction_fnc_hideMouseHint + * + * Public: No + */ #include "script_component.hpp" if (isNull (uiNamespace getVariable ["ACE_Helper_Display", objNull])) exitWith{}; (QGVAR(InteractionHelper) call BIS_fnc_rscLayer) cutText ["", "PLAIN"]; -showHUD true; \ No newline at end of file +showHUD true; diff --git a/addons/interaction/functions/fnc_isInRange.sqf b/addons/interaction/functions/fnc_isInRange.sqf index 5048b66001..05677d7060 100644 --- a/addons/interaction/functions/fnc_isInRange.sqf +++ b/addons/interaction/functions/fnc_isInRange.sqf @@ -1,14 +1,18 @@ /* * Author: commy2 - * * Check if the vehicle is in range of the player. * - * Argument: - * 0: Vehicke (Object) - * 1: Distance in meters (Number) + * Arguments: + * 0: Vehicle <OBJECT> + * 1: Distance in meters <NUMBER> * * Return value: - * (Bool) + * Vehicle in range of player <BOOL> + * + * Example: + * _bool = [target, 5] call ace_interaction_fnc_isInRange + * + * Public: No */ #include "script_component.hpp" diff --git a/addons/interaction/functions/fnc_joinTeam.sqf b/addons/interaction/functions/fnc_joinTeam.sqf index 2e4d1f2898..cf6889d90a 100644 --- a/addons/interaction/functions/fnc_joinTeam.sqf +++ b/addons/interaction/functions/fnc_joinTeam.sqf @@ -1,4 +1,19 @@ -// by commy2 +/* + * Author: commy2 + * Assigns a unit to the team + * + * Arguments: + * 0: Unit <OBJECT> + * 1: Team <STRING> + * + * Return value: + * None + * + * Example: + * [target, "YELLOW"] call ace_interaction_fnc_joinTeam + * + * Public: No + */ #include "script_component.hpp" private ["_unit", "_team", "_message"]; diff --git a/addons/interaction/functions/fnc_moduleInteraction.sqf b/addons/interaction/functions/fnc_moduleInteraction.sqf index 37b7bacba5..925847c028 100644 --- a/addons/interaction/functions/fnc_moduleInteraction.sqf +++ b/addons/interaction/functions/fnc_moduleInteraction.sqf @@ -1,13 +1,19 @@ /* * Author: bux578 - * - * Initializes the Interaction module. + * Initializes the Interaction module * * Arguments: - * Whatever the module provides. (I dunno.) + * 0: Logic <NUMBER> + * 1: ??? + * 2: Activation State <BOOL> * - * Return Value: + * Return value: * None + * + * Example: + * [logic, ???, activationState] call ace_interaction_fnc_moduleInteraction + * + * Public: No */ #include "script_component.hpp" diff --git a/addons/interaction/functions/fnc_moveDown.sqf b/addons/interaction/functions/fnc_moveDown.sqf index 3b7a7074e9..eb946a5f10 100644 --- a/addons/interaction/functions/fnc_moveDown.sqf +++ b/addons/interaction/functions/fnc_moveDown.sqf @@ -1,19 +1,18 @@ /* - Author: Garth de Wet (LH) - - Description: - Depending on the passed value, either scrolls down through the list or up. - - Parameters: - NUMBER - Amount to increase current interaction target - - Returns: - Nothing - - Example: - 1 call FUNC(moveDown); - -1 call FUNC(moveDown); -*/ + * Author: Garth de Wet (LH) + * Scrolls through the list down or up + * + * Arguments: + * 0: Amount <NUMBER> + * + * Return value: + * None + * + * Example: + * [2] call ace_interaction_fnc_moveDown + * + * Public: No + */ #include "script_component.hpp" #define CLAMP(x,low,high) (if(x > high)then{high}else{if(x < low)then{low}else{x}}) diff --git a/addons/interaction/functions/fnc_onButtonUp.sqf b/addons/interaction/functions/fnc_onButtonUp.sqf index cee524c55f..151ce67c98 100644 --- a/addons/interaction/functions/fnc_onButtonUp.sqf +++ b/addons/interaction/functions/fnc_onButtonUp.sqf @@ -1,4 +1,18 @@ -// by commy2 +/* + * Author: commy2 + * On button up + * + * Arguments: + * None + * + * Return value: + * None + * + * Example: + * call ace_interaction_fnc_onButtonUp + * + * Public: No + */ #include "script_component.hpp" private ["_player", "_vehicle", "_target", "_count", "_index", "_action", "_statement", "_condition", "_conditionShow", "_exceptions", "_distance"]; diff --git a/addons/interaction/functions/fnc_onClick.sqf b/addons/interaction/functions/fnc_onClick.sqf index 29fffb8b94..6f9882281f 100644 --- a/addons/interaction/functions/fnc_onClick.sqf +++ b/addons/interaction/functions/fnc_onClick.sqf @@ -1,4 +1,18 @@ -// by commy2 +/* + * Author: commy2 + * On click + * + * Arguments: + * Index <NUMBER> + * + * Return value: + * None + * + * Example: + * 5 call ace_interaction_fnc_onClick + * + * Public: No + */ #include "script_component.hpp" private ["_player", "_vehicle", "_target", "_count", "_index", "_action", "_subMenu", "_statement", "_condition", "_conditionShow", "_exceptions", "_distance"]; diff --git a/addons/interaction/functions/fnc_onSelectMenuDblClick.sqf b/addons/interaction/functions/fnc_onSelectMenuDblClick.sqf index 25d307a2eb..18b69ba40d 100644 --- a/addons/interaction/functions/fnc_onSelectMenuDblClick.sqf +++ b/addons/interaction/functions/fnc_onSelectMenuDblClick.sqf @@ -1,4 +1,18 @@ -// by CorruptedHeart, commy2 +/* + * Author: CorruptedHeart, commy2 + * On select menu double click + * + * Arguments: + * None + * + * Return value: + * None + * + * Example: + * call ace_interaction_fnc_onSelectMenuDblClick + * + * Public: No + */ #include "script_component.hpp" call compile (lbData [8866, lbCurSel 8866]) call GVAR(SelectAccept); diff --git a/addons/interaction/functions/fnc_openDoor.sqf b/addons/interaction/functions/fnc_openDoor.sqf index e175e752cb..3e776f3538 100644 --- a/addons/interaction/functions/fnc_openDoor.sqf +++ b/addons/interaction/functions/fnc_openDoor.sqf @@ -1,4 +1,19 @@ -// by commy2 +/* + * Author: commy2 + * Opens door + * + * Arguments: + * 0: House <OBJECT> + * 1: Door <STRING> + * + * Return value: + * None + * + * Example: + * [house, "door"] call ace_interaction_fnc_openDoor + * + * Public: No + */ #include "script_component.hpp" private ["_info", "_house", "_door", "_animations", "_lockedVariable"]; diff --git a/addons/interaction/functions/fnc_openMenuSelectUI.sqf b/addons/interaction/functions/fnc_openMenuSelectUI.sqf index 55eaba6423..e755869ed1 100644 --- a/addons/interaction/functions/fnc_openMenuSelectUI.sqf +++ b/addons/interaction/functions/fnc_openMenuSelectUI.sqf @@ -1,4 +1,19 @@ -// by commy2 +/* + * Author: commy2 + * Opens menu select UI + * + * Arguments: + * 0: Unit <OBJECT> + * 1: Vehicle <OBJECT> + * + * Return value: + * None + * + * Example: + * [unit, vehicle] call ace_interaction_fnc_openMenuSelectUI + * + * Public: No + */ #include "script_component.hpp" private ["_unit", "_vehicle", "_cargo"]; @@ -20,25 +35,25 @@ _actions = [localize "STR_ACE_Interaction_InteractionMenu", localize "STR_ACE_In // prepare: add all cargo units as options to select menu { - if (_x != _unit) then { - _actions = [ - _actions, - [_x] call EFUNC(common,getName), - QUOTE(PATHTOF(UI\dot_ca.paa)), - _forEachIndex - ] call FUNC(addSelectableItem); - }; + if (_x != _unit) then { + _actions = [ + _actions, + [_x] call EFUNC(common,getName), + QUOTE(PATHTOF(UI\dot_ca.paa)), + _forEachIndex + ] call FUNC(addSelectableItem); + }; } forEach _cargo; // open select menu [ - _actions, - { - call FUNC(hideMenu); - [0, GVAR(InteractionMenu_Crew) select _this, ""] spawn FUNC(showMenu); - GVAR(InteractionMenu_Crew) = nil; - }, - { - call FUNC(hideMenu); - } + _actions, + { + call FUNC(hideMenu); + [0, GVAR(InteractionMenu_Crew) select _this, ""] spawn FUNC(showMenu); + GVAR(InteractionMenu_Crew) = nil; + }, + { + call FUNC(hideMenu); + } ] call FUNC(openSelectMenu); diff --git a/addons/interaction/functions/fnc_openSelectMenu.sqf b/addons/interaction/functions/fnc_openSelectMenu.sqf index de5459f88c..13e02fb044 100644 --- a/addons/interaction/functions/fnc_openSelectMenu.sqf +++ b/addons/interaction/functions/fnc_openSelectMenu.sqf @@ -1,26 +1,27 @@ /* - Author: Garth de Wet (LH) - - Description: - Opens the select menu UI and sets up the UI - - Parameters: - 0: ARRAY - items - ARRAY - 0 = Text - 1 = statement to execute - 2 = condition before execute - 3 = showDisabled - 4 = priority - 5 = icon - 6 = extra variables. Passed to the code. - 1: Code - select action - 2: Code - Cancel Action - Returns: - Nothing - - Example: -*/ + * Author: Garth de Wet (LH) + * Opens the select menu UI and sets up the UI + * + * Arguments: + * 0: Items <ARRAY> + * 0: Text <STRING> + * 1: Statement to execute <CODE> + * 2: Condition before execute <CODE> + * 3: showDisabled <BOOL> + * 4: Priority <NUMBER> + * 5: Icon <STRING> + * 6: Extra variables passed to the code <ARRAY> + * 1: Select Action <CODE> + * 2: Cancel Action <CODE> + * + * Return value: + * None + * + * Example: + * [["text", {statement}, {condition}, showDisabled, priority, "icon", [variables]], {selectAction}, {cancelAction}] call ace_interaction_fnc_openSelectMenu + * + * Public: No + */ #include "script_component.hpp" if (!(profileNamespace getVariable [QGVAR(FlowMenu), false])) then { diff --git a/addons/interaction/functions/fnc_prepareSelectMenu.sqf b/addons/interaction/functions/fnc_prepareSelectMenu.sqf index 34a1bfea5b..f43ec75c4e 100644 --- a/addons/interaction/functions/fnc_prepareSelectMenu.sqf +++ b/addons/interaction/functions/fnc_prepareSelectMenu.sqf @@ -1,19 +1,19 @@ /* - Author: Garth de Wet (LH) - - Description: - Prepares the select menu for use. - - Parameters: - 0: TEXT - Header text - 1: TEXT - Approve button text - - Returns: - ARRAY/NUMBER - container object for use with addSelectableItem. - - Example: - ["Select Explosive", "Place"] call FUNC(prepareSelectMenu); -*/ + * Author: Garth de Wet (LH) + * Prepares the select menu for use + * + * Arguments: + * 0: Header Text <STRING> + * 1: Approve Button Text <STRING> + * + * Return value: + * Container object <ARRAY/NUMBER> + * + * Example: + * _array = ["Select Explosive", "Place"] call ace_interaction_fnc_prepareSelectMenu + * + * Public: No + */ #include "script_component.hpp" private ["_buttonAction", "_header", "_buttonText", "_cancelButton"]; diff --git a/addons/interaction/functions/fnc_push.sqf b/addons/interaction/functions/fnc_push.sqf index f52a9d40de..580f687f64 100644 --- a/addons/interaction/functions/fnc_push.sqf +++ b/addons/interaction/functions/fnc_push.sqf @@ -1,22 +1,27 @@ /* * Author: KoffeinFlummi - * - * Pushes a boat away from the player. + * Pushes a boat away from the player * * Arguments: - * 0: Boat (object) - * 1: Velocity (vectorlike array) + * 0: Boat <OBJECT> + * 1: Velocity <ARRAY> * * Return Value: * None + * + * Example: + * [target, [vector]] call ace_interaction_fnc_push + * + * Public: No */ + #include "script_component.hpp" _boat = _this select 0; _velocity = _this select 1; if !(local _boat) exitWith { - [_this, QUOTE(FUNC(push)), _boat] call EFUNC(common,execRemoteFnc); + [_this, QUOTE(FUNC(push)), _boat] call EFUNC(common,execRemoteFnc); }; _boat setVelocity _velocity; diff --git a/addons/interaction/functions/fnc_removeTag.sqf b/addons/interaction/functions/fnc_removeTag.sqf index 0894520149..d1a16bf88b 100644 --- a/addons/interaction/functions/fnc_removeTag.sqf +++ b/addons/interaction/functions/fnc_removeTag.sqf @@ -1,4 +1,18 @@ -// by commy2 +/* + * Author: commy2 + * Removes tag + * + * Arguments: + * None + * + * Return value: + * None + * + * Example: + * call ace_interaction_fnc_removeTag + * + * Public: No + */ #include "script_component.hpp" 0 spawn { diff --git a/addons/interaction/functions/fnc_sendAway.sqf b/addons/interaction/functions/fnc_sendAway.sqf index 5cd6a9d43a..1a48725644 100644 --- a/addons/interaction/functions/fnc_sendAway.sqf +++ b/addons/interaction/functions/fnc_sendAway.sqf @@ -1,14 +1,18 @@ /* * Author: KoffeinFlummi - * - * Sends a civilian crowd away (chance of failure). + * Sends a civilian crowd away with a chance of failure * * Arguments: - * 0: Unit to be sent away (Object) + * 0: Unit <OBJECT> * * Return value: - * none -*/ + * None + * + * Example: + * [target] call ace_interaction_fnc_sendAway + * + * Public: No + */ #include "script_component.hpp" #define DISTANCE 50 @@ -21,16 +25,16 @@ _unit = _this select 0; ACE_player playActionNow "GestureGo"; if (count weapons ACE_player > 0) then { - _chance = 0.8; + _chance = 0.8; } else { - _chance = 0.5; + _chance = 0.5; }; { - if (count (weapons _unit) == 0 and random 1 < _chance) then { - [-2, { - (_this select 0) setUnitPos "AUTO"; - (_this select 0) doMove [(getPos (_this select 0) select 0) + DISTANCE * (eyeDirection (_this select 1) select 0), (getPos (_this select 0) select 1) + DISTANCE * (eyeDirection (_this select 1) select 1), 0]; - }, [_x, ACE_player]] call CBA_fnc_globalExecute; - }; -} foreach (_unit nearEntities ["Civilian", RADIUS]); + if (count (weapons _unit) == 0 and random 1 < _chance) then { + [-2, { + (_this select 0) setUnitPos "AUTO"; + (_this select 0) doMove [(getPos (_this select 0) select 0) + DISTANCE * (eyeDirection (_this select 1) select 0), (getPos (_this select 0) select 1) + DISTANCE * (eyeDirection (_this select 1) select 1), 0]; + }, [_x, ACE_player]] call CBA_fnc_globalExecute; + }; +} forEach (_unit nearEntities ["Civilian", RADIUS]); diff --git a/addons/interaction/functions/fnc_showMouseHint.sqf b/addons/interaction/functions/fnc_showMouseHint.sqf index 5cb96a0eae..a64114d009 100644 --- a/addons/interaction/functions/fnc_showMouseHint.sqf +++ b/addons/interaction/functions/fnc_showMouseHint.sqf @@ -1,21 +1,20 @@ /* - Author(s): - Garth de Wet (LH) - - Description: - Shows the interaction helper text with the mouse buttons at the bottom middle of the screen - - Parameters: - 0: STRING - Left click text - 1: STRING - Right click text - 3: STRING - (Optional) Scroll text - - Returns: - Nothing - - Example: - ["Place Explosive", "Cancel"] call FUNC(showMouseHint); -*/ + * Author: Garth de Wet (LH) + * Shows the interaction helper text with the mouse buttons at the bottom middle of the screen + * + * Arguments: + * 0: Left Click Text <STRING> + * 1: Right Click Text <STRING> + * 2: Scroll Text <STRING> (Optional) + * + * Return value: + * None + * + * Example: + * ["Place Explosive", "Cancel"] call ace_interaction_fnc_showMouseHint + * + * Public: No + */ #include "script_component.hpp" #define GUI_GRID_W (0.025) @@ -51,4 +50,4 @@ if (_scroll == "") exitWith { (_display displayCtrl 1201) ctrlCommit 0; }; (_display displayCtrl 1002) ctrlSetText _scroll; -showHUD false; \ No newline at end of file +showHUD false; diff --git a/addons/interaction/functions/fnc_sortOptionsByPriority.sqf b/addons/interaction/functions/fnc_sortOptionsByPriority.sqf index 28daa4e7e5..ce4c714d79 100644 --- a/addons/interaction/functions/fnc_sortOptionsByPriority.sqf +++ b/addons/interaction/functions/fnc_sortOptionsByPriority.sqf @@ -1,4 +1,18 @@ -// by commy2 +/* + * Author: commy2 + * Sort options by priority + * + * Arguments: + * Actions <ARRAY> + * + * Return value: + * None + * + * Example: + * _customActions call ace_interaction_fnc_sortOptionsByPriority + * + * Public: No + */ #include "script_component.hpp" private ["_actions", "_count", "_index", "_actionN", "_actionM"]; diff --git a/addons/interaction/functions/fnc_tapShoulder.sqf b/addons/interaction/functions/fnc_tapShoulder.sqf index 11fc6b7881..f18c9c2c30 100644 --- a/addons/interaction/functions/fnc_tapShoulder.sqf +++ b/addons/interaction/functions/fnc_tapShoulder.sqf @@ -1,4 +1,19 @@ -// by commy2 +/* + * Author: commy2 + * Taps a shoulder + * + * Arguments: + * 0: Player <OBJECT> + * 1: Target <OBJECT> + * + * Return value: + * None + * + * Example: + * [player, target] call ace_interaction_fnc_tapShoulder + * + * Public: No + */ #include "script_component.hpp" EXPLODE_3_PVT(_this,_tapper,_target,_shoulderNum); diff --git a/addons/interaction/functions/fnc_updateTooltipPosition.sqf b/addons/interaction/functions/fnc_updateTooltipPosition.sqf index 27148c5aa3..c194102b41 100644 --- a/addons/interaction/functions/fnc_updateTooltipPosition.sqf +++ b/addons/interaction/functions/fnc_updateTooltipPosition.sqf @@ -1,4 +1,20 @@ -// by commy2 +/* + * Author: commy2 + * Updates tooltip's position + * + * Arguments: + * 0: Tooltip Display <NUMBER> + * 1: X Coordinate <NUMBER> + * 2: Y Coordinate <NUMBER> + * + * Return value: + * None + * + * Example: + * [player, 0.5, 0.5] call ace_interaction_fnc_updateTooltipPosition + * + * Public: No + */ #include "script_component.hpp" disableSerialization; From e9abd8c27a423c65aa39fd1ba18014f394194d60 Mon Sep 17 00:00:00 2001 From: jonpas <jonpas33@gmail.com> Date: Sat, 9 May 2015 04:55:41 +0200 Subject: [PATCH 04/51] Fixed lowercasing, improved examples --- addons/interaction/functions/fnc_addPassengerActions.sqf | 2 +- addons/interaction/functions/fnc_addPassengersActions.sqf | 2 +- addons/interaction/functions/fnc_addSelectableItem.sqf | 2 +- addons/interaction/functions/fnc_canBecomeLeader.sqf | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/interaction/functions/fnc_addPassengerActions.sqf b/addons/interaction/functions/fnc_addPassengerActions.sqf index f17ca649c2..4474378bcc 100644 --- a/addons/interaction/functions/fnc_addPassengerActions.sqf +++ b/addons/interaction/functions/fnc_addPassengerActions.sqf @@ -11,7 +11,7 @@ * Children actions <ARRAY> * * Example: - * _array = [vehicle, player, [params]] call ace_interaction_fnc_addPassengerAction + * _array = [target, player, [params]] call ace_interaction_fnc_addPassengerAction * * Public: No */ diff --git a/addons/interaction/functions/fnc_addPassengersActions.sqf b/addons/interaction/functions/fnc_addPassengersActions.sqf index 661c43a643..d1565f8d9a 100644 --- a/addons/interaction/functions/fnc_addPassengersActions.sqf +++ b/addons/interaction/functions/fnc_addPassengersActions.sqf @@ -11,7 +11,7 @@ * Children actions <ARRAY> * * Example: - * _array = [vehicle, player, [params]] call ace_interaction_fnc_addPassengersActions + * _array = [target, player, [params]] call ace_interaction_fnc_addPassengersActions * * Public: No */ diff --git a/addons/interaction/functions/fnc_addSelectableItem.sqf b/addons/interaction/functions/fnc_addSelectableItem.sqf index 8f5676b4ca..6f1339d25a 100644 --- a/addons/interaction/functions/fnc_addSelectableItem.sqf +++ b/addons/interaction/functions/fnc_addSelectableItem.sqf @@ -12,7 +12,7 @@ * Container <ARRAY/NUMBER> * * Example: - * _array = [_actions, "Banana", "UI\dot_ca.paa", data] call ace_interaction_fnc_addSelectableItem + * _array = [_actions, "Banana", "UI\dot_ca.paa", "bananaContents"] call ace_interaction_fnc_addSelectableItem * * Public: No */ diff --git a/addons/interaction/functions/fnc_canBecomeLeader.sqf b/addons/interaction/functions/fnc_canBecomeLeader.sqf index 0bb555c49a..c79f879525 100644 --- a/addons/interaction/functions/fnc_canBecomeLeader.sqf +++ b/addons/interaction/functions/fnc_canBecomeLeader.sqf @@ -3,8 +3,8 @@ * Test if can Become Leader of group * * Arguments: - * 0: target <OBJECT> - * 1: player <OBJECT> + * 0: Target <OBJECT> + * 1: Player <OBJECT> * * Return Value: * Able to become leader of group <BOOL> From f685ec2257f2eba28b9ea7e02b17d2cbebc0c22a Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Sat, 9 May 2015 20:24:39 +0100 Subject: [PATCH 05/51] added zeus changes module --- addons/zeus/$PBOPREFIX$ | 1 + addons/zeus/CfgEventHandlers.hpp | 6 + addons/zeus/XEH_preInit.sqf | 7 + addons/zeus/config.cpp | 22 ++ .../zeus/functions/fnc_bi_moduleCurator.sqf | 310 ++++++++++++++++++ addons/zeus/functions/script_component.hpp | 1 + addons/zeus/script_component.hpp | 12 + 7 files changed, 359 insertions(+) create mode 100644 addons/zeus/$PBOPREFIX$ create mode 100644 addons/zeus/CfgEventHandlers.hpp create mode 100644 addons/zeus/XEH_preInit.sqf create mode 100644 addons/zeus/config.cpp create mode 100644 addons/zeus/functions/fnc_bi_moduleCurator.sqf create mode 100644 addons/zeus/functions/script_component.hpp create mode 100644 addons/zeus/script_component.hpp diff --git a/addons/zeus/$PBOPREFIX$ b/addons/zeus/$PBOPREFIX$ new file mode 100644 index 0000000000..ae5a20d62d --- /dev/null +++ b/addons/zeus/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\zeus \ No newline at end of file diff --git a/addons/zeus/CfgEventHandlers.hpp b/addons/zeus/CfgEventHandlers.hpp new file mode 100644 index 0000000000..f0a9f14d91 --- /dev/null +++ b/addons/zeus/CfgEventHandlers.hpp @@ -0,0 +1,6 @@ + +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_FILE(XEH_preInit)); + }; +}; diff --git a/addons/zeus/XEH_preInit.sqf b/addons/zeus/XEH_preInit.sqf new file mode 100644 index 0000000000..2574706239 --- /dev/null +++ b/addons/zeus/XEH_preInit.sqf @@ -0,0 +1,7 @@ +#include "script_component.hpp" + +ADDON = false; + +PREP(bi_moduleCurator); + +ADDON = true; diff --git a/addons/zeus/config.cpp b/addons/zeus/config.cpp new file mode 100644 index 0000000000..84d3077a96 --- /dev/null +++ b/addons/zeus/config.cpp @@ -0,0 +1,22 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_common"}; + author[] = {"SilentSpike"}; + authorUrl = "https://github.com/SilentSpike"; + VERSION_CONFIG; + }; +}; + +#include "CfgEventHandlers.hpp" + +class CfgVehicles { + class Module_F; + class ModuleCurator_F: Module_F { + function = QUOTE(FUNC(bi_moduleCurator)); + }; +}; \ No newline at end of file diff --git a/addons/zeus/functions/fnc_bi_moduleCurator.sqf b/addons/zeus/functions/fnc_bi_moduleCurator.sqf new file mode 100644 index 0000000000..80f9be5bc1 --- /dev/null +++ b/addons/zeus/functions/fnc_bi_moduleCurator.sqf @@ -0,0 +1,310 @@ +/* +* Author: Bohemia Interactive +* Module function for initalizing zeus +* Edited to remove eagle and global ascension message +* +* Arguments: +* 0: The logic object <OBJECT> +* +* Return Value: +* nil +* +* Public: No +*/ + +#include "script_component.hpp" + +_logic = _this select 0; +_units = _this select 1; +_activated = _this select 2; + +if (_activated) then { + + //--- Terminate when not created on the server + if (!isserver && local _logic && isnull (getassignedcuratorunit _logic)) exitwith { + [format ["%1 is trying to create curator logic ModuleCurator_F",profilename],"bis_fnc_error",false] call bis_fnc_mp; + deletevehicle _logic; + }; + + //--- Get curator owner + _ownerVar = _logic getvariable ["owner",""]; + _ownerUID = parsenumber _ownerVar; + if (cheatsenabled) then { + _ownerVarArray = toarray _ownerVar; + _ownerVarArray resize 3; + if (tostring _ownerVarArray == "DEV") then {_ownerUID = 1;}; + }; + if (_ownerVar == "" && !ismultiplayer) then { + ["Curator owner not defined, player used instead in singleplayer."] call bis_fnc_error; + _ownerVar = player call bis_fnc_objectvar; + }; + if (_ownerUID > 0 && !ismultiplayer) then { + _ownerVar = player call bis_fnc_objectvar; + }; + _isAdmin = _ownerVar == "#adminLogged" || _ownerVar == "#adminVoted"; + + //--- Wipe out the variable so clients can't access it + _logic setvariable ["owner",nil]; + + //--- Server + if (isserver) then { + + //--- Prepare admin variable + _adminVar = ""; + if (_isAdmin) then { + _letters = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]; + _adminVar = "admin_"; + for "_i" from 0 to 9 do {_adminVar = _adminVar + (_letters call bis_fnc_selectrandom);}; + _logic setvariable ["adminVar",_adminVar,true]; + }; + + //--- Get allowed addons + _addonsType = _logic getvariable ["Addons",0]; + _addons = []; + switch _addonsType do { + + //--- All (including unofficial ones) + case 3: { + _cfgPatches = configfile >> "cfgpatches"; + for "_i" from 0 to (count _cfgPatches - 1) do { + _class = _cfgPatches select _i; + if (isclass _class) then {_addons set [count _addons,configname _class];}; + }; + _addons call bis_fnc_activateaddons; + removeallcuratoraddons _logic; + _logic addcuratoraddons _addons; + }; + + //--- All active + case 2: {}; + + //--- All mission + case 1: { + _addonsList = []; + { + _addonsList = _addonsList + (unitaddons typeof _x); + } foreach (entities "all"); + removeallcuratoraddons _logic; + _logic addcuratoraddons _addonsList; + }; + + //--- None + case 0: { + removeallcuratoraddons _logic; + }; + }; + + //--- Handle ownership + [_logic,_ownerVar,_ownerUID,_adminVar] spawn { + scriptname "BIS_fnc_moduleCurator: Owner"; + + _logic = _this select 0; + _ownerVar = _this select 1; + _ownerUID = _this select 2; + _adminVar = _this select 3; + + if (_adminVar != "") then {_ownerVar = _adminVar;}; + + _forced = _logic getvariable ["forced",0] > 0; + _name = _logic getvariable ["name",""]; + if (_name == "") then {_name = localize "STR_A3_curator";}; + + //--- Wait until mission starts + waituntil {time > 0}; + + //--- Refresh addon list, so it's broadcasted to clients + _addons = curatoraddons _logic; + removeAllCuratorAddons _logic; + _logic addcuratoraddons _addons; + + while {true} do { + //--- Wait for player to become Zeus + switch true do { + case (_ownerUID > 0): { + waituntil { + sleep 0.01; + {getplayeruid _x == _ownerVar} count playableunits > 0 + }; + }; + default { + waituntil {isplayer (missionnamespace getvariable [_ownerVar,objnull])}; + }; + }; + + //--- Assign + _player = objnull; + switch true do { + case (_ownerUID > 0): { + { + if (getplayeruid _x == _ownerVar) exitwith {_player = _x;}; + } foreach playableunits; + }; + default { + _player = missionnamespace getvariable [_ownerVar,objnull]; + }; + }; + + waituntil {unassigncurator _logic; isnull (getassignedcuratorunit _logic)}; + waituntil {_player assignCurator _logic; getassignedcuratorunit _logic == _player}; + + //--- Add radio channels + { + _x radiochanneladd [_player]; + } foreach (_logic getvariable ["channels",[]]); + + [_logic,"curatorUnitAssigned",[_logic,_player]] call bis_fnc_callscriptedeventhandler; + + //--- Forced interface + //if (_forced) then { + // [[true,true],"bis_fnc_forceCuratorInterface",_player] call bis_fnc_mp; + //}; + + //--- Wait for player to stop being Zeus + switch true do { + case (_ownerUID > 0): { + waituntil { + sleep 0.01; + {getplayeruid _x == _ownerVar} count playableunits == 0 + }; + }; + default { + waituntil {_player != missionnamespace getvariable [_ownerVar,objnull]}; + }; + }; + + //--- Add radio channels + { + _x radiochannelremove [_player]; + } foreach (_logic getvariable ["channels",[]]); + + //--- Unassign + waituntil {unassigncurator _logic; isnull (getassignedcuratorunit _logic)}; + }; + }; + + //--- Activated all future addons + _addons = []; + { + if (typeof _x == "ModuleCuratorAddAddons_F") then { + _paramAddons = call compile ("[" + (_x getvariable ["addons",""]) + "]"); + { + if !(_x in _addons) then {_addons set [count _addons,_x];}; + { + if !(_x in _addons) then {_addons set [count _addons,_x];}; + } foreach (unitaddons _x); + } foreach _paramAddons; + }; + } foreach (synchronizedobjects _logic); + _addons call bis_fnc_activateaddons; + + //--- Locality changed + _logic addeventhandler [ + "local", + { + _logic = _this select 0; + _bird = _logic getvariable ["bird",objnull]; + _bird setowner owner _logic; + } + ]; + }; + + //--- Player + if (hasinterface) then { + waituntil {local player}; + _serverCommand = if (_ownerVar == "#adminLogged") then {"#shutdown"} else {"#kick"}; + + //--- Black effect until the interface is open + _forced = _logic getvariable ["forced",0] > 0; + if (_forced) then { + _isCurator = switch true do { + case (_ownerUID > 0): { + getplayeruid player == _ownerVar + }; + case (_isAdmin): { + isserver || servercommandavailable _serverCommand + }; + default { + player == missionnamespace getvariable [_ownerVar,objnull] + }; + }; + if (_isCurator) then { + [true,true] spawn bis_fnc_forceCuratorInterface; + ("RscDisplayCurator" call bis_fnc_rscLayer) cuttext ["","black in",1e10]; + }; + }; + + //--- Check if player is server admin + if (_isAdmin) then { + _adminVar = _logic getvariable ["adminVar",""]; + _logic setvariable ["adminVar",nil]; + if (isserver) then { + //--- Host + missionnamespace setvariable [_adminVar,player]; + } else { + //--- Client + [_logic,_adminVar,_serverCommand] spawn { + scriptname "BIS_fnc_moduleCurator: Admin check"; + + _logic = _this select 0; + _adminVar = _this select 1; + _serverCommand = _this select 2; + while {true} do { + waituntil {sleep 0.1; servercommandavailable _serverCommand}; + missionnamespace setvariable [_adminVar,player]; + publicvariable _adminVar; + _respawn = player addeventhandler ["respawn",format ["%1 = _this select 0; publicvariable '%1';",_adminVar]]; + + waituntil {sleep 0.1; !servercommandavailable _serverCommand}; + missionnamespace setvariable [_adminVar,objnull]; + publicvariable _adminVar; + player removeeventhandler ["respawn",_respawn]; + }; + }; + }; + }; + + [_logic] spawn { + _logic = _this select 0; + sleep 1; + waituntil {alive player}; + + //--- Show warning when Zeus key is not assigned + if (count (actionkeys "curatorInterface") == 0) then { + [ + format [ + localize "str_a3_cfgvehicles_modulecurator_f_keyNotAssigned", + (["IGUI","WARNING_RGB"] call bis_fnc_displaycolorget) call bis_fnc_colorRGBAtoHTML + ] + ] call bis_fnc_guiMessage; + }; + + //--- Show hint about pinging for players + if ( + isnil {profilenamespace getvariable "bis_fnc_curatorPinged_done"} + && + {isTutHintsEnabled} + && + {isnull getassignedcuratorlogic player} + && + {player in curatoreditableobjects _logic} + ) then { + sleep 0.5; + [["Curator","Ping"]] call bis_fnc_advHint; + }; + }; + + //--- Add local event handlers + _logic addeventhandler ["curatorFeedbackMessage",{_this call bis_fnc_showCuratorFeedbackMessage;}]; + _logic addeventhandler ["curatorPinged",{_this call bis_fnc_curatorPinged;}]; + _logic addeventhandler ["curatorObjectPlaced",{_this call bis_fnc_curatorObjectPlaced;}]; + _logic addeventhandler ["curatorObjectEdited",{_this call bis_fnc_curatorObjectEdited;}]; + _logic addeventhandler ["curatorWaypointPlaced",{_this call bis_fnc_curatorWaypointPlaced;}]; + + _logic addeventhandler ["curatorObjectDoubleClicked",{(_this select 1) call bis_fnc_showCuratorAttributes;}]; + _logic addeventhandler ["curatorGroupDoubleClicked",{(_this select 1) call bis_fnc_showCuratorAttributes;}]; + _logic addeventhandler ["curatorWaypointDoubleClicked",{(_this select 1) call bis_fnc_showCuratorAttributes;}]; + _logic addeventhandler ["curatorMarkerDoubleClicked",{(_this select 1) call bis_fnc_showCuratorAttributes;}]; + + player call bis_fnc_curatorRespawn; + }; +}; diff --git a/addons/zeus/functions/script_component.hpp b/addons/zeus/functions/script_component.hpp new file mode 100644 index 0000000000..35453cc4e8 --- /dev/null +++ b/addons/zeus/functions/script_component.hpp @@ -0,0 +1 @@ +#include "\z\ace\addons\zeus\script_component.hpp" \ No newline at end of file diff --git a/addons/zeus/script_component.hpp b/addons/zeus/script_component.hpp new file mode 100644 index 0000000000..d5a4ec1bcc --- /dev/null +++ b/addons/zeus/script_component.hpp @@ -0,0 +1,12 @@ +#define COMPONENT zeus +#include "\z\ace\addons\main\script_mod.hpp" + +#ifdef DEBUG_ENABLED_ZEUS + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_ZEUS + #define DEBUG_SETTINGS DEBUG_SETTINGS_ZEUS +#endif + +#include "\z\ace\addons\main\script_macros.hpp" \ No newline at end of file From 079b8489cea079d5ef409e2182473a3823a0133b Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Sat, 9 May 2015 20:30:49 +0100 Subject: [PATCH 06/51] Missing spaces :wink: --- .../zeus/functions/fnc_bi_moduleCurator.sqf | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/addons/zeus/functions/fnc_bi_moduleCurator.sqf b/addons/zeus/functions/fnc_bi_moduleCurator.sqf index 80f9be5bc1..86f9bc781a 100644 --- a/addons/zeus/functions/fnc_bi_moduleCurator.sqf +++ b/addons/zeus/functions/fnc_bi_moduleCurator.sqf @@ -1,16 +1,16 @@ /* -* Author: Bohemia Interactive -* Module function for initalizing zeus -* Edited to remove eagle and global ascension message -* -* Arguments: -* 0: The logic object <OBJECT> -* -* Return Value: -* nil -* -* Public: No -*/ + * Author: Bohemia Interactive + * Module function for initalizing zeus + * Edited to remove eagle and global ascension message + * + * Arguments: + * 0: The logic object <OBJECT> + * + * Return Value: + * nil + * + * Public: No + */ #include "script_component.hpp" From 3544ee57f8fe91116e7acb2ebfcae184b3805660 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Sat, 9 May 2015 20:35:07 +0100 Subject: [PATCH 07/51] Added removed script within comments --- .../zeus/functions/fnc_bi_moduleCurator.sqf | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/addons/zeus/functions/fnc_bi_moduleCurator.sqf b/addons/zeus/functions/fnc_bi_moduleCurator.sqf index 86f9bc781a..36110ac4fe 100644 --- a/addons/zeus/functions/fnc_bi_moduleCurator.sqf +++ b/addons/zeus/functions/fnc_bi_moduleCurator.sqf @@ -152,6 +152,15 @@ if (_activated) then { _x radiochanneladd [_player]; } foreach (_logic getvariable ["channels",[]]); + /* Removed by ACE + //--- Sent notification to all assigned players + { + if (isplayer _x) then { + [["CuratorAssign",[_name,name _player]],"bis_fnc_showNotification",_x] call bis_fnc_mp; + }; + } foreach (curatoreditableobjects _logic); + */ + [_logic,"curatorUnitAssigned",[_logic,_player]] call bis_fnc_callscriptedeventhandler; //--- Forced interface @@ -182,6 +191,15 @@ if (_activated) then { }; }; + /* Removed by ACE + //--- Create bird + _birdType = _logic getvariable ["birdType","eagle_f"]; + if (_birdType != "") then { + _bird = createvehicle [_birdType,[100,100,100],[],0,"none"]; + _logic setvariable ["bird",_bird,true]; + }; + */ + //--- Activated all future addons _addons = []; { @@ -307,4 +325,4 @@ if (_activated) then { player call bis_fnc_curatorRespawn; }; -}; +}; \ No newline at end of file From 633e94a1141766c8947ac1ae5103a6bbed744305 Mon Sep 17 00:00:00 2001 From: jonpas <jonpas33@gmail.com> Date: Sat, 9 May 2015 22:14:00 +0200 Subject: [PATCH 08/51] CBA Macros to Interaction functions --- .../functions/fnc_addPassengerActions.sqf | 4 ++-- .../functions/fnc_addSelectableItem.sqf | 8 ++------ .../interaction/functions/fnc_canJoinGroup.sqf | 5 +---- addons/interaction/functions/fnc_canJoinTeam.sqf | 5 +---- .../interaction/functions/fnc_canTapShoulder.sqf | 5 +---- addons/interaction/functions/fnc_getDoor.sqf | 5 +++-- .../functions/fnc_getDoorAnimations.sqf | 5 ++--- addons/interaction/functions/fnc_getDown.sqf | 6 +++--- .../interaction/functions/fnc_getWeaponPos.sqf | 2 +- addons/interaction/functions/fnc_isInRange.sqf | 5 ++--- addons/interaction/functions/fnc_joinTeam.sqf | 5 ++--- .../functions/fnc_moduleInteraction.sqf | 2 ++ addons/interaction/functions/fnc_moveDown.sqf | 2 ++ addons/interaction/functions/fnc_onButtonUp.sqf | 4 +--- addons/interaction/functions/fnc_onClick.sqf | 3 +-- addons/interaction/functions/fnc_openDoor.sqf | 8 +++----- .../functions/fnc_openMenuSelectUI.sqf | 16 +++++++--------- .../interaction/functions/fnc_openSelectMenu.sqf | 9 ++++++--- .../functions/fnc_prepareSelectMenu.sqf | 7 ++++--- addons/interaction/functions/fnc_push.sqf | 3 +-- addons/interaction/functions/fnc_removeTag.sqf | 2 ++ addons/interaction/functions/fnc_sendAway.sqf | 4 ++-- .../interaction/functions/fnc_showMouseHint.sqf | 12 ++++++------ addons/interaction/functions/fnc_tapShoulder.sqf | 2 +- .../functions/fnc_updateTooltipPosition.sqf | 8 +++++--- 25 files changed, 63 insertions(+), 74 deletions(-) diff --git a/addons/interaction/functions/fnc_addPassengerActions.sqf b/addons/interaction/functions/fnc_addPassengerActions.sqf index 4474378bcc..914edeed28 100644 --- a/addons/interaction/functions/fnc_addPassengerActions.sqf +++ b/addons/interaction/functions/fnc_addPassengerActions.sqf @@ -18,9 +18,9 @@ #include "script_component.hpp" EXPLODE_3_PVT(_this,_vehicle,_player,_parameters); +EXPLODE_1_PVT(_parameters,_unit); -private ["_unit","_actions"]; -_unit = _parameters select 0; +private ["_varName", "_actionTrees", "_actions"]; _varName = format [QEGVAR(interact_menu,Act_%1), typeOf _unit]; _actionTrees = missionNamespace getVariable [_varName, []]; diff --git a/addons/interaction/functions/fnc_addSelectableItem.sqf b/addons/interaction/functions/fnc_addSelectableItem.sqf index 6f1339d25a..4875ba2c97 100644 --- a/addons/interaction/functions/fnc_addSelectableItem.sqf +++ b/addons/interaction/functions/fnc_addSelectableItem.sqf @@ -18,17 +18,13 @@ */ #include "script_component.hpp" -private ["_container", "_displayName", "_picture", "_data", "_index"]; - -_container = _this select 0; -_displayName = _this select 1; -_picture = _this select 2; -_data = _this select 3; +PARAMS_4(_container,_displayName,_picture,_data); if (_picture == "" || _picture == "PictureThing") then { _picture = QUOTE(PATHTOF(UI\dot_ca.paa)); }; +private ["_index"]; _index = lbAdd [_container, _displayName]; lbSetData [_container, _index, str _data]; lbSetPicture [_container, _index, _picture]; diff --git a/addons/interaction/functions/fnc_canJoinGroup.sqf b/addons/interaction/functions/fnc_canJoinGroup.sqf index 26597ca0a0..33b4623c4c 100644 --- a/addons/interaction/functions/fnc_canJoinGroup.sqf +++ b/addons/interaction/functions/fnc_canJoinGroup.sqf @@ -16,10 +16,7 @@ */ #include "script_component.hpp" -private ["_unit", "_target"]; - -_unit = _this select 0; -_target = _this select 1; +PARAMS_2(_unit,_target); alive _target && {!(_target getVariable ["ACE_isUnconscious", false])} diff --git a/addons/interaction/functions/fnc_canJoinTeam.sqf b/addons/interaction/functions/fnc_canJoinTeam.sqf index 4312981978..ba894c7a13 100644 --- a/addons/interaction/functions/fnc_canJoinTeam.sqf +++ b/addons/interaction/functions/fnc_canJoinTeam.sqf @@ -16,10 +16,7 @@ */ #include "script_component.hpp" -private ["_unit", "_target"]; - -_unit = _this select 0; -_target = _this select 1; +PARAMS_2(_unit,_target); alive _target && {!(_target getVariable ["ACE_isUnconscious", false])} diff --git a/addons/interaction/functions/fnc_canTapShoulder.sqf b/addons/interaction/functions/fnc_canTapShoulder.sqf index 2be9bf70a9..1b48d3280d 100644 --- a/addons/interaction/functions/fnc_canTapShoulder.sqf +++ b/addons/interaction/functions/fnc_canTapShoulder.sqf @@ -16,10 +16,7 @@ */ #include "script_component.hpp" -private ["_unit", "_target"]; - -_unit = _this select 0; -_target = _this select 1; +PARAMS_2(_unit,_target); _target isKindOf "CAManBase" && {alive _target} && diff --git a/addons/interaction/functions/fnc_getDoor.sqf b/addons/interaction/functions/fnc_getDoor.sqf index 460a325954..fdf1447828 100644 --- a/addons/interaction/functions/fnc_getDoor.sqf +++ b/addons/interaction/functions/fnc_getDoor.sqf @@ -17,9 +17,9 @@ */ #include "script_component.hpp" -private ["_distance", "_position0", "_position1", "_intersections", "_count", "_house", "_door", "_index", "_id"]; +PARAMS_1(_distance); -_distance = _this select 0; +private ["_position0", "_position1", "_intersections", "_count", "_house", "_door"]; _position0 = positionCameraToWorld [0, 0, 0]; _position1 = positionCameraToWorld [0, 0, _distance]; @@ -38,4 +38,5 @@ _intersections = [_house, "GEOM"] intersect [_position0, _position1]; _door = _intersections select 0 select 0; if (isNil "_door") exitWith {[_house, ""]}; + [_house, _door] diff --git a/addons/interaction/functions/fnc_getDoorAnimations.sqf b/addons/interaction/functions/fnc_getDoorAnimations.sqf index cb0b7122b0..6f85ef644b 100644 --- a/addons/interaction/functions/fnc_getDoorAnimations.sqf +++ b/addons/interaction/functions/fnc_getDoorAnimations.sqf @@ -18,10 +18,9 @@ */ #include "script_component.hpp" -private ["_house", "_door", "_animations", "_lockedVariable"]; +PARAMS_2(_house,_door); -_house = _this select 0; -_door = _this select 1; +private ["_index", "_animations", "_lockedVariable"]; _index = [ "door_1", diff --git a/addons/interaction/functions/fnc_getDown.sqf b/addons/interaction/functions/fnc_getDown.sqf index 9e7daecb46..09d651eadf 100644 --- a/addons/interaction/functions/fnc_getDown.sqf +++ b/addons/interaction/functions/fnc_getDown.sqf @@ -17,9 +17,9 @@ #define RADIUS 10 -private ["_unit", "_chance", "_x"]; +PARAMS_1(_unit); -_unit = _this select 0; +private ["_chance", "_x"]; ACE_player playActionNow "GestureGo"; // put something else here. @@ -35,4 +35,4 @@ if (count (weapons ACE_player) > 0) then { _this setUnitPos "DOWN"; }, _x] call CBA_fnc_globalExecute; }; -} foreach (_unit nearEntities ["Civilian", RADIUS]); +} forEach (_unit nearEntities ["Civilian", RADIUS]); diff --git a/addons/interaction/functions/fnc_getWeaponPos.sqf b/addons/interaction/functions/fnc_getWeaponPos.sqf index 35ea202b1d..1e3c8b32ec 100644 --- a/addons/interaction/functions/fnc_getWeaponPos.sqf +++ b/addons/interaction/functions/fnc_getWeaponPos.sqf @@ -16,7 +16,7 @@ #include "script_component.hpp" // IGNORE_PRIVATE_WARNING(_target); -private ["_weaponDir","_refSystem"]; +private ["_weaponDir", "_refSystem"]; _weaponDir = _target weaponDirection currentWeapon _target; _refSystem = _weaponDir call EFUNC(common,createOrthonormalReference); diff --git a/addons/interaction/functions/fnc_isInRange.sqf b/addons/interaction/functions/fnc_isInRange.sqf index 05677d7060..490ddf05e5 100644 --- a/addons/interaction/functions/fnc_isInRange.sqf +++ b/addons/interaction/functions/fnc_isInRange.sqf @@ -16,10 +16,9 @@ */ #include "script_component.hpp" -private ["_vehicle", "_distance", "_player"]; +PARAMS_2(_vehicle,_distance); -_vehicle = _this select 0; -_distance = _this select 1; +private ["_player", "_position0", "_position1"]; _player = ACE_player; diff --git a/addons/interaction/functions/fnc_joinTeam.sqf b/addons/interaction/functions/fnc_joinTeam.sqf index cf6889d90a..cd2ea8c880 100644 --- a/addons/interaction/functions/fnc_joinTeam.sqf +++ b/addons/interaction/functions/fnc_joinTeam.sqf @@ -16,10 +16,9 @@ */ #include "script_component.hpp" -private ["_unit", "_team", "_message"]; +PARAMS_2(_unit,_team); -_unit = _this select 0; -_team = _this select 1; +private ["_message"]; _unit setVariable [QGVAR(assignedFireTeam), _team, true]; [_unit, format ["{_this assignTeam '%1'}", _team]] call EFUNC(common,execRemoteFnc); diff --git a/addons/interaction/functions/fnc_moduleInteraction.sqf b/addons/interaction/functions/fnc_moduleInteraction.sqf index 925847c028..bd02093aa0 100644 --- a/addons/interaction/functions/fnc_moduleInteraction.sqf +++ b/addons/interaction/functions/fnc_moduleInteraction.sqf @@ -17,6 +17,8 @@ */ #include "script_component.hpp" +private ["_logic", "_activated"]; + _logic = _this select 0; _activated = _this select 2; diff --git a/addons/interaction/functions/fnc_moveDown.sqf b/addons/interaction/functions/fnc_moveDown.sqf index eb946a5f10..f2e675b256 100644 --- a/addons/interaction/functions/fnc_moveDown.sqf +++ b/addons/interaction/functions/fnc_moveDown.sqf @@ -15,6 +15,8 @@ */ #include "script_component.hpp" +private ["_count", "_player", "_vehicle", "_dlgInteractionDialog", "_top", "_i", "", "_ctrl", "_index", "_action", "_color", "_current", "_infoText"]; + #define CLAMP(x,low,high) (if(x > high)then{high}else{if(x < low)then{low}else{x}}) if (isNil QGVAR(MainButton)) exitWith{}; if (isNil QGVAR(Buttons)) exitWith{}; diff --git a/addons/interaction/functions/fnc_onButtonUp.sqf b/addons/interaction/functions/fnc_onButtonUp.sqf index 151ce67c98..da1b55b613 100644 --- a/addons/interaction/functions/fnc_onButtonUp.sqf +++ b/addons/interaction/functions/fnc_onButtonUp.sqf @@ -15,7 +15,7 @@ */ #include "script_component.hpp" -private ["_player", "_vehicle", "_target", "_count", "_index", "_action", "_statement", "_condition", "_conditionShow", "_exceptions", "_distance"]; +private ["_player", "_vehicle", "_target", "_count", "_index", "_action", "_statement", "_condition", "_conditionShow", "_distance"]; _player = ACE_player; _vehicle = vehicle _player; @@ -34,11 +34,9 @@ _action = if (_index != -1 && {_index < _count}) then { closeDialog 0; - _statement = _action select 1; _condition = _action select 2; _conditionShow = _action select 7; -_exceptions = _action select 8;// _distance = _action select 9; if ((_distance == 0 || {[GVAR(Target), _distance] call FUNC(isInRange)}) && {[_target, _player] call _condition} && {[_target, _player] call _conditionShow}) then { diff --git a/addons/interaction/functions/fnc_onClick.sqf b/addons/interaction/functions/fnc_onClick.sqf index 6f9882281f..a240823710 100644 --- a/addons/interaction/functions/fnc_onClick.sqf +++ b/addons/interaction/functions/fnc_onClick.sqf @@ -14,7 +14,7 @@ * Public: No */ #include "script_component.hpp" -private ["_player", "_vehicle", "_target", "_count", "_index", "_action", "_subMenu", "_statement", "_condition", "_conditionShow", "_exceptions", "_distance"]; +private ["_player", "_vehicle", "_target", "_count", "_index", "_action", "_subMenu", "_statement", "_condition", "_conditionShow", "_distance"]; _player = ACE_player; _vehicle = vehicle _player; @@ -43,7 +43,6 @@ if (count _subMenu < 2) then { _statement = _action select 1; _condition = _action select 2; _conditionShow = _action select 7; - _exceptions = _action select 8;// _distance = _action select 9; if ((_distance == 0 || {[GVAR(Target), _distance] call FUNC(isInRange)}) && {[_target, _player] call _condition} && {[_target, _player] call _conditionShow}) then { diff --git a/addons/interaction/functions/fnc_openDoor.sqf b/addons/interaction/functions/fnc_openDoor.sqf index 3e776f3538..6b34c49ca9 100644 --- a/addons/interaction/functions/fnc_openDoor.sqf +++ b/addons/interaction/functions/fnc_openDoor.sqf @@ -16,19 +16,17 @@ */ #include "script_component.hpp" -private ["_info", "_house", "_door", "_animations", "_lockedVariable"]; +private ["_info", "_animations", "_phase", "_position", "_time", "_usedMouseWheel"]; _info = [2] call FUNC(getDoor); -_house = _info select 0; -_door = _info select 1; +EXPLODE_2_PVT(_info,_house,_door); if (isNull _house) exitWith {}; _animations = [_house, _door] call FUNC(getDoorAnimations); -_lockedVariable = _animations select 1; -_animations = _animations select 0; +EXPLODE_2_PVT(_animations,_animations,_lockedVariable); if (count _animations == 0) exitWith {}; diff --git a/addons/interaction/functions/fnc_openMenuSelectUI.sqf b/addons/interaction/functions/fnc_openMenuSelectUI.sqf index e755869ed1..e1b6a30df1 100644 --- a/addons/interaction/functions/fnc_openMenuSelectUI.sqf +++ b/addons/interaction/functions/fnc_openMenuSelectUI.sqf @@ -16,24 +16,22 @@ */ #include "script_component.hpp" -private ["_unit", "_vehicle", "_cargo"]; +PARAMS_2(_unit,_vehicle); -_unit = _this select 0; -_vehicle = _this select 1; +private ["_cargo", "_actions"]; -// allow interaction with all cargo slots and all ffv slots +// Allow interaction with all cargo slots and all FFV slots _cargo = [_vehicle, ["cargo", "ffv"], true] call EFUNC(common,getVehicleCrew); -// you can only interact if you are in cargo or ffv yourself. exit otherwise +// You can only interact if you are in cargo or FFV yourself. exit otherwise if !(_unit in _cargo) exitWith {}; GVAR(InteractionMenu_Crew) = _cargo; -// prepare: add header and "OK" button to select menu -private "_actions"; +// Prepare: add header and "OK" button to select menu _actions = [localize "STR_ACE_Interaction_InteractionMenu", localize "STR_ACE_Interaction_Interact"] call FUNC(prepareSelectMenu); -// prepare: add all cargo units as options to select menu +// Prepare: add all cargo units as options to select menu { if (_x != _unit) then { _actions = [ @@ -45,7 +43,7 @@ _actions = [localize "STR_ACE_Interaction_InteractionMenu", localize "STR_ACE_In }; } forEach _cargo; -// open select menu +// Open select menu [ _actions, { diff --git a/addons/interaction/functions/fnc_openSelectMenu.sqf b/addons/interaction/functions/fnc_openSelectMenu.sqf index 13e02fb044..a12ceefa6c 100644 --- a/addons/interaction/functions/fnc_openSelectMenu.sqf +++ b/addons/interaction/functions/fnc_openSelectMenu.sqf @@ -27,11 +27,14 @@ if (!(profileNamespace getVariable [QGVAR(FlowMenu), false])) then { GVAR(SelectAccept) = _this select 1; GVAR(SelectCancel) = _this select 2; - buttonSetAction [8855, QUOTE( call GVAR(SelectCancel); )]; // cancel - buttonSetAction [8860, QUOTE( (call compile (lbData [ARR_2(8866, lbCurSel 8866)])) call GVAR(SelectAccept); )]; // accept + buttonSetAction [8855, QUOTE( call GVAR(SelectCancel); )]; // Cancel + buttonSetAction [8860, QUOTE( (call compile (lbData [ARR_2(8866, lbCurSel 8866)])) call GVAR(SelectAccept); )]; // Accept lbSetCurSel [8866, 0]; }else{ - _customActions = _this select 0; + PARAMS_1(_customActions); + + private ["_count", "_action"]; + _count = count _customActions; if (_count == 0) exitWith {}; _customActions call FUNC(sortOptionsByPriority); diff --git a/addons/interaction/functions/fnc_prepareSelectMenu.sqf b/addons/interaction/functions/fnc_prepareSelectMenu.sqf index f43ec75c4e..05b1bc8e35 100644 --- a/addons/interaction/functions/fnc_prepareSelectMenu.sqf +++ b/addons/interaction/functions/fnc_prepareSelectMenu.sqf @@ -16,13 +16,14 @@ */ #include "script_component.hpp" -private ["_buttonAction", "_header", "_buttonText", "_cancelButton"]; +PARAMS_2(_header,_buttonText); + closeDialog 0; -_header = _this select 0; -_buttonText = _this select 1; + if (isNil "_buttonText" or {_buttonText == ""}) then { _buttonText = localize "STR_ACE_Interaction_MakeSelection"; }; + createDialog "RscACE_SelectAnItem"; ctrlSetText [8860, _buttonText]; ctrlSetText [8870, _header]; diff --git a/addons/interaction/functions/fnc_push.sqf b/addons/interaction/functions/fnc_push.sqf index 580f687f64..946a5118be 100644 --- a/addons/interaction/functions/fnc_push.sqf +++ b/addons/interaction/functions/fnc_push.sqf @@ -17,8 +17,7 @@ #include "script_component.hpp" -_boat = _this select 0; -_velocity = _this select 1; +PARAMS_2(_boat,_velocity); if !(local _boat) exitWith { [_this, QUOTE(FUNC(push)), _boat] call EFUNC(common,execRemoteFnc); diff --git a/addons/interaction/functions/fnc_removeTag.sqf b/addons/interaction/functions/fnc_removeTag.sqf index d1a16bf88b..b017c203b2 100644 --- a/addons/interaction/functions/fnc_removeTag.sqf +++ b/addons/interaction/functions/fnc_removeTag.sqf @@ -16,6 +16,8 @@ #include "script_component.hpp" 0 spawn { + private ["_index"]; + waitUntil {player getVariable ["ACE_Name", ""] != ""}; _name = player getVariable ["ACE_Name", ""]; diff --git a/addons/interaction/functions/fnc_sendAway.sqf b/addons/interaction/functions/fnc_sendAway.sqf index 1a48725644..0dd106de08 100644 --- a/addons/interaction/functions/fnc_sendAway.sqf +++ b/addons/interaction/functions/fnc_sendAway.sqf @@ -18,9 +18,9 @@ #define DISTANCE 50 #define RADIUS 10 -private ["_unit", "_chance", "_x"]; +PARAMS_1(_unit); -_unit = _this select 0; +private ["_chance", "_x"]; ACE_player playActionNow "GestureGo"; diff --git a/addons/interaction/functions/fnc_showMouseHint.sqf b/addons/interaction/functions/fnc_showMouseHint.sqf index a64114d009..e3a9b45f94 100644 --- a/addons/interaction/functions/fnc_showMouseHint.sqf +++ b/addons/interaction/functions/fnc_showMouseHint.sqf @@ -19,9 +19,10 @@ #define GUI_GRID_W (0.025) #define GUI_GRID_H (0.04) -private ["_leftClick", "_rightClick", "_scroll"]; -_leftClick = _this select 0; -_rightClick = _this select 1; + +private ["_scroll", "_display"]; + +PARAMS_2(_leftClick,_rightClick); _scroll = ""; if (count _this > 2) then { _scroll = _this select 2; @@ -43,9 +44,8 @@ if (isNull _display) exitWith{}; if (_scroll == "") exitWith { (_display displayCtrl 1002) ctrlShow false; (_display displayCtrl 1202) ctrlShow false; - - (_display displayCtrl 1001) ctrlSetPosition [21 * GUI_GRID_W, 18 * GUI_GRID_H, 8 * GUI_GRID_W, 1.5 * GUI_GRID_H]; - (_display displayCtrl 1201) ctrlSetPosition [20 * GUI_GRID_W, 18.5 * GUI_GRID_H, 1 * GUI_GRID_W, 1 * GUI_GRID_H]; + (_display displayCtrl 1001) ctrlSetPosition [21 * GUI_GRID_W, 18 * GUI_GRID_H, 8 * GUI_GRID_W, 1.5 * GUI_GRID_H]; + (_display displayCtrl 1201) ctrlSetPosition [20 * GUI_GRID_W, 18.5 * GUI_GRID_H, 1 * GUI_GRID_W, 1 * GUI_GRID_H]; (_display displayCtrl 1001) ctrlCommit 0; (_display displayCtrl 1201) ctrlCommit 0; }; diff --git a/addons/interaction/functions/fnc_tapShoulder.sqf b/addons/interaction/functions/fnc_tapShoulder.sqf index f18c9c2c30..510fa4497f 100644 --- a/addons/interaction/functions/fnc_tapShoulder.sqf +++ b/addons/interaction/functions/fnc_tapShoulder.sqf @@ -28,7 +28,7 @@ if (_target != ACE_player) exitWith { addCamShake [4, 0.5, 5]; -private "_message"; +private ["_message"]; //localize is converting the escaped <> symbols, so just add them here instead of in the stringtable if (_shoulderNum == 0) then { _message = format ["%1 >", (localize "STR_ACE_Interaction_YouWereTappedRight")]; diff --git a/addons/interaction/functions/fnc_updateTooltipPosition.sqf b/addons/interaction/functions/fnc_updateTooltipPosition.sqf index c194102b41..27eb36e976 100644 --- a/addons/interaction/functions/fnc_updateTooltipPosition.sqf +++ b/addons/interaction/functions/fnc_updateTooltipPosition.sqf @@ -17,12 +17,14 @@ */ #include "script_component.hpp" +PARAMS_3(_tooltip,_coordinateX,_coordinateY); + disableSerialization; -_ctrl = ctrlParent (_this select 0) displayCtrl 40; +_ctrl = ctrlParent _tooltip displayCtrl 40; _ctrl ctrlSetPosition [ - (_this select 1) + 0.01 * safezoneW, - (_this select 2) + 0.01 * safezoneH, + _coordinateX + 0.01 * safezoneW, + _coordinateY + 0.01 * safezoneH, 2.0 / 16 * safezoneW, 0.3 / 9 * safezoneH ]; From 1a2e7d0596e0fb2bf7746839882d52aa6f10ed3a Mon Sep 17 00:00:00 2001 From: jonpas <jonpas33@gmail.com> Date: Sat, 9 May 2015 22:25:48 +0200 Subject: [PATCH 09/51] Tabs to Spaces, Removed unused GUI class --- addons/interaction/CfgVehicles.hpp | 1084 ++++++++++++++-------------- addons/interaction/Menu_Config.hpp | 324 +++++---- addons/interaction/README.md | 1 - addons/interaction/config.cpp | 30 +- 4 files changed, 716 insertions(+), 723 deletions(-) diff --git a/addons/interaction/CfgVehicles.hpp b/addons/interaction/CfgVehicles.hpp index 5548311718..5afaf21c28 100644 --- a/addons/interaction/CfgVehicles.hpp +++ b/addons/interaction/CfgVehicles.hpp @@ -1,566 +1,564 @@ class CfgVehicles { - - class Module_F; - class ACE_ModuleInteraction: Module_F { - author = "$STR_ACE_Common_ACETeam"; - category = "ACE"; - displayName = "Interaction System"; - function = "ACE_Interaction_fnc_moduleInteraction"; - scope = 2; - isGlobal = 1; - icon = PATHTOF(UI\Icon_Module_Interaction_ca.paa); - class Arguments { - class EnableTeamManagement { - displayName = "Enable Team Management"; - description = "Should players be allowed to use the Team Management Menu? Default: Yes"; - typeName = "BOOL"; - class values { - class Yes { default = 1; name = "Yes"; value = 1;}; - class No { name = "No"; value = 0; }; + class Module_F; + class ACE_ModuleInteraction: Module_F { + author = "$STR_ACE_Common_ACETeam"; + category = "ACE"; + displayName = "Interaction System"; + function = "ACE_Interaction_fnc_moduleInteraction"; + scope = 2; + isGlobal = 1; + icon = PATHTOF(UI\Icon_Module_Interaction_ca.paa); + class Arguments { + class EnableTeamManagement { + displayName = "Enable Team Management"; + description = "Should players be allowed to use the Team Management Menu? Default: Yes"; + typeName = "BOOL"; + class values { + class Yes { default = 1; name = "Yes"; value = 1;}; + class No { name = "No"; value = 0; }; + }; + }; }; - }; - }; - }; - - class Man; - class CAManBase: Man { - class ACE_Actions { - class ACE_MainActions { - displayName = "$STR_ACE_Interaction_MainAction"; - distance = 4; - condition = QUOTE(true); - statement = ""; - icon = "\a3\ui_f\data\IGUI\Cfg\Actions\eject_ca.paa"; - selection = "pelvis"; - - class ACE_TeamManagement { - displayName = "$STR_ACE_Interaction_TeamManagement"; - condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam) && {GVAR(EnableTeamManagement)}); - statement = ""; - showDisabled = 0; - priority = 3.2; - icon = PATHTOF(UI\team\team_management_ca.paa); - hotkey = "M"; - - class ACE_AssignTeamRed { - displayName = "$STR_ACE_Interaction_AssignTeamRed"; - condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam)); - statement = QUOTE([ARR_2(_target,'RED')] call DFUNC(joinTeam)); - showDisabled = 1; - icon = PATHTOF(UI\team\team_red_ca.paa); - priority = 2.4; - hotkey = "R"; - }; - class ACE_AssignTeamGreen { - displayName = "$STR_ACE_Interaction_AssignTeamGreen"; - condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam)); - statement = QUOTE([ARR_2(_target,'GREEN')] call DFUNC(joinTeam)); - showDisabled = 1; - icon = PATHTOF(UI\team\team_green_ca.paa); - priority = 2.3; - hotkey = "G"; - }; - class ACE_AssignTeamBlue { - displayName = "$STR_ACE_Interaction_AssignTeamBlue"; - condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam)); - statement = QUOTE([ARR_2(_target,'BLUE')] call DFUNC(joinTeam)); - showDisabled = 1; - icon = PATHTOF(UI\team\team_blue_ca.paa); - priority = 2.2; - hotkey = "B"; - }; - class ACE_AssignTeamYellow { - displayName = "$STR_ACE_Interaction_AssignTeamYellow"; - condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam)); - statement = QUOTE([ARR_2(_target,'YELLOW')] call DFUNC(joinTeam)); - showDisabled = 1; - icon = PATHTOF(UI\team\team_yellow_ca.paa); - priority = 2.1; - hotkey = "Y"; - }; - - class ACE_UnassignTeam { - displayName = "$STR_ACE_Interaction_LeaveTeam"; - condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam) && {assignedTeam _target != 'MAIN'}); - statement = QUOTE([ARR_2(_target,'MAIN')] call DFUNC(joinTeam)); - showDisabled = 1; - icon = PATHTOF(UI\team\team_white_ca.paa); - priority = 2.5; - hotkey = "N"; - }; - }; - - class ACE_JoinGroup { - displayName = "$STR_ACE_Interaction_JoinGroup"; - condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinGroup)); - statement = QUOTE([_player] joinSilent group _target); - showDisabled = 0; - priority = 2.6; - icon = PATHTOF(UI\team\team_management_ca.paa); - hotkey = "J"; - }; - - class ACE_GetDown { - displayName = "$STR_ACE_Interaction_GetDown"; - condition = QUOTE([_target] call DFUNC(canInteractWithCivilian)); - statement = QUOTE([_target] call DFUNC(getDown)); - showDisabled = 0; - priority = 2.2; - }; - class ACE_SendAway { - displayName = "$STR_ACE_Interaction_SendAway"; - condition = QUOTE([_target] call DFUNC(canInteractWithCivilian)); - statement = QUOTE([_target] call DFUNC(sendAway)); - showDisabled = 0; - priority = 2.0; - }; - class ACE_Pardon { - displayName = "$STR_ACE_Interaction_Pardon"; - condition = QUOTE(rating _target < -2000 && {alive _target} && {side group _player == side group _target}); - statement = QUOTE([ARR_3(_target,'{_this addRating -rating _this}',_target)] call DEFUNC(common,execRemoteFnc)); - showDisabled = 0; - priority = 2.5; - }; - }; - class ACE_Torso { - displayName = "$STR_ACE_Interaction_Torso"; - selection = "spine3"; - distance = 1.50; - condition = ""; - statement = ""; - }; - class ACE_Head { - displayName = "$STR_ACE_Interaction_Head"; - selection = "pilot"; - distance = 1.50; - condition = ""; - statement = ""; - }; - class ACE_ArmLeft { - displayName = "$STR_ACE_Interaction_ArmLeft"; - selection = "LeftForeArm"; - distance = 1.50; - condition = ""; - statement = ""; - }; - class ACE_ArmRight { - displayName = "$STR_ACE_Interaction_ArmRight"; - selection = "RightForeArm"; - distance = 1.50; - condition = ""; - statement = ""; - }; - class ACE_LegLeft { - displayName = "$STR_ACE_Interaction_LegLeft"; - selection = "LKnee"; - distance = 1.50; - condition = ""; - statement = ""; - }; - class ACE_LegRight { - displayName = "$STR_ACE_Interaction_LegRight"; - selection = "RKnee"; - distance = 1.50; - condition = ""; - statement = ""; - }; - class ACE_Weapon { - displayName = "$STR_ACE_Interaction_Weapon"; - position = QUOTE(call FUNC(getWeaponPos)); - distance = 1.50; - condition = ""; - statement = ""; - }; - - class ACE_TapShoulderRight { - displayName = "$STR_ACE_Interaction_TapShoulder"; - selection = "rightshoulder"; - distance = 2.0; - condition = QUOTE([ARR_2(_player, _target)] call DFUNC(canTapShoulder)); - statement = QUOTE([ARR_3(_player, _target, 0)] call DFUNC(tapShoulder)); - }; - class ACE_TapShoulderLeft { - displayName = "$STR_ACE_Interaction_TapShoulder"; - selection = "leftshoulder"; - distance = 2.0; - condition = QUOTE([ARR_2(_player, _target)] call DFUNC(canTapShoulder)); - statement = QUOTE([ARR_3(_player, _target, 1)] call DFUNC(tapShoulder)); - }; }; - class ACE_SelfActions { - class ACE_TeamManagement { - displayName = "$STR_ACE_Interaction_TeamManagement"; - condition = QUOTE(GVAR(EnableTeamManagement)); - exceptions[] = {"isNotInside"}; - statement = ""; - showDisabled = 1; - priority = 3.2; - icon = PATHTOF(UI\team\team_management_ca.paa); - hotkey = "M"; + class Man; + class CAManBase: Man { + class ACE_Actions { + class ACE_MainActions { + displayName = "$STR_ACE_Interaction_MainAction"; + distance = 4; + condition = QUOTE(true); + statement = ""; + icon = "\a3\ui_f\data\IGUI\Cfg\Actions\eject_ca.paa"; + selection = "pelvis"; - class ACE_JoinTeamRed { - displayName = "$STR_ACE_Interaction_JoinTeamRed"; - condition = QUOTE(true); - exceptions[] = {"isNotInside"}; - statement = QUOTE([ARR_2(_player,'RED')] call DFUNC(joinTeam)); - showDisabled = 1; - priority = 2.4; - icon = PATHTOF(UI\team\team_red_ca.paa); - hotkey = "R"; - }; - class ACE_JoinTeamGreen { - displayName = "$STR_ACE_Interaction_JoinTeamGreen"; - condition = QUOTE(true); - exceptions[] = {"isNotInside"}; - statement = QUOTE([ARR_2(_player,'GREEN')] call DFUNC(joinTeam)); - showDisabled = 1; - priority = 2.3; - icon = PATHTOF(UI\team\team_green_ca.paa); - hotkey = "G"; - }; - class ACE_JoinTeamBlue { - displayName = "$STR_ACE_Interaction_JoinTeamBlue"; - condition = QUOTE(true); - exceptions[] = {"isNotInside"}; - statement = QUOTE([ARR_2(_player,'BLUE')] call DFUNC(joinTeam)); - showDisabled = 1; - priority = 2.2; - icon = PATHTOF(UI\team\team_blue_ca.paa); - hotkey = "B"; - }; - class ACE_JoinTeamYellow { - displayName = "$STR_ACE_Interaction_JoinTeamYellow"; - condition = QUOTE(true); - exceptions[] = {"isNotInside"}; - statement = QUOTE([ARR_2(_player,'YELLOW')] call DFUNC(joinTeam)); - showDisabled = 1; - priority = 2.1; - icon = PATHTOF(UI\team\team_yellow_ca.paa); - hotkey = "Y"; + class ACE_TeamManagement { + displayName = "$STR_ACE_Interaction_TeamManagement"; + condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam) && {GVAR(EnableTeamManagement)}); + statement = ""; + showDisabled = 0; + priority = 3.2; + icon = PATHTOF(UI\team\team_management_ca.paa); + hotkey = "M"; + + class ACE_AssignTeamRed { + displayName = "$STR_ACE_Interaction_AssignTeamRed"; + condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam)); + statement = QUOTE([ARR_2(_target,'RED')] call DFUNC(joinTeam)); + showDisabled = 1; + icon = PATHTOF(UI\team\team_red_ca.paa); + priority = 2.4; + hotkey = "R"; + }; + class ACE_AssignTeamGreen { + displayName = "$STR_ACE_Interaction_AssignTeamGreen"; + condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam)); + statement = QUOTE([ARR_2(_target,'GREEN')] call DFUNC(joinTeam)); + showDisabled = 1; + icon = PATHTOF(UI\team\team_green_ca.paa); + priority = 2.3; + hotkey = "G"; + }; + class ACE_AssignTeamBlue { + displayName = "$STR_ACE_Interaction_AssignTeamBlue"; + condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam)); + statement = QUOTE([ARR_2(_target,'BLUE')] call DFUNC(joinTeam)); + showDisabled = 1; + icon = PATHTOF(UI\team\team_blue_ca.paa); + priority = 2.2; + hotkey = "B"; + }; + class ACE_AssignTeamYellow { + displayName = "$STR_ACE_Interaction_AssignTeamYellow"; + condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam)); + statement = QUOTE([ARR_2(_target,'YELLOW')] call DFUNC(joinTeam)); + showDisabled = 1; + icon = PATHTOF(UI\team\team_yellow_ca.paa); + priority = 2.1; + hotkey = "Y"; + }; + + class ACE_UnassignTeam { + displayName = "$STR_ACE_Interaction_LeaveTeam"; + condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinTeam) && {assignedTeam _target != 'MAIN'}); + statement = QUOTE([ARR_2(_target,'MAIN')] call DFUNC(joinTeam)); + showDisabled = 1; + icon = PATHTOF(UI\team\team_white_ca.paa); + priority = 2.5; + hotkey = "N"; + }; + }; + + class ACE_JoinGroup { + displayName = "$STR_ACE_Interaction_JoinGroup"; + condition = QUOTE([ARR_2(_player,_target)] call DFUNC(canJoinGroup)); + statement = QUOTE([_player] joinSilent group _target); + showDisabled = 0; + priority = 2.6; + icon = PATHTOF(UI\team\team_management_ca.paa); + hotkey = "J"; + }; + + class ACE_GetDown { + displayName = "$STR_ACE_Interaction_GetDown"; + condition = QUOTE([_target] call DFUNC(canInteractWithCivilian)); + statement = QUOTE([_target] call DFUNC(getDown)); + showDisabled = 0; + priority = 2.2; + }; + class ACE_SendAway { + displayName = "$STR_ACE_Interaction_SendAway"; + condition = QUOTE([_target] call DFUNC(canInteractWithCivilian)); + statement = QUOTE([_target] call DFUNC(sendAway)); + showDisabled = 0; + priority = 2.0; + }; + class ACE_Pardon { + displayName = "$STR_ACE_Interaction_Pardon"; + condition = QUOTE(rating _target < -2000 && {alive _target} && {side group _player == side group _target}); + statement = QUOTE([ARR_3(_target,'{_this addRating -rating _this}',_target)] call DEFUNC(common,execRemoteFnc)); + showDisabled = 0; + priority = 2.5; + }; + }; + class ACE_Torso { + displayName = "$STR_ACE_Interaction_Torso"; + selection = "spine3"; + distance = 1.50; + condition = ""; + statement = ""; + }; + class ACE_Head { + displayName = "$STR_ACE_Interaction_Head"; + selection = "pilot"; + distance = 1.50; + condition = ""; + statement = ""; + }; + class ACE_ArmLeft { + displayName = "$STR_ACE_Interaction_ArmLeft"; + selection = "LeftForeArm"; + distance = 1.50; + condition = ""; + statement = ""; + }; + class ACE_ArmRight { + displayName = "$STR_ACE_Interaction_ArmRight"; + selection = "RightForeArm"; + distance = 1.50; + condition = ""; + statement = ""; + }; + class ACE_LegLeft { + displayName = "$STR_ACE_Interaction_LegLeft"; + selection = "LKnee"; + distance = 1.50; + condition = ""; + statement = ""; + }; + class ACE_LegRight { + displayName = "$STR_ACE_Interaction_LegRight"; + selection = "RKnee"; + distance = 1.50; + condition = ""; + statement = ""; + }; + class ACE_Weapon { + displayName = "$STR_ACE_Interaction_Weapon"; + position = QUOTE(call FUNC(getWeaponPos)); + distance = 1.50; + condition = ""; + statement = ""; + }; + + class ACE_TapShoulderRight { + displayName = "$STR_ACE_Interaction_TapShoulder"; + selection = "rightshoulder"; + distance = 2.0; + condition = QUOTE([ARR_2(_player, _target)] call DFUNC(canTapShoulder)); + statement = QUOTE([ARR_3(_player, _target, 0)] call DFUNC(tapShoulder)); + }; + class ACE_TapShoulderLeft { + displayName = "$STR_ACE_Interaction_TapShoulder"; + selection = "leftshoulder"; + distance = 2.0; + condition = QUOTE([ARR_2(_player, _target)] call DFUNC(canTapShoulder)); + statement = QUOTE([ARR_3(_player, _target, 1)] call DFUNC(tapShoulder)); + }; }; - class ACE_LeaveTeam { - displayName = "$STR_ACE_Interaction_LeaveTeam"; - condition = QUOTE(assignedTeam _player != 'MAIN'); - exceptions[] = {"isNotInside"}; - statement = QUOTE([ARR_2(_player,'MAIN')] call DFUNC(joinTeam)); - showDisabled = 1; - priority = 2.5; - icon = PATHTOF(UI\team\team_white_ca.paa); - hotkey = "N"; - }; - class ACE_BecomeLeader { - displayName = "$STR_ACE_Interaction_BecomeLeader"; - condition = QUOTE(_this call DFUNC(canBecomeLeader)); - exceptions[] = {"isNotInside"}; - statement = QUOTE(_this call DFUNC(doBecomeLeader)); - showDisabled = 1; - priority = 1.0; - icon = PATHTOF(UI\team\team_white_ca.paa); - hotkey = "L"; - }; - class ACE_LeaveGroup { - displayName = "$STR_ACE_Interaction_LeaveGroup"; - condition = QUOTE(count (units group _player) > 1); - exceptions[] = {"isNotInside"}; - statement = QUOTE(_oldGroup = units group _player; _newGroup = createGroup side _player; [_player] joinSilent _newGroup; {_player reveal _x} forEach _oldGroup;); - showDisabled = 1; - priority = 1.2; - icon = PATHTOF(UI\team\team_management_ca.paa); - hotkey = "M"; - }; - }; + class ACE_SelfActions { + class ACE_TeamManagement { + displayName = "$STR_ACE_Interaction_TeamManagement"; + condition = QUOTE(GVAR(EnableTeamManagement)); + exceptions[] = {"isNotInside"}; + statement = ""; + showDisabled = 1; + priority = 3.2; + icon = PATHTOF(UI\team\team_management_ca.paa); + hotkey = "M"; - class ACE_Gestures { - displayName = "$STR_ACE_Interaction_Gestures"; - condition = "canStand _target"; - statement = ""; - showDisabled = 1; - priority = 3.5; - icon = PATHTOF(UI\gestures_ca.paa); - hotkey = "G"; + class ACE_JoinTeamRed { + displayName = "$STR_ACE_Interaction_JoinTeamRed"; + condition = QUOTE(true); + exceptions[] = {"isNotInside"}; + statement = QUOTE([ARR_2(_player,'RED')] call DFUNC(joinTeam)); + showDisabled = 1; + priority = 2.4; + icon = PATHTOF(UI\team\team_red_ca.paa); + hotkey = "R"; + }; + class ACE_JoinTeamGreen { + displayName = "$STR_ACE_Interaction_JoinTeamGreen"; + condition = QUOTE(true); + exceptions[] = {"isNotInside"}; + statement = QUOTE([ARR_2(_player,'GREEN')] call DFUNC(joinTeam)); + showDisabled = 1; + priority = 2.3; + icon = PATHTOF(UI\team\team_green_ca.paa); + hotkey = "G"; + }; + class ACE_JoinTeamBlue { + displayName = "$STR_ACE_Interaction_JoinTeamBlue"; + condition = QUOTE(true); + exceptions[] = {"isNotInside"}; + statement = QUOTE([ARR_2(_player,'BLUE')] call DFUNC(joinTeam)); + showDisabled = 1; + priority = 2.2; + icon = PATHTOF(UI\team\team_blue_ca.paa); + hotkey = "B"; + }; + class ACE_JoinTeamYellow { + displayName = "$STR_ACE_Interaction_JoinTeamYellow"; + condition = QUOTE(true); + exceptions[] = {"isNotInside"}; + statement = QUOTE([ARR_2(_player,'YELLOW')] call DFUNC(joinTeam)); + showDisabled = 1; + priority = 2.1; + icon = PATHTOF(UI\team\team_yellow_ca.paa); + hotkey = "Y"; + }; - /*class ACE_Gesture_Advance { - displayName = "$STR_ACE_Interaction_Gestures_Attack"; - condition = "canStand _target"; - statement = "_target playActionNow 'gestureAttack';"; - showDisabled = 1; - priority = 2.0; - };*/ - class ACE_Gesture_Advance { - displayName = "$STR_ACE_Interaction_Gestures_Advance"; - condition = QUOTE(canStand _target); - statement = QUOTE(_target playActionNow 'gestureAdvance';); - showDisabled = 1; - priority = 1.9; - hotkey = "1"; - }; - class ACE_Gesture_Go { - displayName = "$STR_ACE_Interaction_Gestures_Go"; - condition = QUOTE(canStand _target); - statement = QUOTE(_target playActionNow ([ARR_2('gestureGo','gestureGoB')] select floor random 2);); - showDisabled = 1; - priority = 1.8; - hotkey = "2"; - }; - class ACE_Gesture_Follow { - displayName = "$STR_ACE_Interaction_Gestures_Follow"; - condition = QUOTE(canStand _target); - statement = QUOTE(_target playActionNow 'gestureFollow';); - showDisabled = 1; - priority = 1.7; - hotkey = "3"; - }; - /*class ACE_Gesture_Point { - displayName = "$STR_ACE_Interaction_Gestures_Point"; - condition = QUOTE(canStand _target); - statement = QUOTE(_target playActionNow 'gesturePoint';); - showDisabled = 1; - priority = 1.6; - };*/ - class ACE_Gesture_Up { - displayName = "$STR_ACE_Interaction_Gestures_Up"; - condition = QUOTE(canStand _target); - statement = QUOTE(_target playActionNow 'gestureUp';); - showDisabled = 1; - priority = 1.5; - hotkey = "4"; - }; - class ACE_Gesture_Cover { - displayName = "$STR_ACE_Interaction_Gestures_Cover"; - condition = QUOTE(canStand _target); - statement = QUOTE(_target playActionNow 'gestureCover';); - showDisabled = 1; - priority = 1.4; - hotkey = "5"; - }; - class ACE_Gesture_CeaseFire { - displayName = "$STR_ACE_Interaction_Gestures_Cease_Fire"; - condition = QUOTE(canStand _target); - statement = QUOTE(_target playActionNow 'gestureCeaseFire';); - showDisabled = 1; - priority = 1.3; - hotkey = "6"; - }; - class ACE_Gesture_Freeze { - displayName = "$STR_ACE_Interaction_Gestures_Freeze"; - condition = QUOTE(canStand _target); - statement = QUOTE(_target playActionNow 'gestureFreeze';); - showDisabled = 1; - priority = 1.2; - hotkey = "7"; - }; - class ACE_Gesture_Yes { - displayName = "$STR_ACE_Interaction_Gestures_Yes"; - condition = QUOTE(canStand _target); - statement = QUOTE(_target playActionNow ([ARR_2('gestureYes','gestureNod')] select floor random 2);); - showDisabled = 1; - priority = 1.1; - hotkey = "8"; - }; - class ACE_Gesture_No { - displayName = "$STR_ACE_Interaction_Gestures_No"; - condition = QUOTE(canStand _target); - statement = QUOTE(_target playActionNow 'gestureNo';); - showDisabled = 1; - priority = 1.0; - hotkey = "9"; - }; - class ACE_Gesture_Hi { - displayName = "$STR_ACE_Interaction_Gestures_Hi"; - condition = QUOTE(canStand _target); - statement = QUOTE(_target playActionNow ([ARR_3('gestureHi','gestureHiB','gestureHiC')] select floor random 3);); - showDisabled = 1; - priority = 0.9; - hotkey = "0"; - }; - }; + class ACE_LeaveTeam { + displayName = "$STR_ACE_Interaction_LeaveTeam"; + condition = QUOTE(assignedTeam _player != 'MAIN'); + exceptions[] = {"isNotInside"}; + statement = QUOTE([ARR_2(_player,'MAIN')] call DFUNC(joinTeam)); + showDisabled = 1; + priority = 2.5; + icon = PATHTOF(UI\team\team_white_ca.paa); + hotkey = "N"; + }; + class ACE_BecomeLeader { + displayName = "$STR_ACE_Interaction_BecomeLeader"; + condition = QUOTE(_this call DFUNC(canBecomeLeader)); + exceptions[] = {"isNotInside"}; + statement = QUOTE(_this call DFUNC(doBecomeLeader)); + showDisabled = 1; + priority = 1.0; + icon = PATHTOF(UI\team\team_white_ca.paa); + hotkey = "L"; + }; + class ACE_LeaveGroup { + displayName = "$STR_ACE_Interaction_LeaveGroup"; + condition = QUOTE(count (units group _player) > 1); + exceptions[] = {"isNotInside"}; + statement = QUOTE(_oldGroup = units group _player; _newGroup = createGroup side _player; [_player] joinSilent _newGroup; {_player reveal _x} forEach _oldGroup;); + showDisabled = 1; + priority = 1.2; + icon = PATHTOF(UI\team\team_management_ca.paa); + hotkey = "M"; + }; + }; - class ACE_Equipment { - displayName = "$STR_ACE_Interaction_Equipment"; - condition = QUOTE(true); - exceptions[] = {"isNotInside","notOnMap"}; - statement = ""; - showDisabled = 1; - priority = 4.5; - icon = ""; // @todo - hotkey = "E"; - }; - }; - }; + class ACE_Gestures { + displayName = "$STR_ACE_Interaction_Gestures"; + condition = "canStand _target"; + statement = ""; + showDisabled = 1; + priority = 3.5; + icon = PATHTOF(UI\gestures_ca.paa); + hotkey = "G"; - class LandVehicle; - class Car: LandVehicle { - class ACE_Actions { - class ACE_MainActions { - displayName = "$STR_ACE_Interaction_MainAction"; - selection = ""; - distance = 10; - condition = "true"; - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); - }; - }; - }; - class ACE_SelfActions { - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); - }; - }; - }; - class Tank: LandVehicle { - class ACE_Actions { - class ACE_MainActions { - displayName = "$STR_ACE_Interaction_MainAction"; - selection = ""; - distance = 10; - condition = "true"; - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); - }; - }; - }; - class ACE_SelfActions { - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); - }; - }; - }; + /*class ACE_Gesture_Advance { + displayName = "$STR_ACE_Interaction_Gestures_Attack"; + condition = "canStand _target"; + statement = "_target playActionNow 'gestureAttack';"; + showDisabled = 1; + priority = 2.0; + };*/ + class ACE_Gesture_Advance { + displayName = "$STR_ACE_Interaction_Gestures_Advance"; + condition = QUOTE(canStand _target); + statement = QUOTE(_target playActionNow 'gestureAdvance';); + showDisabled = 1; + priority = 1.9; + hotkey = "1"; + }; + class ACE_Gesture_Go { + displayName = "$STR_ACE_Interaction_Gestures_Go"; + condition = QUOTE(canStand _target); + statement = QUOTE(_target playActionNow ([ARR_2('gestureGo','gestureGoB')] select floor random 2);); + showDisabled = 1; + priority = 1.8; + hotkey = "2"; + }; + class ACE_Gesture_Follow { + displayName = "$STR_ACE_Interaction_Gestures_Follow"; + condition = QUOTE(canStand _target); + statement = QUOTE(_target playActionNow 'gestureFollow';); + showDisabled = 1; + priority = 1.7; + hotkey = "3"; + }; + /*class ACE_Gesture_Point { + displayName = "$STR_ACE_Interaction_Gestures_Point"; + condition = QUOTE(canStand _target); + statement = QUOTE(_target playActionNow 'gesturePoint';); + showDisabled = 1; + priority = 1.6; + };*/ + class ACE_Gesture_Up { + displayName = "$STR_ACE_Interaction_Gestures_Up"; + condition = QUOTE(canStand _target); + statement = QUOTE(_target playActionNow 'gestureUp';); + showDisabled = 1; + priority = 1.5; + hotkey = "4"; + }; + class ACE_Gesture_Cover { + displayName = "$STR_ACE_Interaction_Gestures_Cover"; + condition = QUOTE(canStand _target); + statement = QUOTE(_target playActionNow 'gestureCover';); + showDisabled = 1; + priority = 1.4; + hotkey = "5"; + }; + class ACE_Gesture_CeaseFire { + displayName = "$STR_ACE_Interaction_Gestures_Cease_Fire"; + condition = QUOTE(canStand _target); + statement = QUOTE(_target playActionNow 'gestureCeaseFire';); + showDisabled = 1; + priority = 1.3; + hotkey = "6"; + }; + class ACE_Gesture_Freeze { + displayName = "$STR_ACE_Interaction_Gestures_Freeze"; + condition = QUOTE(canStand _target); + statement = QUOTE(_target playActionNow 'gestureFreeze';); + showDisabled = 1; + priority = 1.2; + hotkey = "7"; + }; + class ACE_Gesture_Yes { + displayName = "$STR_ACE_Interaction_Gestures_Yes"; + condition = QUOTE(canStand _target); + statement = QUOTE(_target playActionNow ([ARR_2('gestureYes','gestureNod')] select floor random 2);); + showDisabled = 1; + priority = 1.1; + hotkey = "8"; + }; + class ACE_Gesture_No { + displayName = "$STR_ACE_Interaction_Gestures_No"; + condition = QUOTE(canStand _target); + statement = QUOTE(_target playActionNow 'gestureNo';); + showDisabled = 1; + priority = 1.0; + hotkey = "9"; + }; + class ACE_Gesture_Hi { + displayName = "$STR_ACE_Interaction_Gestures_Hi"; + condition = QUOTE(canStand _target); + statement = QUOTE(_target playActionNow ([ARR_3('gestureHi','gestureHiB','gestureHiC')] select floor random 3);); + showDisabled = 1; + priority = 0.9; + hotkey = "0"; + }; + }; - class Air; - class Helicopter: Air { - class ACE_Actions { - class ACE_MainActions { - displayName = "$STR_ACE_Interaction_MainAction"; - selection = ""; - distance = 10; - condition = "true"; - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + class ACE_Equipment { + displayName = "$STR_ACE_Interaction_Equipment"; + condition = QUOTE(true); + exceptions[] = {"isNotInside","notOnMap"}; + statement = ""; + showDisabled = 1; + priority = 4.5; + icon = ""; // @todo + hotkey = "E"; + }; }; - }; }; - class ACE_SelfActions { - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); - }; - }; - }; - class Plane: Air { - class ACE_Actions { - class ACE_MainActions { - displayName = "$STR_ACE_Interaction_MainAction"; - selection = ""; - distance = 10; - condition = "true"; - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + + class LandVehicle; + class Car: LandVehicle { + class ACE_Actions { + class ACE_MainActions { + displayName = "$STR_ACE_Interaction_MainAction"; + selection = ""; + distance = 10; + condition = "true"; + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; + }; }; - }; - }; - class ACE_SelfActions { - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); - }; - }; - }; - - class Ship; - class Ship_F: Ship { - class ACE_Actions { - class ACE_MainActions { - displayName = "$STR_ACE_Interaction_MainAction"; - selection = ""; - distance = 10; - condition = "true"; - - class ACE_Push { - displayName = "$STR_ACE_Interaction_Push"; - distance = 6; - condition = QUOTE(getMass _target < 1000 && {alive _target}); - statement = QUOTE([ARR_2(_target, [ARR_3(2 * (vectorDir _player select 0), 2 * (vectorDir _player select 1), 0.5)])] call DFUNC(push);); - showDisabled = 0; - priority = -1; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; }; - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; + class Tank: LandVehicle { + class ACE_Actions { + class ACE_MainActions { + displayName = "$STR_ACE_Interaction_MainAction"; + selection = ""; + distance = 10; + condition = "true"; + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; + }; }; - }; - }; - class ACE_SelfActions { - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); - }; - }; - }; - - class StaticWeapon: LandVehicle { - class ACE_Actions { - class ACE_MainActions { - displayName = "$STR_ACE_Interaction_MainAction"; - selection = "gunnerview"; - distance = 2; - condition = "true"; - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; }; - }; }; - class ACE_SelfActions { - class ACE_Passengers { - displayName = "$STR_ACE_Interaction_Passengers"; - condition = "true"; - statement = ""; - insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); - }; - }; - }; - class thingX; - class ReammoBox_F: thingX { - class ACE_Actions { - class ACE_MainActions { - displayName = "$STR_ACE_Interaction_MainAction"; - selection = ""; - distance = 2; - condition = "true"; - }; + class Air; + class Helicopter: Air { + class ACE_Actions { + class ACE_MainActions { + displayName = "$STR_ACE_Interaction_MainAction"; + selection = ""; + distance = 10; + condition = "true"; + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; + }; + }; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; + }; + }; + class Plane: Air { + class ACE_Actions { + class ACE_MainActions { + displayName = "$STR_ACE_Interaction_MainAction"; + selection = ""; + distance = 10; + condition = "true"; + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; + }; + }; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; + }; }; - class ACE_SelfActions {}; - }; + class Ship; + class Ship_F: Ship { + class ACE_Actions { + class ACE_MainActions { + displayName = "$STR_ACE_Interaction_MainAction"; + selection = ""; + distance = 10; + condition = "true"; + + class ACE_Push { + displayName = "$STR_ACE_Interaction_Push"; + distance = 6; + condition = QUOTE(getMass _target < 1000 && {alive _target}); + statement = QUOTE([ARR_2(_target, [ARR_3(2 * (vectorDir _player select 0), 2 * (vectorDir _player select 1), 0.5)])] call DFUNC(push);); + showDisabled = 0; + priority = -1; + }; + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; + }; + }; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; + }; + }; + + class StaticWeapon: LandVehicle { + class ACE_Actions { + class ACE_MainActions { + displayName = "$STR_ACE_Interaction_MainAction"; + selection = "gunnerview"; + distance = 2; + condition = "true"; + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; + }; + }; + class ACE_SelfActions { + class ACE_Passengers { + displayName = "$STR_ACE_Interaction_Passengers"; + condition = "true"; + statement = ""; + insertChildren = QUOTE(_this call DFUNC(addPassengersActions)); + }; + }; + }; + + class thingX; + class ReammoBox_F: thingX { + class ACE_Actions { + class ACE_MainActions { + displayName = "$STR_ACE_Interaction_MainAction"; + selection = ""; + distance = 2; + condition = "true"; + }; + }; + class ACE_SelfActions {}; + }; }; diff --git a/addons/interaction/Menu_Config.hpp b/addons/interaction/Menu_Config.hpp index 38f12066e0..790874a1ac 100644 --- a/addons/interaction/Menu_Config.hpp +++ b/addons/interaction/Menu_Config.hpp @@ -1,46 +1,44 @@ - #define HSPACE 0.5-2.0/16/2 #define VSPACE 0.5-0.3/9/2 -class RscStructuredText; class ACE_Interaction_Button_Base { - tooltip = ""; - //action = "ACE_Interaction_isMousePressed = true;(findDisplay 1713999) closeDisplay 1;_action = ACE_Interaction_Buttons select ACE_Interaction_SelectedButton;ACE_Interaction_SelectedButton = -1; if (call (_action select 2)) then {call (_action select 1)};"; - action = ""; + tooltip = ""; + //action = "ACE_Interaction_isMousePressed = true;(findDisplay 1713999) closeDisplay 1;_action = ACE_Interaction_Buttons select ACE_Interaction_SelectedButton;ACE_Interaction_SelectedButton = -1; if (call (_action select 2)) then {call (_action select 1)};"; + action = ""; - idc = -1; - access = 0; - type = 1; - text = ""; - font = "PuristaMedium"; - sizeEx = "0.8 / 40 / (getResolution select 5)"; - shadow = 2; + idc = -1; + access = 0; + type = 1; + text = ""; + font = "PuristaMedium"; + sizeEx = "0.8 / 40 / (getResolution select 5)"; + shadow = 2; - style = 2; - x = 0; - y = 0; - w = 2.0 / 16 * safezoneW; - h = 0.3 / 9 * safezoneH; + style = 2; + x = 0; + y = 0; + w = 2.0 / 16 * safezoneW; + h = 0.3 / 9 * safezoneH; - offsetX = 0.003; - offsetY = 0.003; - offsetPressedX = 0.002; - offsetPressedY = 0.002; - borderSize = 0; + offsetX = 0.003; + offsetY = 0.003; + offsetPressedX = 0.002; + offsetPressedY = 0.002; + borderSize = 0; - colorText[] = {1,1,1,1}; - colorDisabled[] = {0.5,0.5,0.5,1}; - colorBackground[] = {0,0,0,0.8}; - colorBackgroundDisabled[] = {0,0,0,0.8}; - colorBackgroundActive[] = {1,1,1,0}; - colorFocused[] = {1,1,1,1}; - colorShadow[] = {0,0,0,0}; - colorBorder[] = {1,1,1,0.8}; + colorText[] = {1,1,1,1}; + colorDisabled[] = {0.5,0.5,0.5,1}; + colorBackground[] = {0,0,0,0.8}; + colorBackgroundDisabled[] = {0,0,0,0.8}; + colorBackgroundActive[] = {1,1,1,0}; + colorFocused[] = {1,1,1,1}; + colorShadow[] = {0,0,0,0}; + colorBorder[] = {1,1,1,0.8}; - soundEnter[] = {"\A3\ui_f\data\sound\RscButton\soundEnter",0.09,1}; - soundPush[] = {"\A3\ui_f\data\sound\RscButton\soundPush",0.09,1}; - soundClick[] = {"\A3\ui_f\data\sound\RscButton\soundClick",0.09,1}; - soundEscape[] = {"\A3\ui_f\data\sound\RscButton\soundEscape",0.09,1}; + soundEnter[] = {"\A3\ui_f\data\sound\RscButton\soundEnter",0.09,1}; + soundPush[] = {"\A3\ui_f\data\sound\RscButton\soundPush",0.09,1}; + soundClick[] = {"\A3\ui_f\data\sound\RscButton\soundClick",0.09,1}; + soundEscape[] = {"\A3\ui_f\data\sound\RscButton\soundEscape",0.09,1}; }; class RscListbox; @@ -49,86 +47,86 @@ class RscText; #define X_OFFSET 0.2 class RscACE_SelectAnItem { - idd = 8854; - movingEnable = 0; - class controls { - class back:IGUIBack { - x = X_OFFSET; - y = 0; - w = 0.6; - h = 0.71; - colorBackground[] = {0, 0, 0, 0.2}; - }; - class header: RscText{ - idc = 8870; - x = X_OFFSET + 0.005; - y = 0.005; - w = 0.59; - h = 0.05; - style = 0x02; - text = ""; - }; - class itemList:RscListBox { - onMouseButtonDblClick = "_this call ACE_Interaction_fnc_onSelectMenuDblClick"; - idc = 8866; - x = X_OFFSET + 0.005; - w = 0.59; - h = 0.54; - y = 0.06; - }; + idd = 8854; + movingEnable = 0; + class controls { + class back:IGUIBack { + x = X_OFFSET; + y = 0; + w = 0.6; + h = 0.71; + colorBackground[] = {0, 0, 0, 0.2}; + }; + class header: RscText{ + idc = 8870; + x = X_OFFSET + 0.005; + y = 0.005; + w = 0.59; + h = 0.05; + style = 0x02; + text = ""; + }; + class itemList:RscListBox { + onMouseButtonDblClick = "_this call ACE_Interaction_fnc_onSelectMenuDblClick"; + idc = 8866; + x = X_OFFSET + 0.005; + w = 0.59; + h = 0.54; + y = 0.06; + }; - class cancelBtnBackground: ACE_Interaction_Button_Base { - type = 0; - style = 2; - idc = -1; - colorBackground[] = {0,0,0,0.5}; - colorBackgroundDisabled[] = {0,0,0,0.5}; - x = X_OFFSET + 0.005; - w = 0.15; - h = 0.1; - y = 0.605; - }; - class approveBtnBackground: ACE_Interaction_Button_Base { - type = 0; - style = 2; - idc = -1; - colorBackground[] = {0,0,0,0.5}; - colorBackgroundDisabled[] = {0,0,0,0.5}; - x = X_OFFSET + 0.445; - y = 0.605; - h = 0.1; - w = 0.15; - }; + class cancelBtnBackground: ACE_Interaction_Button_Base { + type = 0; + style = 2; + idc = -1; + colorBackground[] = {0,0,0,0.5}; + colorBackgroundDisabled[] = {0,0,0,0.5}; + x = X_OFFSET + 0.005; + w = 0.15; + h = 0.1; + y = 0.605; + }; + class approveBtnBackground: ACE_Interaction_Button_Base { + type = 0; + style = 2; + idc = -1; + colorBackground[] = {0,0,0,0.5}; + colorBackgroundDisabled[] = {0,0,0,0.5}; + x = X_OFFSET + 0.445; + y = 0.605; + h = 0.1; + w = 0.15; + }; - class cancelBtn: ACE_Interaction_Button_Base { - idc = 8855; - x = X_OFFSET + 0.005; - w = 0.15; - h = 0.1; - y = 0.605; - style = 2; - text = $STR_ACE_Interaction_Back; //$STR_ACE_Interaction_CancelSelection; - action = "call ACE_Interaction_fnc_hideMenu;"; //'Default' call ACE_Interaction_fnc_openMenu; 'Default' call ACE_Interaction_fnc_openMenuSelf; - colorBackground[] = {0,0,0,0}; - colorBackgroundDisabled[] = {0,0,0,0}; - colorBackgroundActive[] = {1,1,1,0.2}; - colorFocused[] = {0,0,0,0}; + class cancelBtn: ACE_Interaction_Button_Base { + idc = 8855; + x = X_OFFSET + 0.005; + w = 0.15; + h = 0.1; + y = 0.605; + style = 2; + text = $STR_ACE_Interaction_Back; //$STR_ACE_Interaction_CancelSelection; + action = "call ACE_Interaction_fnc_hideMenu;"; //'Default' call ACE_Interaction_fnc_openMenu; 'Default' call ACE_Interaction_fnc_openMenuSelf; + colorBackground[] = {0,0,0,0}; + colorBackgroundDisabled[] = {0,0,0,0}; + colorBackgroundActive[] = {1,1,1,0.2}; + colorFocused[] = {0,0,0,0}; + }; + class approveBtn: ACE_Interaction_Button_Base { + idc = 8860; + x = X_OFFSET + 0.445; + y = 0.605; + h = 0.1; + w = 0.15; + style = 2; + text = $STR_ACE_Interaction_MakeSelection; + action = "call ACE_Interaction_fnc_hideMenu;"; + colorBackground[] = {0,0,0,0}; + colorBackgroundDisabled[] = {0,0,0,0}; + colorBackgroundActive[] = {1,1,1,0.2}; + colorFocused[] = {0,0,0,0}; + }; }; - class approveBtn: ACE_Interaction_Button_Base { - idc = 8860; - x = X_OFFSET + 0.445; - y = 0.605; - h = 0.1; - w = 0.15; - style = 2; - text = $STR_ACE_Interaction_MakeSelection; - action = "call ACE_Interaction_fnc_hideMenu;"; - colorBackground[] = {0,0,0,0}; - colorBackgroundDisabled[] = {0,0,0,0}; - colorBackgroundActive[] = {1,1,1,0.2}; - colorFocused[] = {0,0,0,0}; - }; - }; }; #define GUI_GRID_W (0.025) @@ -136,64 +134,64 @@ class RscACE_SelectAnItem { class RscPicture; class RscInteractionIcon: RscPicture { - x = 19.25 * GUI_GRID_W; - y = 15.75 * GUI_GRID_H; - w = 2*GUI_GRID_H; - h = 2*GUI_GRID_H; + x = 19.25 * GUI_GRID_W; + y = 15.75 * GUI_GRID_H; + w = 2*GUI_GRID_H; + h = 2*GUI_GRID_H; }; class RscInteractionHelperIcon: RscInteractionIcon { - x = 20 * GUI_GRID_W; - y = 16 * GUI_GRID_H; - w = GUI_GRID_H; - h = GUI_GRID_H; + x = 20 * GUI_GRID_W; + y = 16 * GUI_GRID_H; + w = GUI_GRID_H; + h = GUI_GRID_H; }; class RscInteractionText: RscText{ - x = 21 * GUI_GRID_W; - y = 16 * GUI_GRID_H; - w = 8 * GUI_GRID_W; - h = 1.5 * GUI_GRID_H; + x = 21 * GUI_GRID_W; + y = 16 * GUI_GRID_H; + w = 8 * GUI_GRID_W; + h = 1.5 * GUI_GRID_H; }; class RscTitles { - class GVAR(InteractionHelper) { - idd = 9930; - enableSimulation = 1; - movingEnable = 0; - fadeIn=0.5; - fadeOut=0.5; - duration = 10e10; - onLoad = "uiNamespace setVariable ['ACE_Helper_Display', _this select 0];"; + class GVAR(InteractionHelper) { + idd = 9930; + enableSimulation = 1; + movingEnable = 0; + fadeIn=0.5; + fadeOut=0.5; + duration = 10e10; + onLoad = "uiNamespace setVariable ['ACE_Helper_Display', _this select 0];"; - class controls { - class SelectIcon: RscInteractionHelperIcon{ - idc = 1200; - text = PATHTOF(UI\mouse_left_ca.paa); - y = 17.5 * GUI_GRID_H; - }; - class SelectText: RscInteractionText{ - idc = 1000; - y = 17 * GUI_GRID_H; - text = $STR_ACE_Interaction_MakeSelection; - }; - class GoBackIcon: RscInteractionHelperIcon{ - idc = 1201; - text = PATHTOF(UI\mouse_right_ca.paa); - y = 19.5 * GUI_GRID_H; - }; - class GoBackText: RscInteractionText{ - idc = 1001; - y = 19 * GUI_GRID_H; - text = $STR_ACE_Interaction_Back; - }; - class ScrollIcon: RscInteractionHelperIcon{ - idc = 1202; - text = PATHTOF(UI\mouse_scroll_ca.paa); - y = 18.5 * GUI_GRID_H; - }; - class ScrollText: RscInteractionText{ - idc = 1002; - y = 18 * GUI_GRID_H; - text = $STR_ACE_Interaction_ScrollHint; - }; + class controls { + class SelectIcon: RscInteractionHelperIcon{ + idc = 1200; + text = PATHTOF(UI\mouse_left_ca.paa); + y = 17.5 * GUI_GRID_H; + }; + class SelectText: RscInteractionText{ + idc = 1000; + y = 17 * GUI_GRID_H; + text = $STR_ACE_Interaction_MakeSelection; + }; + class GoBackIcon: RscInteractionHelperIcon{ + idc = 1201; + text = PATHTOF(UI\mouse_right_ca.paa); + y = 19.5 * GUI_GRID_H; + }; + class GoBackText: RscInteractionText{ + idc = 1001; + y = 19 * GUI_GRID_H; + text = $STR_ACE_Interaction_Back; + }; + class ScrollIcon: RscInteractionHelperIcon{ + idc = 1202; + text = PATHTOF(UI\mouse_scroll_ca.paa); + y = 18.5 * GUI_GRID_H; + }; + class ScrollText: RscInteractionText{ + idc = 1002; + y = 18 * GUI_GRID_H; + text = $STR_ACE_Interaction_ScrollHint; + }; + }; }; - }; }; diff --git a/addons/interaction/README.md b/addons/interaction/README.md index 92401b2547..8e841e9a58 100644 --- a/addons/interaction/README.md +++ b/addons/interaction/README.md @@ -3,7 +3,6 @@ ace_interaction Provides interaction options between units. - ## Maintainers The people responsible for merging changes to this component or answering potential questions. diff --git a/addons/interaction/config.cpp b/addons/interaction/config.cpp index cfca73a90b..7d10e1bef5 100644 --- a/addons/interaction/config.cpp +++ b/addons/interaction/config.cpp @@ -1,26 +1,24 @@ #include "script_component.hpp" class CfgPatches { - class ADDON { - units[] = {}; - weapons[] = {}; - requiredVersion = REQUIRED_VERSION; - requiredAddons[] = {"ace_interact_menu"}; - author[] = {"commy2", "KoffeinFlummi", "esteldunedain", "bux578"}; - authorUrl = "https://github.com/commy2/"; - VERSION_CONFIG; - }; + class ADDON { + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_interact_menu"}; + author[] = {"commy2", "KoffeinFlummi", "esteldunedain", "bux578"}; + authorUrl = "https://github.com/commy2/"; + VERSION_CONFIG; + }; }; #include "CfgEventHandlers.hpp" - #include "CfgVehicles.hpp" - -#include <Menu_Config.hpp> +#include "Menu_Config.hpp" class ACE_Settings { - class GVAR(EnableTeamManagement) { - value = 1; - typeName = "BOOL"; - }; + class GVAR(EnableTeamManagement) { + value = 1; + typeName = "BOOL"; + }; }; From 212b8528fa289fc44a1f68feaeeeb31df4320664 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Sat, 9 May 2015 21:30:52 +0100 Subject: [PATCH 10/51] Bird locality code no longer needed --- addons/zeus/functions/fnc_bi_moduleCurator.sqf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/addons/zeus/functions/fnc_bi_moduleCurator.sqf b/addons/zeus/functions/fnc_bi_moduleCurator.sqf index 36110ac4fe..640ca7cead 100644 --- a/addons/zeus/functions/fnc_bi_moduleCurator.sqf +++ b/addons/zeus/functions/fnc_bi_moduleCurator.sqf @@ -215,6 +215,7 @@ if (_activated) then { } foreach (synchronizedobjects _logic); _addons call bis_fnc_activateaddons; + /* Removed by ACE //--- Locality changed _logic addeventhandler [ "local", @@ -224,6 +225,7 @@ if (_activated) then { _bird setowner owner _logic; } ]; + */ }; //--- Player From e0c658560bc50c9cc6d7ce1b11c8db0410432c92 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Sun, 10 May 2015 15:33:03 +0100 Subject: [PATCH 11/51] Added myself to authors.txt --- AUTHORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS.txt b/AUTHORS.txt index 366664efbd..f1f1db5755 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -72,6 +72,7 @@ Raspu86 Riccardo Petricca <petriccarcc@gmail.com> Robert Boklahánics <bokirobi@gmail.com> ramius86 <pasini86@hotmail.com> +SilentSpike <SilentSpike100@gmail.com> simon84 <badguy360th@gmail.com> Sniperwolf572 <tenga6@gmail.com> Tachi <zaveruha007@gmail.com> From eaa0f16e3038c4d21261cb9de5e584daa2e4eba4 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Sun, 10 May 2015 17:17:17 +0100 Subject: [PATCH 12/51] Transferring rest of function files --- addons/zeus/functions/fnc_bi_moduleMine.sqf | 18 +++ .../functions/fnc_bi_moduleProjectile.sqf | 141 +++++++++++++++++ .../functions/fnc_bi_moduleRemoteControl.sqf | 149 ++++++++++++++++++ 3 files changed, 308 insertions(+) create mode 100644 addons/zeus/functions/fnc_bi_moduleMine.sqf create mode 100644 addons/zeus/functions/fnc_bi_moduleProjectile.sqf create mode 100644 addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf diff --git a/addons/zeus/functions/fnc_bi_moduleMine.sqf b/addons/zeus/functions/fnc_bi_moduleMine.sqf new file mode 100644 index 0000000000..68e798df3a --- /dev/null +++ b/addons/zeus/functions/fnc_bi_moduleMine.sqf @@ -0,0 +1,18 @@ +_logic = _this select 0; +_units = _this select 1; +_activated = _this select 2; + +if (_activated) then { + _explosive = gettext (configfile >> "cfgvehicles" >> typeof _logic >> "explosive"); + if (_explosive != "") then { + _explosive = createvehicle [_explosive,position _logic,[],0,"none"]; + _explosive attachto [_logic]; + + //--- Show hint to curator who placed the object + [[["Curator","PlaceMines"],nil,nil,nil,nil,nil,nil,true],"bis_fnc_advHint",_logic] call bis_fnc_mp; + + waituntil {sleep 0.1; isnull _explosive || isnull _logic || !alive _logic}; + if (isnull _logic) then {deletevehicle _explosive;} else {_explosive setdamage 1;}; + deletevehicle _logic; + }; +}; \ No newline at end of file diff --git a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf new file mode 100644 index 0000000000..7d9a8301f4 --- /dev/null +++ b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf @@ -0,0 +1,141 @@ +_logic = _this select 0; +_units = _this select 1; +_activated = _this select 2; + +if ({local _x} count (objectcurators _logic) > 0) then { + //--- Reveal the circle to curators + _logic hideobject false; + _logic setpos position _logic; +}; +if !(isserver) exitwith {}; + +if (_activated) then { + _ammo = _logic getvariable ["type",gettext (configfile >> "cfgvehicles" >> typeof _logic >> "ammo")]; + if (_ammo != "") then { + _cfgAmmo = configfile >> "cfgammo" >> _ammo; + //if !(isclass _cfgAmmo) exitwith {["CfgAmmo class '%1' not found.",_ammo] call bis_fnc_error;}; + _dirVar = _fnc_scriptname + typeof _logic; + _logic setdir (missionnamespace getvariable [_dirVar,direction _logic]); //--- Restore custom direction + _pos = getposatl _logic; + _posAmmo = +_pos; + _posAmmo set [2,0]; + _dir = direction _logic; + _simulation = tolower gettext (configfile >> "cfgammo" >> _ammo >> "simulation"); + _altitude = 0; + _velocity = []; + _attach = false; + _radio = ""; + _delay = 60; + _sound = ""; + _soundSourceClass = ""; + _hint = []; + _shakeStrength = 0; + _shakeRadius = 0; + switch (_simulation) do { + case "shotshell": { + _altitude = 1000; + _velocity = [0,0,-100]; + _radio = "SentGenIncoming"; + _sounds = if (getnumber (_cfgAmmo >> "hit") < 200) then {["mortar1","mortar2"]} else {["shell1","shell2","shell3","shell4"]}; + _sound = _sounds call bis_fnc_selectrandom; + _hint = ["Curator","PlaceOrdnance"]; + _shakeStrength = 0.01; + _shakeRadius = 300; + }; + case "shotsubmunitions": { + _posAmmo = [_posAmmo,500,_dir + 180] call bis_fnc_relpos; + _altitude = 1000 - ((getterrainheightasl _posAmmo) - (getterrainheightasl _pos)); + _posAmmo set [2,_altitude]; + _velocity = [sin _dir * 68,cos _dir * 68,-100]; + _radio = "SentGenIncoming"; + _hint = ["Curator","PlaceOrdnance"]; + _shakeStrength = 0.02; + _shakeRadius = 500; + }; + case "shotilluminating": { + _altitude = 66; + _velocity = [wind select 0,wind select 1,30]; + _sound = "SN_Flare_Fired_4"; + _soundSourceClass = "SoundFlareLoop_F"; + }; + case "shotnvgmarker"; + case "shotsmokex": { + _altitude = 0; + _velocity = [0,0,0]; + _attach = true; + }; + default {["Ammo simulation '%1' is not supported",_simulation] call bis_fnc_error;}; + }; + if (count _hint > 0) then { + [[_hint,nil,nil,nil,nil,nil,nil,true],"bis_fnc_advHint",objectcurators _logic] call bis_fnc_mp; + }; + if (count _velocity == 3) then { + _altitude = (_logic getvariable ["altitude",_altitude]) call bis_fnc_parsenumber; + _radio = _logic getvariable ["radio",_radio]; + + //--- Create projectile + _posAmmo set [2,_altitude]; + _projectile = createvehicle [_ammo,_posAmmo,[],0,"none"]; + _projectile setpos _posAmmo; + _projectile setvelocity _velocity; + if (_attach) then {_projectile attachto [_logic,[0,0,_altitude]];}; + + //--- Play sound + if (_sound != "") then {[[_logic,_sound,"say3D"],"bis_fnc_sayMessage"] call bis_fnc_mp;}; + + //--- Create sound source + _soundSource = if (_soundSourceClass != "") then {createSoundSource [_soundSourceClass,_pos,[],0]} else {objnull}; + + //--- Update + if (_attach) then { + waituntil { + _soundSource setposatl getposatl _projectile; + sleep 1; + isnull _projectile || isnull _logic + }; + } else { + waituntil { + _soundSource setposatl getposatl _projectile; + + if (getposatl _logic distance _pos > 0 || direction _logic != _dir) then { + _posNew = getposasl _logic; + _dirDiff = direction _logic - _dir; + _posNew = [_posNew,[getposasl _projectile,_pos] call bis_fnc_distance2d,direction _logic + 180] call bis_fnc_relpos; + _posNew set [2,getposasl _projectile select 2]; + _projectile setvelocity ([velocity _projectile,-_dirDiff] call bis_fnc_rotatevector2d); + _projectile setposasl _posNew; + _pos = getposatl _logic; + _dir = direction _logic; + missionnamespace setvariable [_dirVar,_dir]; + }; + sleep 0.1; + isnull _projectile || isnull _logic + }; + }; + deletevehicle _projectile; + deletevehicle _soundSource; + if (count objectcurators _logic > 0) then { + + //--- Delete curator spawned logic + if (_shakeStrength > 0) then { + if (_simulation == "shotsubmunitions") then {sleep 0.5;}; + [[_shakeStrength,0.7,[position _logic,_shakeRadius]],"bis_fnc_shakeCuratorCamera"] call bis_fnc_mp; + }; + deletevehicle _logic; + } else { + + //--- Repeat to achieve permanent effect + _repeat = _logic getvariable ["repeat",0] > 0; + if (_repeat) then { + [_logic,_units,_activated] call bis_fnc_moduleprojectile; + } else { + deletevehicle _logic; + }; + }; + } else { + deletevehicle _logic; + }; + } else { + ["Cannot create projectile, 'ammo' config attribute is missing in %1",typeof _logic] call bis_fnc_error; + }; +}; \ No newline at end of file diff --git a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf new file mode 100644 index 0000000000..cbf1ae69c2 --- /dev/null +++ b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf @@ -0,0 +1,149 @@ +_logic = _this select 0; +_units = _this select 1; +_activated = _this select 2; + +if (_activated && local _logic && !isnull curatorcamera) then { + + //--- Terminate when remote control is already in progress + if !(isnull (missionnamespace getvariable ["bis_fnc_moduleRemoteControl_unit",objnull])) exitwith {}; + + //--- Get unit under cursor + _unit = objnull; + _mouseOver = missionnamespace getvariable ["bis_fnc_curatorObjectPlaced_mouseOver",[""]]; + if ((_mouseOver select 0) == typename objnull) then {_unit = _mouseOver select 1;}; + _unit = effectivecommander _unit; + + //--- Check if the unit is suitable + _error = ""; + if !(side group _unit in [east,west,resistance,civilian]) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorEmpty";}; + if (isplayer _unit) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorPlayer";}; + if !(alive _unit) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorDestroyed";}; + if (isnull _unit) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorNull";}; + if !(isnull (_unit getvariable ["bis_fnc_moduleRemoteControl_owner",objnull])) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorControl";}; + + if (_error == "") then { + _unit spawn { + scriptname "bis_fnc_moduleRemoteControl: Loop"; + _unit = _this; + _vehicle = vehicle _unit; + _vehicleRole = str assignedvehiclerole _unit; + + bis_fnc_moduleRemoteControl_unit = _unit; + _unit setvariable ["bis_fnc_moduleRemoteControl_owner",player,true]; + + _blur = ppeffectcreate ["RadialBlur",144]; + _blur ppeffectenable true; + _blur ppeffectadjust [0,0,0.3,0.3]; + _blur ppeffectcommit 0; + _blur ppeffectadjust [0.03,0.03,0.1,0.1]; + _blur ppeffectcommit 1; + + _cam = "camera" camcreate getposatl curatorcamera; + _cam cameraeffect ["internal","back"]; + _cam campreparetarget (screentoworld [0.5,0.5]); + _cam camcommitprepared 0; + _cam campreparetarget _unit; + _cam campreparefov 0.1; + _cam camcommitprepared 1; + sleep 0.75; + + ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black out",0.25]; + sleep 0.25; + + //--- Wait for interface to close + (finddisplay 312) closedisplay 2; + waituntil {isnull curatorcamera}; + + //--- Switch + player remotecontrol _unit; + if (cameraon != _vehicle) then { + _vehicle switchcamera cameraview; + }; + + ppeffectdestroy _blur; + _cam cameraeffect ["terminate","back"]; + camdestroy _cam; + + _color = ppeffectcreate ["colorCorrections",1896]; + _color ppeffectenable true; + _color ppeffectadjust [1,1,0,[0,0,0,1],[1,1,1,1],[0,0,0,0],[0.9,0.0,0,0,0,0.5,1]]; + _color ppeffectcommit 0; + + _curator = getassignedcuratorlogic player; + [_curator,"curatorObjectRemoteControlled",[_curator,player,_unit,true]] call bis_fnc_callScriptedEventHandler; + [["Curator","RemoteControl"],nil,nil,nil,nil,nil,nil,true] call bis_fnc_advHint; + + sleep 0.3; + _color ppeffectadjust [1,1,0,[0,0,0,1],[1,1,1,1],[0,0,0,0],[0.9,0.85,0,0,0,0.5,1]]; + _color ppeffectcommit 0.3; + ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black in",0.5]; + + //--- Back to player + _vehicle = vehicle _unit; + _vehicleRole = str assignedvehiclerole _unit; + _rating = rating player; + waituntil { + //--- Refresh when vehicle or vehicle role changes + if ((vehicle _unit != _vehicle || str assignedvehiclerole _unit != _vehicleRole) && {alive _unit}) then { + player remotecontrol _unit; + _vehicle = vehicle _unit; + _vehicleRole = str assignedvehiclerole _unit; + }; + if (rating player < _rating) then { + player addrating (-rating player + _rating); + }; + sleep 0.01; + !isnull curatorcamera + || + {cameraon == vehicle player} + || + {!alive _unit} //--- Also isnull check, objNull is not alive + || + {isnull getassignedcuratorlogic player} + //|| + //{_unit getvariable ["bis_fnc_moduleRemoteControl_owner",objnull] != player} //--- Another curator stole the unit + }; + + player addrating (-rating player + _rating); + objnull remotecontrol _unit; + _unit setvariable ["bis_fnc_moduleRemoteControl_owner",nil,true]; + + //--- Death screen + if ( + isnull curatorcamera + && + {cameraon != vehicle player} + && + {!isnull _unit} + && + {!isnull getassignedcuratorlogic player} + //&& + //{(_unit getvariable ["bis_fnc_moduleRemoteControl_owner",objnull] == player)} + ) then { + sleep 2; + ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black out",1]; + sleep 1; + }; + _unitPos = getposatl _unit; + _camPos = [_unitPos,10,direction _unit + 180] call bis_fnc_relpos; + _camPos set [2,(_unitPos select 2) + (getterrainheightasl _unitPos) - (getterrainheightasl _camPos) + 10]; + //[_camPos,_unit] call bis_fnc_setcuratorcamera; + (getassignedcuratorlogic player) setvariable ["bis_fnc_modulecuratorsetcamera_params",[_camPos,_unit]]; + + sleep 0.1; //--- Engine needs a delay in case controlled unit was deleted + ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black in",1e10]; + opencuratorinterface; + ppeffectdestroy _color; + + waituntil {!isnull curatorcamera}; + player switchcamera cameraview; + bis_fnc_moduleRemoteControl_unit = nil; + ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black in",1]; + [_curator,"curatorObjectRemoteControlled",[_curator,player,_unit,false]] call bis_fnc_callScriptedEventHandler; + sleep 0.01; + }; + } else { + [objnull,_error] call bis_fnc_showCuratorFeedbackMessage; + }; + deletevehicle _logic; +}; \ No newline at end of file From 9dd163ac3da97d7605f0906d189ef1b895315887 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Sun, 10 May 2015 17:21:18 +0100 Subject: [PATCH 13/51] Use moduleProjectile with ballistics support --- .../functions/fnc_bi_moduleProjectile.sqf | 303 +++++++++++------- 1 file changed, 179 insertions(+), 124 deletions(-) diff --git a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf index 7d9a8301f4..e6b98588a6 100644 --- a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf +++ b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf @@ -1,141 +1,196 @@ +/* + * Author: Bohemia Interactive + * Module function for spawning projectiles + * Used by Curator artillery modules etc + * Edited to remove radio warning (also retiained ballistics support) + * + * Arguments: + * 0: The logic object <OBJECT> + * + * Return Value: + * nil + * + * Public: No + */ + +_fnc_scriptNameParentTemp = if !(isnil '_fnc_scriptName') then {_fnc_scriptName} else {'BIS_fnc_moduleProjectile'}; +private ['_fnc_scriptNameParent']; +_fnc_scriptNameParent = _fnc_scriptNameParentTemp; +_fnc_scriptNameParentTemp = nil; + +private ['_fnc_scriptName']; +_fnc_scriptName = 'BIS_fnc_moduleProjectile'; +scriptname _fnc_scriptName; + +private ["_logic", "_units", "_activated"]; _logic = _this select 0; _units = _this select 1; _activated = _this select 2; if ({local _x} count (objectcurators _logic) > 0) then { - //--- Reveal the circle to curators - _logic hideobject false; - _logic setpos position _logic; + //--- Reveal the circle to curators + _logic hideobject false; + _logic setpos position _logic; }; if !(isserver) exitwith {}; if (_activated) then { - _ammo = _logic getvariable ["type",gettext (configfile >> "cfgvehicles" >> typeof _logic >> "ammo")]; - if (_ammo != "") then { - _cfgAmmo = configfile >> "cfgammo" >> _ammo; - //if !(isclass _cfgAmmo) exitwith {["CfgAmmo class '%1' not found.",_ammo] call bis_fnc_error;}; - _dirVar = _fnc_scriptname + typeof _logic; - _logic setdir (missionnamespace getvariable [_dirVar,direction _logic]); //--- Restore custom direction - _pos = getposatl _logic; - _posAmmo = +_pos; - _posAmmo set [2,0]; - _dir = direction _logic; - _simulation = tolower gettext (configfile >> "cfgammo" >> _ammo >> "simulation"); - _altitude = 0; - _velocity = []; - _attach = false; - _radio = ""; - _delay = 60; - _sound = ""; - _soundSourceClass = ""; - _hint = []; - _shakeStrength = 0; - _shakeRadius = 0; - switch (_simulation) do { - case "shotshell": { - _altitude = 1000; - _velocity = [0,0,-100]; - _radio = "SentGenIncoming"; - _sounds = if (getnumber (_cfgAmmo >> "hit") < 200) then {["mortar1","mortar2"]} else {["shell1","shell2","shell3","shell4"]}; - _sound = _sounds call bis_fnc_selectrandom; - _hint = ["Curator","PlaceOrdnance"]; - _shakeStrength = 0.01; - _shakeRadius = 300; - }; - case "shotsubmunitions": { - _posAmmo = [_posAmmo,500,_dir + 180] call bis_fnc_relpos; - _altitude = 1000 - ((getterrainheightasl _posAmmo) - (getterrainheightasl _pos)); - _posAmmo set [2,_altitude]; - _velocity = [sin _dir * 68,cos _dir * 68,-100]; - _radio = "SentGenIncoming"; - _hint = ["Curator","PlaceOrdnance"]; - _shakeStrength = 0.02; - _shakeRadius = 500; - }; - case "shotilluminating": { - _altitude = 66; - _velocity = [wind select 0,wind select 1,30]; - _sound = "SN_Flare_Fired_4"; - _soundSourceClass = "SoundFlareLoop_F"; - }; - case "shotnvgmarker"; - case "shotsmokex": { - _altitude = 0; - _velocity = [0,0,0]; - _attach = true; - }; - default {["Ammo simulation '%1' is not supported",_simulation] call bis_fnc_error;}; - }; - if (count _hint > 0) then { - [[_hint,nil,nil,nil,nil,nil,nil,true],"bis_fnc_advHint",objectcurators _logic] call bis_fnc_mp; - }; - if (count _velocity == 3) then { - _altitude = (_logic getvariable ["altitude",_altitude]) call bis_fnc_parsenumber; - _radio = _logic getvariable ["radio",_radio]; + _ammo = _logic getvariable ["type",gettext (configfile >> "cfgvehicles" >> typeof _logic >> "ammo")]; + if (_ammo != "") then { + _cfgAmmo = configfile >> "cfgammo" >> _ammo; + //if !(isclass _cfgAmmo) exitwith {["CfgAmmo class '%1' not found.",_ammo] call bis_fnc_error;}; + _dirVar = _fnc_scriptname + typeof _logic; + _logic setdir (missionnamespace getvariable [_dirVar,direction _logic]); //--- Restore custom direction + _pos = getposatl _logic; + _posAmmo = +_pos; + _posAmmo set [2,0]; + _dir = direction _logic; + _simulation = tolower gettext (configfile >> "cfgammo" >> _ammo >> "simulation"); + _altitude = 0; + _velocity = []; + _attach = false; + _radio = ""; + _delay = 60; + _sound = ""; + _soundSourceClass = ""; + _hint = []; + _shakeStrength = 0; + _shakeRadius = 0; + switch (_simulation) do { + case "shotshell": { + _altitude = 1000; + _velocity = [0,0,-100]; + _radio = "SentGenIncoming"; + _sounds = if (getnumber (_cfgAmmo >> "hit") < 200) then {["mortar1","mortar2"]} else {["shell1","shell2","shell3","shell4"]}; + _sound = _sounds call bis_fnc_selectrandom; + _hint = ["Curator","PlaceOrdnance"]; + _shakeStrength = 0.01; + _shakeRadius = 300; + }; + case "shotsubmunitions": { + _posAmmo = [_posAmmo,500,_dir + 180] call bis_fnc_relpos; + _altitude = 1000 - ((getterrainheightasl _posAmmo) - (getterrainheightasl _pos)); + _posAmmo set [2,_altitude]; + _velocity = [sin _dir * 68,cos _dir * 68,-100]; + _radio = "SentGenIncoming"; + _hint = ["Curator","PlaceOrdnance"]; + _shakeStrength = 0.02; + _shakeRadius = 500; + }; + case "shotilluminating": { + _altitude = 66; + _velocity = [wind select 0,wind select 1,30]; + _sound = "SN_Flare_Fired_4"; + _soundSourceClass = "SoundFlareLoop_F"; + }; + case "shotnvgmarker"; + case "shotsmokex": { + _altitude = 0; + _velocity = [0,0,0]; + _attach = true; + }; + default {["Ammo simulation '%1' is not supported",_simulation] call bis_fnc_error;}; + }; + /* Removed by ACE + _fnc_playRadio = { + if (_radio != "") then { + _entities = (getposatl _logic) nearentities ["All",100]; + _sides = []; + { + if (isplayer _x) then { + _side = side group _x; + if (_side in [east,west,resistance,civilian]) then { + //--- Play radio (only if it wasn't played recently) + if (time > _x getvariable ["BIS_fnc_moduleProjectile_radio",-_delay]) then { + [[_side,_radio,"side"],"bis_fnc_sayMessage",_x] call bis_fnc_mp; + _x setvariable ["BIS_fnc_moduleProjectile_radio",time + _delay]; + }; + }; + }; + } foreach _entities; + }; + }; + */ + if (count _hint > 0) then { + [[_hint,nil,nil,nil,nil,nil,nil,true],"bis_fnc_advHint",objectcurators _logic] call bis_fnc_mp; + }; + if (count _velocity == 3) then { + _altitude = (_logic getvariable ["altitude",_altitude]) call bis_fnc_parsenumber; + _radio = _logic getvariable ["radio",_radio]; - //--- Create projectile - _posAmmo set [2,_altitude]; - _projectile = createvehicle [_ammo,_posAmmo,[],0,"none"]; - _projectile setpos _posAmmo; - _projectile setvelocity _velocity; - if (_attach) then {_projectile attachto [_logic,[0,0,_altitude]];}; + //--- Create projectile + _posAmmo set [2,_altitude]; + _projectile = createvehicle [_ammo,_posAmmo,[],0,"none"]; + _projectile setpos _posAmmo; + _projectile setvelocity _velocity; + if (_attach) then {_projectile attachto [_logic,[0,0,_altitude]];}; - //--- Play sound - if (_sound != "") then {[[_logic,_sound,"say3D"],"bis_fnc_sayMessage"] call bis_fnc_mp;}; + // This is our addition to this function + if (!isnil "ace_frag_fnc_addManualTrack") then { + [_projectile] call ace_frag_fnc_addManualTrack + }; - //--- Create sound source - _soundSource = if (_soundSourceClass != "") then {createSoundSource [_soundSourceClass,_pos,[],0]} else {objnull}; + //--- Play sound + if (_sound != "") then {[[_logic,_sound,"say3D"],"bis_fnc_sayMessage"] call bis_fnc_mp;}; - //--- Update - if (_attach) then { - waituntil { - _soundSource setposatl getposatl _projectile; - sleep 1; - isnull _projectile || isnull _logic - }; - } else { - waituntil { - _soundSource setposatl getposatl _projectile; + //--- Create sound source + _soundSource = if (_soundSourceClass != "") then {createSoundSource [_soundSourceClass,_pos,[],0]} else {objnull}; - if (getposatl _logic distance _pos > 0 || direction _logic != _dir) then { - _posNew = getposasl _logic; - _dirDiff = direction _logic - _dir; - _posNew = [_posNew,[getposasl _projectile,_pos] call bis_fnc_distance2d,direction _logic + 180] call bis_fnc_relpos; - _posNew set [2,getposasl _projectile select 2]; - _projectile setvelocity ([velocity _projectile,-_dirDiff] call bis_fnc_rotatevector2d); - _projectile setposasl _posNew; - _pos = getposatl _logic; - _dir = direction _logic; - missionnamespace setvariable [_dirVar,_dir]; - }; - sleep 0.1; - isnull _projectile || isnull _logic - }; - }; - deletevehicle _projectile; - deletevehicle _soundSource; - if (count objectcurators _logic > 0) then { + /* Removed by ACE + //--- Play radio warning + [] call _fnc_playRadio; + */ - //--- Delete curator spawned logic - if (_shakeStrength > 0) then { - if (_simulation == "shotsubmunitions") then {sleep 0.5;}; - [[_shakeStrength,0.7,[position _logic,_shakeRadius]],"bis_fnc_shakeCuratorCamera"] call bis_fnc_mp; - }; - deletevehicle _logic; - } else { + //--- Update + if (_attach) then { + waituntil { + _soundSource setposatl getposatl _projectile; + sleep 1; + isnull _projectile || isnull _logic + }; + } else { + waituntil { + _soundSource setposatl getposatl _projectile; - //--- Repeat to achieve permanent effect - _repeat = _logic getvariable ["repeat",0] > 0; - if (_repeat) then { - [_logic,_units,_activated] call bis_fnc_moduleprojectile; - } else { - deletevehicle _logic; - }; - }; - } else { - deletevehicle _logic; - }; - } else { - ["Cannot create projectile, 'ammo' config attribute is missing in %1",typeof _logic] call bis_fnc_error; - }; + if (getposatl _logic distance _pos > 0 || direction _logic != _dir) then { + _posNew = getposasl _logic; + _dirDiff = direction _logic - _dir; + _posNew = [_posNew,[getposasl _projectile,_pos] call bis_fnc_distance2d,direction _logic + 180] call bis_fnc_relpos; + _posNew set [2,getposasl _projectile select 2]; + _projectile setvelocity ([velocity _projectile,-_dirDiff] call bis_fnc_rotatevector2d); + _projectile setposasl _posNew; + _pos = getposatl _logic; + _dir = direction _logic; + missionnamespace setvariable [_dirVar,_dir]; + }; + sleep 0.1; + isnull _projectile || isnull _logic + }; + }; + deletevehicle _projectile; + deletevehicle _soundSource; + if (count objectcurators _logic > 0) then { + + //--- Delete curator spawned logic + if (_shakeStrength > 0) then { + if (_simulation == "shotsubmunitions") then {sleep 0.5;}; + [[_shakeStrength,0.7,[position _logic,_shakeRadius]],"bis_fnc_shakeCuratorCamera"] call bis_fnc_mp; + }; + deletevehicle _logic; + } else { + + //--- Repeat to achieve permanent effect + _repeat = _logic getvariable ["repeat",0] > 0; + if (_repeat) then { + [_logic,_units,_activated] call bis_fnc_moduleprojectile; + } else { + deletevehicle _logic; + }; + }; + } else { + deletevehicle _logic; + }; + } else { + ["Cannot create projectile, 'ammo' config attribute is missing in %1",typeof _logic] call bis_fnc_error; + }; }; \ No newline at end of file From 5166e73cc0cd21b6c12e20aedb83cb7971913636 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Sun, 10 May 2015 17:26:24 +0100 Subject: [PATCH 14/51] Added commented out code and function prep --- addons/zeus/XEH_preInit.sqf | 3 + addons/zeus/functions/fnc_bi_moduleMine.sqf | 31 ++- .../functions/fnc_bi_moduleRemoteControl.sqf | 253 +++++++++--------- 3 files changed, 153 insertions(+), 134 deletions(-) diff --git a/addons/zeus/XEH_preInit.sqf b/addons/zeus/XEH_preInit.sqf index 2574706239..726f6923b3 100644 --- a/addons/zeus/XEH_preInit.sqf +++ b/addons/zeus/XEH_preInit.sqf @@ -3,5 +3,8 @@ ADDON = false; PREP(bi_moduleCurator); +PREP(bi_moduleMine); +PREP(bi_moduleProjectile); +PREP(bi_moduleRemoteControl); ADDON = true; diff --git a/addons/zeus/functions/fnc_bi_moduleMine.sqf b/addons/zeus/functions/fnc_bi_moduleMine.sqf index 68e798df3a..c3ce200a62 100644 --- a/addons/zeus/functions/fnc_bi_moduleMine.sqf +++ b/addons/zeus/functions/fnc_bi_moduleMine.sqf @@ -3,16 +3,27 @@ _units = _this select 1; _activated = _this select 2; if (_activated) then { - _explosive = gettext (configfile >> "cfgvehicles" >> typeof _logic >> "explosive"); - if (_explosive != "") then { - _explosive = createvehicle [_explosive,position _logic,[],0,"none"]; - _explosive attachto [_logic]; + _explosive = gettext (configfile >> "cfgvehicles" >> typeof _logic >> "explosive"); + if (_explosive != "") then { + _explosive = createvehicle [_explosive,position _logic,[],0,"none"]; + _explosive attachto [_logic]; - //--- Show hint to curator who placed the object - [[["Curator","PlaceMines"],nil,nil,nil,nil,nil,nil,true],"bis_fnc_advHint",_logic] call bis_fnc_mp; + /* Removed by ACE + //--- Reveal the mine to curator's side + { + _side = (getassignedcuratorunit _x) call bis_fnc_objectSide; + _side revealmine _explosive; + } foreach (objectcurators _logic); - waituntil {sleep 0.1; isnull _explosive || isnull _logic || !alive _logic}; - if (isnull _logic) then {deletevehicle _explosive;} else {_explosive setdamage 1;}; - deletevehicle _logic; - }; + //--- Mark minefields in the map + [] spawn bis_fnc_drawMinefields; + */ + + //--- Show hint to curator who placed the object + [[["Curator","PlaceMines"],nil,nil,nil,nil,nil,nil,true],"bis_fnc_advHint",_logic] call bis_fnc_mp; + + waituntil {sleep 0.1; isnull _explosive || isnull _logic || !alive _logic}; + if (isnull _logic) then {deletevehicle _explosive;} else {_explosive setdamage 1;}; + deletevehicle _logic; + }; }; \ No newline at end of file diff --git a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf index cbf1ae69c2..6289089d5e 100644 --- a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf +++ b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf @@ -4,146 +4,151 @@ _activated = _this select 2; if (_activated && local _logic && !isnull curatorcamera) then { - //--- Terminate when remote control is already in progress - if !(isnull (missionnamespace getvariable ["bis_fnc_moduleRemoteControl_unit",objnull])) exitwith {}; + //--- Terminate when remote control is already in progress + if !(isnull (missionnamespace getvariable ["bis_fnc_moduleRemoteControl_unit",objnull])) exitwith {}; - //--- Get unit under cursor - _unit = objnull; - _mouseOver = missionnamespace getvariable ["bis_fnc_curatorObjectPlaced_mouseOver",[""]]; - if ((_mouseOver select 0) == typename objnull) then {_unit = _mouseOver select 1;}; - _unit = effectivecommander _unit; + //--- Get unit under cursor + _unit = objnull; + _mouseOver = missionnamespace getvariable ["bis_fnc_curatorObjectPlaced_mouseOver",[""]]; + if ((_mouseOver select 0) == typename objnull) then {_unit = _mouseOver select 1;}; + _unit = effectivecommander _unit; - //--- Check if the unit is suitable - _error = ""; - if !(side group _unit in [east,west,resistance,civilian]) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorEmpty";}; - if (isplayer _unit) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorPlayer";}; - if !(alive _unit) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorDestroyed";}; - if (isnull _unit) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorNull";}; - if !(isnull (_unit getvariable ["bis_fnc_moduleRemoteControl_owner",objnull])) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorControl";}; + //--- Check if the unit is suitable + _error = ""; + if !(side group _unit in [east,west,resistance,civilian]) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorEmpty";}; + if (isplayer _unit) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorPlayer";}; + if !(alive _unit) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorDestroyed";}; + if (isnull _unit) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorNull";}; + if !(isnull (_unit getvariable ["bis_fnc_moduleRemoteControl_owner",objnull])) then {_error = localize "str_a3_cfgvehicles_moduleremotecontrol_f_errorControl";}; - if (_error == "") then { - _unit spawn { - scriptname "bis_fnc_moduleRemoteControl: Loop"; - _unit = _this; - _vehicle = vehicle _unit; - _vehicleRole = str assignedvehiclerole _unit; + if (_error == "") then { + _unit spawn { + scriptname "bis_fnc_moduleRemoteControl: Loop"; + _unit = _this; + _vehicle = vehicle _unit; + _vehicleRole = str assignedvehiclerole _unit; - bis_fnc_moduleRemoteControl_unit = _unit; - _unit setvariable ["bis_fnc_moduleRemoteControl_owner",player,true]; + bis_fnc_moduleRemoteControl_unit = _unit; + _unit setvariable ["bis_fnc_moduleRemoteControl_owner",player,true]; - _blur = ppeffectcreate ["RadialBlur",144]; - _blur ppeffectenable true; - _blur ppeffectadjust [0,0,0.3,0.3]; - _blur ppeffectcommit 0; - _blur ppeffectadjust [0.03,0.03,0.1,0.1]; - _blur ppeffectcommit 1; + /* Removed by ACE + //--- Play wind cue to all players + [format ["wind%1",ceil random 5],"bis_fnc_playsound"] call bis_fnc_mp; + */ - _cam = "camera" camcreate getposatl curatorcamera; - _cam cameraeffect ["internal","back"]; - _cam campreparetarget (screentoworld [0.5,0.5]); - _cam camcommitprepared 0; - _cam campreparetarget _unit; - _cam campreparefov 0.1; - _cam camcommitprepared 1; - sleep 0.75; + _blur = ppeffectcreate ["RadialBlur",144]; + _blur ppeffectenable true; + _blur ppeffectadjust [0,0,0.3,0.3]; + _blur ppeffectcommit 0; + _blur ppeffectadjust [0.03,0.03,0.1,0.1]; + _blur ppeffectcommit 1; - ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black out",0.25]; - sleep 0.25; + _cam = "camera" camcreate getposatl curatorcamera; + _cam cameraeffect ["internal","back"]; + _cam campreparetarget (screentoworld [0.5,0.5]); + _cam camcommitprepared 0; + _cam campreparetarget _unit; + _cam campreparefov 0.1; + _cam camcommitprepared 1; + sleep 0.75; - //--- Wait for interface to close - (finddisplay 312) closedisplay 2; - waituntil {isnull curatorcamera}; + ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black out",0.25]; + sleep 0.25; - //--- Switch - player remotecontrol _unit; - if (cameraon != _vehicle) then { - _vehicle switchcamera cameraview; - }; + //--- Wait for interface to close + (finddisplay 312) closedisplay 2; + waituntil {isnull curatorcamera}; - ppeffectdestroy _blur; - _cam cameraeffect ["terminate","back"]; - camdestroy _cam; + //--- Switch + player remotecontrol _unit; + if (cameraon != _vehicle) then { + _vehicle switchcamera cameraview; + }; - _color = ppeffectcreate ["colorCorrections",1896]; - _color ppeffectenable true; - _color ppeffectadjust [1,1,0,[0,0,0,1],[1,1,1,1],[0,0,0,0],[0.9,0.0,0,0,0,0.5,1]]; - _color ppeffectcommit 0; + ppeffectdestroy _blur; + _cam cameraeffect ["terminate","back"]; + camdestroy _cam; - _curator = getassignedcuratorlogic player; - [_curator,"curatorObjectRemoteControlled",[_curator,player,_unit,true]] call bis_fnc_callScriptedEventHandler; - [["Curator","RemoteControl"],nil,nil,nil,nil,nil,nil,true] call bis_fnc_advHint; + _color = ppeffectcreate ["colorCorrections",1896]; + _color ppeffectenable true; + _color ppeffectadjust [1,1,0,[0,0,0,1],[1,1,1,1],[0,0,0,0],[0.9,0.0,0,0,0,0.5,1]]; + _color ppeffectcommit 0; - sleep 0.3; - _color ppeffectadjust [1,1,0,[0,0,0,1],[1,1,1,1],[0,0,0,0],[0.9,0.85,0,0,0,0.5,1]]; - _color ppeffectcommit 0.3; - ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black in",0.5]; + _curator = getassignedcuratorlogic player; + [_curator,"curatorObjectRemoteControlled",[_curator,player,_unit,true]] call bis_fnc_callScriptedEventHandler; + [["Curator","RemoteControl"],nil,nil,nil,nil,nil,nil,true] call bis_fnc_advHint; - //--- Back to player - _vehicle = vehicle _unit; - _vehicleRole = str assignedvehiclerole _unit; - _rating = rating player; - waituntil { - //--- Refresh when vehicle or vehicle role changes - if ((vehicle _unit != _vehicle || str assignedvehiclerole _unit != _vehicleRole) && {alive _unit}) then { - player remotecontrol _unit; - _vehicle = vehicle _unit; - _vehicleRole = str assignedvehiclerole _unit; - }; - if (rating player < _rating) then { - player addrating (-rating player + _rating); - }; - sleep 0.01; - !isnull curatorcamera - || - {cameraon == vehicle player} - || - {!alive _unit} //--- Also isnull check, objNull is not alive - || - {isnull getassignedcuratorlogic player} - //|| - //{_unit getvariable ["bis_fnc_moduleRemoteControl_owner",objnull] != player} //--- Another curator stole the unit - }; + sleep 0.3; + _color ppeffectadjust [1,1,0,[0,0,0,1],[1,1,1,1],[0,0,0,0],[0.9,0.85,0,0,0,0.5,1]]; + _color ppeffectcommit 0.3; + ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black in",0.5]; - player addrating (-rating player + _rating); - objnull remotecontrol _unit; - _unit setvariable ["bis_fnc_moduleRemoteControl_owner",nil,true]; + //--- Back to player + _vehicle = vehicle _unit; + _vehicleRole = str assignedvehiclerole _unit; + _rating = rating player; + waituntil { + //--- Refresh when vehicle or vehicle role changes + if ((vehicle _unit != _vehicle || str assignedvehiclerole _unit != _vehicleRole) && {alive _unit}) then { + player remotecontrol _unit; + _vehicle = vehicle _unit; + _vehicleRole = str assignedvehiclerole _unit; + }; + if (rating player < _rating) then { + player addrating (-rating player + _rating); + }; + sleep 0.01; + !isnull curatorcamera + || + {cameraon == vehicle player} + || + {!alive _unit} //--- Also isnull check, objNull is not alive + || + {isnull getassignedcuratorlogic player} + //|| + //{_unit getvariable ["bis_fnc_moduleRemoteControl_owner",objnull] != player} //--- Another curator stole the unit + }; - //--- Death screen - if ( - isnull curatorcamera - && - {cameraon != vehicle player} - && - {!isnull _unit} - && - {!isnull getassignedcuratorlogic player} - //&& - //{(_unit getvariable ["bis_fnc_moduleRemoteControl_owner",objnull] == player)} - ) then { - sleep 2; - ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black out",1]; - sleep 1; - }; - _unitPos = getposatl _unit; - _camPos = [_unitPos,10,direction _unit + 180] call bis_fnc_relpos; - _camPos set [2,(_unitPos select 2) + (getterrainheightasl _unitPos) - (getterrainheightasl _camPos) + 10]; - //[_camPos,_unit] call bis_fnc_setcuratorcamera; - (getassignedcuratorlogic player) setvariable ["bis_fnc_modulecuratorsetcamera_params",[_camPos,_unit]]; + player addrating (-rating player + _rating); + objnull remotecontrol _unit; + _unit setvariable ["bis_fnc_moduleRemoteControl_owner",nil,true]; - sleep 0.1; //--- Engine needs a delay in case controlled unit was deleted - ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black in",1e10]; - opencuratorinterface; - ppeffectdestroy _color; + //--- Death screen + if ( + isnull curatorcamera + && + {cameraon != vehicle player} + && + {!isnull _unit} + && + {!isnull getassignedcuratorlogic player} + //&& + //{(_unit getvariable ["bis_fnc_moduleRemoteControl_owner",objnull] == player)} + ) then { + sleep 2; + ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black out",1]; + sleep 1; + }; + _unitPos = getposatl _unit; + _camPos = [_unitPos,10,direction _unit + 180] call bis_fnc_relpos; + _camPos set [2,(_unitPos select 2) + (getterrainheightasl _unitPos) - (getterrainheightasl _camPos) + 10]; + //[_camPos,_unit] call bis_fnc_setcuratorcamera; + (getassignedcuratorlogic player) setvariable ["bis_fnc_modulecuratorsetcamera_params",[_camPos,_unit]]; - waituntil {!isnull curatorcamera}; - player switchcamera cameraview; - bis_fnc_moduleRemoteControl_unit = nil; - ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black in",1]; - [_curator,"curatorObjectRemoteControlled",[_curator,player,_unit,false]] call bis_fnc_callScriptedEventHandler; - sleep 0.01; - }; - } else { - [objnull,_error] call bis_fnc_showCuratorFeedbackMessage; - }; - deletevehicle _logic; + sleep 0.1; //--- Engine needs a delay in case controlled unit was deleted + ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black in",1e10]; + opencuratorinterface; + ppeffectdestroy _color; + + waituntil {!isnull curatorcamera}; + player switchcamera cameraview; + bis_fnc_moduleRemoteControl_unit = nil; + ("bis_fnc_moduleRemoteCurator" call bis_fnc_rscLayer) cuttext ["","black in",1]; + [_curator,"curatorObjectRemoteControlled",[_curator,player,_unit,false]] call bis_fnc_callScriptedEventHandler; + sleep 0.01; + }; + } else { + [objnull,_error] call bis_fnc_showCuratorFeedbackMessage; + }; + deletevehicle _logic; }; \ No newline at end of file From a40277f6f12b0d6228d0a24d837d7d5935c778b9 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Sun, 10 May 2015 17:32:01 +0100 Subject: [PATCH 15/51] Module configs and function headers --- addons/zeus/config.cpp | 10 ++++++++++ addons/zeus/functions/fnc_bi_moduleCurator.sqf | 2 -- addons/zeus/functions/fnc_bi_moduleMine.sqf | 14 ++++++++++++++ .../zeus/functions/fnc_bi_moduleRemoteControl.sqf | 14 ++++++++++++++ 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/addons/zeus/config.cpp b/addons/zeus/config.cpp index 84d3077a96..3da43d935e 100644 --- a/addons/zeus/config.cpp +++ b/addons/zeus/config.cpp @@ -16,7 +16,17 @@ class CfgPatches { class CfgVehicles { class Module_F; + class ModuleEmpty_F; class ModuleCurator_F: Module_F { function = QUOTE(FUNC(bi_moduleCurator)); }; + class ModuleMine_F: ModuleEmpty_F { + function = QUOTE(FUNC(bi_moduleMine)); + }; + class ModuleOrdnance_F: Module_F { + function = QUOTE(FUNC(bi_moduleProjectile)); + }; + class ModuleRemoteControl_F: Module_F { + function = QUOTE(FUNC(bi_moduleRemoteControl)); + }; }; \ No newline at end of file diff --git a/addons/zeus/functions/fnc_bi_moduleCurator.sqf b/addons/zeus/functions/fnc_bi_moduleCurator.sqf index 640ca7cead..2203cb7f3a 100644 --- a/addons/zeus/functions/fnc_bi_moduleCurator.sqf +++ b/addons/zeus/functions/fnc_bi_moduleCurator.sqf @@ -12,8 +12,6 @@ * Public: No */ -#include "script_component.hpp" - _logic = _this select 0; _units = _this select 1; _activated = _this select 2; diff --git a/addons/zeus/functions/fnc_bi_moduleMine.sqf b/addons/zeus/functions/fnc_bi_moduleMine.sqf index c3ce200a62..d8142c078d 100644 --- a/addons/zeus/functions/fnc_bi_moduleMine.sqf +++ b/addons/zeus/functions/fnc_bi_moduleMine.sqf @@ -1,3 +1,17 @@ +/* + * Author: Bohemia Interactive + * Module function for spawning mines + * Edited to remove forced map markers and mines being revealed to players + * + * Arguments: + * 0: The logic object <OBJECT> + * + * Return Value: + * nil + * + * Public: No + */ + _logic = _this select 0; _units = _this select 1; _activated = _this select 2; diff --git a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf index 6289089d5e..bf73a8863e 100644 --- a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf +++ b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf @@ -1,3 +1,17 @@ +/* + * Author: Bohemia Interactive + * Module function for remote controlling units as zeus + * Edited to remove global wind sound + * + * Arguments: + * 0: The logic object <OBJECT> + * + * Return Value: + * nil + * + * Public: No + */ + _logic = _this select 0; _units = _this select 1; _activated = _this select 2; From c1c10f43b266cc2b7863c441243d1ffb1ed5a822 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Sun, 10 May 2015 17:41:43 +0100 Subject: [PATCH 16/51] Fixed typo --- addons/zeus/functions/fnc_bi_moduleProjectile.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf index e6b98588a6..afb3f6e4bc 100644 --- a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf +++ b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf @@ -2,7 +2,7 @@ * Author: Bohemia Interactive * Module function for spawning projectiles * Used by Curator artillery modules etc - * Edited to remove radio warning (also retiained ballistics support) + * Edited to remove radio warning (also retains ballistics support added by ACE_Modules) * * Arguments: * 0: The logic object <OBJECT> From 519aba57b57ce5bdcc3edbd8cd3d16d58189b820 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Mon, 11 May 2015 14:45:37 +0100 Subject: [PATCH 17/51] Transfered ballistics support (as discussed with glowbal) --- addons/modules/XEH_preInit.sqf | 1 - addons/modules/config.cpp | 5 +- .../functions/fnc_bi_moduleProjectile.sqf | 191 ------------------ 3 files changed, 1 insertion(+), 196 deletions(-) delete mode 100644 addons/modules/functions/fnc_bi_moduleProjectile.sqf diff --git a/addons/modules/XEH_preInit.sqf b/addons/modules/XEH_preInit.sqf index dfbbe2c2b9..7573d34352 100644 --- a/addons/modules/XEH_preInit.sqf +++ b/addons/modules/XEH_preInit.sqf @@ -3,7 +3,6 @@ ADDON = false; PREP(moduleInit); -PREP(bi_moduleProjectile); GVAR(moduleInitCollection) = []; diff --git a/addons/modules/config.cpp b/addons/modules/config.cpp index 4fc3b8b60d..c5880e7bb1 100644 --- a/addons/modules/config.cpp +++ b/addons/modules/config.cpp @@ -23,9 +23,6 @@ class CfgVehicles { init = QUOTE(_this call DFUNC(moduleInit)); }; }; - class ModuleOrdnance_F: Module_F { - function = "ace_modules_fnc_bi_moduleProjectile"; - }; }; -#include "CfgEventHandlers.hpp" +#include "CfgEventHandlers.hpp" \ No newline at end of file diff --git a/addons/modules/functions/fnc_bi_moduleProjectile.sqf b/addons/modules/functions/fnc_bi_moduleProjectile.sqf deleted file mode 100644 index 56e3eb9883..0000000000 --- a/addons/modules/functions/fnc_bi_moduleProjectile.sqf +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Author: Bohemia Interactive - * Module function for spawning projectiles - * Used by Curator artillery modules etc - * - * Arguments: - * 0: The logic object <OBJECT> - * - * Return Value: - * nil - * - * Public: No - */ - -_fnc_scriptNameParentTemp = if !(isnil '_fnc_scriptName') then {_fnc_scriptName} else {'BIS_fnc_moduleProjectile'}; -private ['_fnc_scriptNameParent']; -_fnc_scriptNameParent = _fnc_scriptNameParentTemp; -_fnc_scriptNameParentTemp = nil; - -private ['_fnc_scriptName']; -_fnc_scriptName = 'BIS_fnc_moduleProjectile'; -scriptname _fnc_scriptName; - -private ["_logic", "_units", "_activated"]; -_logic = _this select 0; -_units = _this select 1; -_activated = _this select 2; - -if ({local _x} count (objectcurators _logic) > 0) then { - //--- Reveal the circle to curators - _logic hideobject false; - _logic setpos position _logic; -}; -if !(isserver) exitwith {}; - -if (_activated) then { - _ammo = _logic getvariable ["type",gettext (configfile >> "cfgvehicles" >> typeof _logic >> "ammo")]; - if (_ammo != "") then { - _cfgAmmo = configfile >> "cfgammo" >> _ammo; - //if !(isclass _cfgAmmo) exitwith {["CfgAmmo class '%1' not found.",_ammo] call bis_fnc_error;}; - _dirVar = _fnc_scriptname + typeof _logic; - _logic setdir (missionnamespace getvariable [_dirVar,direction _logic]); //--- Restore custom direction - _pos = getposatl _logic; - _posAmmo = +_pos; - _posAmmo set [2,0]; - _dir = direction _logic; - _simulation = tolower gettext (configfile >> "cfgammo" >> _ammo >> "simulation"); - _altitude = 0; - _velocity = []; - _attach = false; - _radio = ""; - _delay = 60; - _sound = ""; - _soundSourceClass = ""; - _hint = []; - _shakeStrength = 0; - _shakeRadius = 0; - switch (_simulation) do { - case "shotshell": { - _altitude = 1000; - _velocity = [0,0,-100]; - _radio = "SentGenIncoming"; - _sounds = if (getnumber (_cfgAmmo >> "hit") < 200) then {["mortar1","mortar2"]} else {["shell1","shell2","shell3","shell4"]}; - _sound = _sounds call bis_fnc_selectrandom; - _hint = ["Curator","PlaceOrdnance"]; - _shakeStrength = 0.01; - _shakeRadius = 300; - }; - case "shotsubmunitions": { - _posAmmo = [_posAmmo,500,_dir + 180] call bis_fnc_relpos; - _altitude = 1000 - ((getterrainheightasl _posAmmo) - (getterrainheightasl _pos)); - _posAmmo set [2,_altitude]; - _velocity = [sin _dir * 68,cos _dir * 68,-100]; - _radio = "SentGenIncoming"; - _hint = ["Curator","PlaceOrdnance"]; - _shakeStrength = 0.02; - _shakeRadius = 500; - }; - case "shotilluminating": { - _altitude = 66; - _velocity = [wind select 0,wind select 1,30]; - _sound = "SN_Flare_Fired_4"; - _soundSourceClass = "SoundFlareLoop_F"; - }; - case "shotnvgmarker"; - case "shotsmokex": { - _altitude = 0; - _velocity = [0,0,0]; - _attach = true; - }; - default {["Ammo simulation '%1' is not supported",_simulation] call bis_fnc_error;}; - }; - _fnc_playRadio = { - if (_radio != "") then { - _entities = (getposatl _logic) nearentities ["All",100]; - _sides = []; - { - if (isplayer _x) then { - _side = side group _x; - if (_side in [east,west,resistance,civilian]) then { - //--- Play radio (only if it wasn't played recently) - if (time > _x getvariable ["BIS_fnc_moduleProjectile_radio",-_delay]) then { - [[_side,_radio,"side"],"bis_fnc_sayMessage",_x] call bis_fnc_mp; - _x setvariable ["BIS_fnc_moduleProjectile_radio",time + _delay]; - }; - }; - }; - } foreach _entities; - }; - }; - if (count _hint > 0) then { - [[_hint,nil,nil,nil,nil,nil,nil,true],"bis_fnc_advHint",objectcurators _logic] call bis_fnc_mp; - }; - if (count _velocity == 3) then { - _altitude = (_logic getvariable ["altitude",_altitude]) call bis_fnc_parsenumber; - _radio = _logic getvariable ["radio",_radio]; - - //--- Create projectile - _posAmmo set [2,_altitude]; - _projectile = createvehicle [_ammo,_posAmmo,[],0,"none"]; - _projectile setpos _posAmmo; - _projectile setvelocity _velocity; - if (_attach) then {_projectile attachto [_logic,[0,0,_altitude]];}; - - // This is our addition to this function - if (!isnil "ace_frag_fnc_addManualTrack") then { - [_projectile] call ace_frag_fnc_addManualTrack - }; - - //--- Play sound - if (_sound != "") then {[[_logic,_sound,"say3D"],"bis_fnc_sayMessage"] call bis_fnc_mp;}; - - //--- Create sound source - _soundSource = if (_soundSourceClass != "") then {createSoundSource [_soundSourceClass,_pos,[],0]} else {objnull}; - - //--- Play radio warning - [] call _fnc_playRadio; - - //--- Update - if (_attach) then { - waituntil { - _soundSource setposatl getposatl _projectile; - sleep 1; - isnull _projectile || isnull _logic - }; - } else { - waituntil { - _soundSource setposatl getposatl _projectile; - - if (getposatl _logic distance _pos > 0 || direction _logic != _dir) then { - _posNew = getposasl _logic; - _dirDiff = direction _logic - _dir; - _posNew = [_posNew,[getposasl _projectile,_pos] call bis_fnc_distance2d,direction _logic + 180] call bis_fnc_relpos; - _posNew set [2,getposasl _projectile select 2]; - _projectile setvelocity ([velocity _projectile,-_dirDiff] call bis_fnc_rotatevector2d); - _projectile setposasl _posNew; - _pos = getposatl _logic; - _dir = direction _logic; - missionnamespace setvariable [_dirVar,_dir]; - }; - sleep 0.1; - isnull _projectile || isnull _logic - }; - }; - deletevehicle _projectile; - deletevehicle _soundSource; - if (count objectcurators _logic > 0) then { - - //--- Delete curator spawned logic - if (_shakeStrength > 0) then { - if (_simulation == "shotsubmunitions") then {sleep 0.5;}; - [[_shakeStrength,0.7,[position _logic,_shakeRadius]],"bis_fnc_shakeCuratorCamera"] call bis_fnc_mp; - }; - deletevehicle _logic; - } else { - - //--- Repeat to achieve permanent effect - _repeat = _logic getvariable ["repeat",0] > 0; - if (_repeat) then { - [_logic,_units,_activated] call bis_fnc_moduleprojectile; - } else { - deletevehicle _logic; - }; - }; - } else { - deletevehicle _logic; - }; - } else { - ["Cannot create projectile, 'ammo' config attribute is missing in %1",typeof _logic] call bis_fnc_error; - }; -}; From 3118666f8093dcbe2496182777e056caaef8125e Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Mon, 11 May 2015 16:02:24 +0100 Subject: [PATCH 18/51] Added settings module to config Started functionality --- .../functions/fnc_readSettingFromModule.sqf | 2 +- addons/zeus/CfgFactionClasses.hpp | 6 ++ addons/zeus/CfgVehicles.hpp | 80 +++++++++++++++++++ addons/zeus/XEH_preInit.sqf | 1 + addons/zeus/config.cpp | 21 +---- .../functions/fnc_bi_moduleProjectile.sqf | 2 +- .../zeus/functions/fnc_moduleZeusSettings.sqf | 29 +++++++ 7 files changed, 121 insertions(+), 20 deletions(-) create mode 100644 addons/zeus/CfgFactionClasses.hpp create mode 100644 addons/zeus/CfgVehicles.hpp create mode 100644 addons/zeus/functions/fnc_moduleZeusSettings.sqf diff --git a/addons/common/functions/fnc_readSettingFromModule.sqf b/addons/common/functions/fnc_readSettingFromModule.sqf index c92bb4ab94..518df8ed43 100644 --- a/addons/common/functions/fnc_readSettingFromModule.sqf +++ b/addons/common/functions/fnc_readSettingFromModule.sqf @@ -24,4 +24,4 @@ if (isNil {_logic getVariable _moduleVariable}) exitWith { }; // Set the setting globally and force it -[_settingName, _logic getVariable _moduleVariable, true, true] call FUNC(setSetting); +[_settingName, _logic getVariable _moduleVariable, true, true] call FUNC(setSetting); \ No newline at end of file diff --git a/addons/zeus/CfgFactionClasses.hpp b/addons/zeus/CfgFactionClasses.hpp new file mode 100644 index 0000000000..5d4fe23018 --- /dev/null +++ b/addons/zeus/CfgFactionClasses.hpp @@ -0,0 +1,6 @@ +class CfgFactionClasses { + class NO_CATEGORY; + class ADDON: NO_CATEGORY { + displayName = "ACE Zeus"; + }; +}; \ No newline at end of file diff --git a/addons/zeus/CfgVehicles.hpp b/addons/zeus/CfgVehicles.hpp new file mode 100644 index 0000000000..41289e44db --- /dev/null +++ b/addons/zeus/CfgVehicles.hpp @@ -0,0 +1,80 @@ +class CfgVehicles { + class Module_F; + class ModuleEmpty_F; + class ACE_Module; + + class GVAR(moduleZeusSettings): ACE_Module { + scope = 2; + displayName = "Zeus Settings [ACE]"; + icon = QUOTE(PATHTOF(UI\Icon_Module_Medical_ca.paa)); + category = "ACE_zeus"; + function = QUOTE(DFUNC(moduleZeusSettings)); + functionPriority = 1; + isGlobal = 1; + isTriggerActivated = 0; + author = "SilentSpike"; + class Arguments { + class zeusAscension { + displayName = "Enable Ascension Messages"; + description = "Display a global popup message when a player is assigned as Zeus."; + typeName = "BOOL"; + defaultValue = 1; + }; + class zeusBird { + displayName = "Enable Eagle"; + description = "Spawn an eagle that follows the Zeus camera."; + typeName = "BOOL"; + defaultValue = 1; + }; + class radioOrdnance { + displayName = "Ordnance Radio Warning"; + description = "Play a radio warning when Zeus uses ordnance."; + typeName = "BOOL"; + defaultValue = 1; + }; + class revealMines { + displayName = "Reveal Mines"; + description = "Do you want to reveal mines placed by Zeus?"; + typeName = "NUMBER"; + class values { + class disable { + name = "Disabled"; + value = 0; + }; + class partial { + name = "Reveal to sides friendly with Zeus unit"; + value = 1; + }; + class full { + name = "Add map markers and reveal to sides friendly with Zeus unit"; + value = 2; + default = 1; + }; + }; + }; + class remoteWind { + displayName = "Reveal Remote Control"; + description = "Play a wind sound when Zeus remote controls a unit."; + typeName = "BOOL"; + defaultValue = 1; + }; + }; + class ModuleDescription { + description = "Provides control over various aspects of Zeus."; + sync[] = {}; + }; + }; + + class ModuleCurator_F: Module_F { + function = QUOTE(DFUNC(bi_moduleCurator)); + }; + class ModuleMine_F: ModuleEmpty_F { + function = QUOTE(DFUNC(bi_moduleMine)); + }; + class ModuleOrdnance_F: Module_F { + function = QUOTE(DFUNC(bi_moduleProjectile)); + }; + class ModuleRemoteControl_F: Module_F { + function = QUOTE(DFUNC(bi_moduleRemoteControl)); + }; +}; \ No newline at end of file diff --git a/addons/zeus/XEH_preInit.sqf b/addons/zeus/XEH_preInit.sqf index 726f6923b3..e7bb1b96a5 100644 --- a/addons/zeus/XEH_preInit.sqf +++ b/addons/zeus/XEH_preInit.sqf @@ -6,5 +6,6 @@ PREP(bi_moduleCurator); PREP(bi_moduleMine); PREP(bi_moduleProjectile); PREP(bi_moduleRemoteControl); +PREP(moduleZeusSettings); ADDON = true; diff --git a/addons/zeus/config.cpp b/addons/zeus/config.cpp index 3da43d935e..e469ae7aaa 100644 --- a/addons/zeus/config.cpp +++ b/addons/zeus/config.cpp @@ -5,7 +5,7 @@ class CfgPatches { units[] = {}; weapons[] = {}; requiredVersion = REQUIRED_VERSION; - requiredAddons[] = {"ace_common"}; + requiredAddons[] = {"ace_common","ace_modules"}; author[] = {"SilentSpike"}; authorUrl = "https://github.com/SilentSpike"; VERSION_CONFIG; @@ -13,20 +13,5 @@ class CfgPatches { }; #include "CfgEventHandlers.hpp" - -class CfgVehicles { - class Module_F; - class ModuleEmpty_F; - class ModuleCurator_F: Module_F { - function = QUOTE(FUNC(bi_moduleCurator)); - }; - class ModuleMine_F: ModuleEmpty_F { - function = QUOTE(FUNC(bi_moduleMine)); - }; - class ModuleOrdnance_F: Module_F { - function = QUOTE(FUNC(bi_moduleProjectile)); - }; - class ModuleRemoteControl_F: Module_F { - function = QUOTE(FUNC(bi_moduleRemoteControl)); - }; -}; \ No newline at end of file +#include "CfgFactionClasses.hpp" +#include "CfgVehicles.hpp" \ No newline at end of file diff --git a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf index afb3f6e4bc..fbae16e00d 100644 --- a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf +++ b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf @@ -2,7 +2,7 @@ * Author: Bohemia Interactive * Module function for spawning projectiles * Used by Curator artillery modules etc - * Edited to remove radio warning (also retains ballistics support added by ACE_Modules) + * Edited to remove radio warning and add ballistics support * * Arguments: * 0: The logic object <OBJECT> diff --git a/addons/zeus/functions/fnc_moduleZeusSettings.sqf b/addons/zeus/functions/fnc_moduleZeusSettings.sqf new file mode 100644 index 0000000000..94dc0d966a --- /dev/null +++ b/addons/zeus/functions/fnc_moduleZeusSettings.sqf @@ -0,0 +1,29 @@ +/* + * Author: SilentSpike + * Module for adjusting various aspects of zeus + * + * Arguments: + * 0: The module logic <LOGIC> + * 1: units <ARRAY> + * 2: activated <BOOL> + * + * Return Value: + * None <NIL> + * + * Public: No + */ + +#include "script_component.hpp" + +private ["_logic", "_units", "_activated"]; +_logic = _this select 0; +_units = _this select 1; +_activated = _this select 2; + +if !(_activated) exitWith {}; + +[_logic, QGVAR(settingAscension), "zeusAscension"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(settingBird), "zeusBird"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(settingOrdnance), "radioOrdnance"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(settingMines), "revealMines"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(settingWind), "remoteWind"] call EFUNC(common,readSettingFromModule); \ No newline at end of file From 755581be4084f8393b49bbf8343f09fea493afa0 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Mon, 11 May 2015 16:23:46 +0100 Subject: [PATCH 19/51] Changed BI functions to check for settings --- .../zeus/functions/fnc_bi_moduleCurator.sqf | 55 ++++++++++--------- addons/zeus/functions/fnc_bi_moduleMine.sqf | 22 +++++--- .../functions/fnc_bi_moduleProjectile.sqf | 11 ++-- .../functions/fnc_bi_moduleRemoteControl.sqf | 9 +-- .../zeus/functions/fnc_moduleZeusSettings.sqf | 10 ++-- 5 files changed, 57 insertions(+), 50 deletions(-) diff --git a/addons/zeus/functions/fnc_bi_moduleCurator.sqf b/addons/zeus/functions/fnc_bi_moduleCurator.sqf index 2203cb7f3a..333053c8eb 100644 --- a/addons/zeus/functions/fnc_bi_moduleCurator.sqf +++ b/addons/zeus/functions/fnc_bi_moduleCurator.sqf @@ -150,14 +150,15 @@ if (_activated) then { _x radiochanneladd [_player]; } foreach (_logic getvariable ["channels",[]]); - /* Removed by ACE - //--- Sent notification to all assigned players - { - if (isplayer _x) then { - [["CuratorAssign",[_name,name _player]],"bis_fnc_showNotification",_x] call bis_fnc_mp; - }; - } foreach (curatoreditableobjects _logic); - */ + // Added by ACE_zeus to toggle ascension messages + if (GETMVAR(QGVAR(zeusAscension),true)) then { + //--- Sent notification to all assigned players + { + if (isplayer _x) then { + [["CuratorAssign",[_name,name _player]],"bis_fnc_showNotification",_x] call bis_fnc_mp; + }; + } foreach (curatoreditableobjects _logic); + }; [_logic,"curatorUnitAssigned",[_logic,_player]] call bis_fnc_callscriptedeventhandler; @@ -189,14 +190,15 @@ if (_activated) then { }; }; - /* Removed by ACE - //--- Create bird - _birdType = _logic getvariable ["birdType","eagle_f"]; - if (_birdType != "") then { - _bird = createvehicle [_birdType,[100,100,100],[],0,"none"]; - _logic setvariable ["bird",_bird,true]; + // Added by ACE_zeus to toggle eagle + if (GETMVAR(QGVAR(zeusBird),true)) then { + //--- Create bird + _birdType = _logic getvariable ["birdType","eagle_f"]; + if (_birdType != "") then { + _bird = createvehicle [_birdType,[100,100,100],[],0,"none"]; + _logic setvariable ["bird",_bird,true]; + }; }; - */ //--- Activated all future addons _addons = []; @@ -213,17 +215,18 @@ if (_activated) then { } foreach (synchronizedobjects _logic); _addons call bis_fnc_activateaddons; - /* Removed by ACE - //--- Locality changed - _logic addeventhandler [ - "local", - { - _logic = _this select 0; - _bird = _logic getvariable ["bird",objnull]; - _bird setowner owner _logic; - } - ]; - */ + // Added by ACE_zeus to toggle eagle + if (GETMVAR(QGVAR(zeusBird),true)) then { + //--- Locality changed + _logic addeventhandler [ + "local", + { + _logic = _this select 0; + _bird = _logic getvariable ["bird",objnull]; + _bird setowner owner _logic; + } + ]; + }; }; //--- Player diff --git a/addons/zeus/functions/fnc_bi_moduleMine.sqf b/addons/zeus/functions/fnc_bi_moduleMine.sqf index d8142c078d..df1c55dbf1 100644 --- a/addons/zeus/functions/fnc_bi_moduleMine.sqf +++ b/addons/zeus/functions/fnc_bi_moduleMine.sqf @@ -22,16 +22,20 @@ if (_activated) then { _explosive = createvehicle [_explosive,position _logic,[],0,"none"]; _explosive attachto [_logic]; - /* Removed by ACE - //--- Reveal the mine to curator's side - { - _side = (getassignedcuratorunit _x) call bis_fnc_objectSide; - _side revealmine _explosive; - } foreach (objectcurators _logic); + // Added by ACE_zeus to control if mines are revealed + _revealMines = GETMVAR(QGVAR(revealMines),2); + if (_revealMines > 0) then { + //--- Reveal the mine to curator's side + { + _side = (getassignedcuratorunit _x) call bis_fnc_objectSide; + _side revealmine _explosive; + } foreach (objectcurators _logic); - //--- Mark minefields in the map - [] spawn bis_fnc_drawMinefields; - */ + if (_revealMines > 1) then { + //--- Mark minefields in the map + [] spawn bis_fnc_drawMinefields; + }; + }; //--- Show hint to curator who placed the object [[["Curator","PlaceMines"],nil,nil,nil,nil,nil,nil,true],"bis_fnc_advHint",_logic] call bis_fnc_mp; diff --git a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf index fbae16e00d..047f5ac5eb 100644 --- a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf +++ b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf @@ -91,7 +91,6 @@ if (_activated) then { }; default {["Ammo simulation '%1' is not supported",_simulation] call bis_fnc_error;}; }; - /* Removed by ACE _fnc_playRadio = { if (_radio != "") then { _entities = (getposatl _logic) nearentities ["All",100]; @@ -110,7 +109,6 @@ if (_activated) then { } foreach _entities; }; }; - */ if (count _hint > 0) then { [[_hint,nil,nil,nil,nil,nil,nil,true],"bis_fnc_advHint",objectcurators _logic] call bis_fnc_mp; }; @@ -136,10 +134,11 @@ if (_activated) then { //--- Create sound source _soundSource = if (_soundSourceClass != "") then {createSoundSource [_soundSourceClass,_pos,[],0]} else {objnull}; - /* Removed by ACE - //--- Play radio warning - [] call _fnc_playRadio; - */ + // Added by ACE_zeus to toggle ordnance radio message + if (GETMVAR(QGVAR(radioOrdnance),true)) then { + //--- Play radio warning + [] call _fnc_playRadio; + }; //--- Update if (_attach) then { diff --git a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf index bf73a8863e..e57ee98b5c 100644 --- a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf +++ b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf @@ -45,10 +45,11 @@ if (_activated && local _logic && !isnull curatorcamera) then { bis_fnc_moduleRemoteControl_unit = _unit; _unit setvariable ["bis_fnc_moduleRemoteControl_owner",player,true]; - /* Removed by ACE - //--- Play wind cue to all players - [format ["wind%1",ceil random 5],"bis_fnc_playsound"] call bis_fnc_mp; - */ + // Added by ACE_zeus to toggle remote control wind sound + if (GETMVAR(QGVAR(remoteWind),true)) then { + //--- Play wind cue to all players + [format ["wind%1",ceil random 5],"bis_fnc_playsound"] call bis_fnc_mp; + }; _blur = ppeffectcreate ["RadialBlur",144]; _blur ppeffectenable true; diff --git a/addons/zeus/functions/fnc_moduleZeusSettings.sqf b/addons/zeus/functions/fnc_moduleZeusSettings.sqf index 94dc0d966a..5963d7216c 100644 --- a/addons/zeus/functions/fnc_moduleZeusSettings.sqf +++ b/addons/zeus/functions/fnc_moduleZeusSettings.sqf @@ -22,8 +22,8 @@ _activated = _this select 2; if !(_activated) exitWith {}; -[_logic, QGVAR(settingAscension), "zeusAscension"] call EFUNC(common,readSettingFromModule); -[_logic, QGVAR(settingBird), "zeusBird"] call EFUNC(common,readSettingFromModule); -[_logic, QGVAR(settingOrdnance), "radioOrdnance"] call EFUNC(common,readSettingFromModule); -[_logic, QGVAR(settingMines), "revealMines"] call EFUNC(common,readSettingFromModule); -[_logic, QGVAR(settingWind), "remoteWind"] call EFUNC(common,readSettingFromModule); \ No newline at end of file +[_logic, QGVAR(zeusAscension), "zeusAscension"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(zeusBird), "zeusBird"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(radioOrdnance), "radioOrdnance"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(revealMines), "revealMines"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(remoteWind), "remoteWind"] call EFUNC(common,readSettingFromModule); \ No newline at end of file From e16ea007e401f15c18bcbbcdedd6171bd8dc3699 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Mon, 11 May 2015 16:30:46 +0100 Subject: [PATCH 20/51] Add ACE settings --- addons/zeus/ACE_Settings.hpp | 23 +++++++++++++++++++++++ addons/zeus/CfgVehicles.hpp | 2 +- addons/zeus/config.cpp | 3 ++- 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 addons/zeus/ACE_Settings.hpp diff --git a/addons/zeus/ACE_Settings.hpp b/addons/zeus/ACE_Settings.hpp new file mode 100644 index 0000000000..7221e51f34 --- /dev/null +++ b/addons/zeus/ACE_Settings.hpp @@ -0,0 +1,23 @@ +class ACE_Settings { + class GVAR(zeusAscension) { + typeName = "BOOL"; + value = 1; + }; + class GVAR(zeusBird) { + typeName = "BOOL"; + value = 1; + }; + class GVAR(radioOrdnance) { + typeName = "BOOL"; + value = 1; + }; + class GVAR(revealMines) { + typeName = "SCALAR"; + value = 2; + values[] = {"Disabled", "Partially", "Fully"}; + }; + class GVAR(remoteWind) { + typeName = "BOOL"; + value = 1; + }; +}; diff --git a/addons/zeus/CfgVehicles.hpp b/addons/zeus/CfgVehicles.hpp index 41289e44db..8952571f2a 100644 --- a/addons/zeus/CfgVehicles.hpp +++ b/addons/zeus/CfgVehicles.hpp @@ -6,7 +6,7 @@ class CfgVehicles { class GVAR(moduleZeusSettings): ACE_Module { scope = 2; displayName = "Zeus Settings [ACE]"; - icon = QUOTE(PATHTOF(UI\Icon_Module_Medical_ca.paa)); + //icon = QUOTE(PATHTOF(iconGoesHere)); category = "ACE_zeus"; function = QUOTE(DFUNC(moduleZeusSettings)); functionPriority = 1; diff --git a/addons/zeus/config.cpp b/addons/zeus/config.cpp index e469ae7aaa..cea8c64f76 100644 --- a/addons/zeus/config.cpp +++ b/addons/zeus/config.cpp @@ -14,4 +14,5 @@ class CfgPatches { #include "CfgEventHandlers.hpp" #include "CfgFactionClasses.hpp" -#include "CfgVehicles.hpp" \ No newline at end of file +#include "CfgVehicles.hpp" +#include "ACE_Settings.hpp" \ No newline at end of file From b09ebc9c795704eb0d3c4d10dc6f1442ab574b3d Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Mon, 11 May 2015 17:08:25 +0100 Subject: [PATCH 21/51] QGVAR was meant to be GVAR Improved module text Forgot about script_component --- addons/zeus/ACE_Settings.hpp | 8 +++---- addons/zeus/CfgVehicles.hpp | 24 +++++++++---------- .../zeus/functions/fnc_bi_moduleCurator.sqf | 8 ++++--- addons/zeus/functions/fnc_bi_moduleMine.sqf | 4 +++- .../functions/fnc_bi_moduleProjectile.sqf | 4 +++- .../functions/fnc_bi_moduleRemoteControl.sqf | 4 +++- 6 files changed, 30 insertions(+), 22 deletions(-) diff --git a/addons/zeus/ACE_Settings.hpp b/addons/zeus/ACE_Settings.hpp index 7221e51f34..179a211664 100644 --- a/addons/zeus/ACE_Settings.hpp +++ b/addons/zeus/ACE_Settings.hpp @@ -7,6 +7,10 @@ class ACE_Settings { typeName = "BOOL"; value = 1; }; + class GVAR(remoteWind) { + typeName = "BOOL"; + value = 1; + }; class GVAR(radioOrdnance) { typeName = "BOOL"; value = 1; @@ -16,8 +20,4 @@ class ACE_Settings { value = 2; values[] = {"Disabled", "Partially", "Fully"}; }; - class GVAR(remoteWind) { - typeName = "BOOL"; - value = 1; - }; }; diff --git a/addons/zeus/CfgVehicles.hpp b/addons/zeus/CfgVehicles.hpp index 8952571f2a..53c859309a 100644 --- a/addons/zeus/CfgVehicles.hpp +++ b/addons/zeus/CfgVehicles.hpp @@ -15,17 +15,23 @@ class CfgVehicles { author = "SilentSpike"; class Arguments { class zeusAscension { - displayName = "Enable Ascension Messages"; - description = "Display a global popup message when a player is assigned as Zeus."; + displayName = "Ascension Messages"; + description = "Display global popup messages when a player is assigned as Zeus."; typeName = "BOOL"; defaultValue = 1; }; class zeusBird { - displayName = "Enable Eagle"; + displayName = "Zeus Eagle"; description = "Spawn an eagle that follows the Zeus camera."; typeName = "BOOL"; defaultValue = 1; }; + class remoteWind { + displayName = "Wind Sounds"; + description = "Play wind sounds when Zeus remote controls a unit."; + typeName = "BOOL"; + defaultValue = 1; + }; class radioOrdnance { displayName = "Ordnance Radio Warning"; description = "Play a radio warning when Zeus uses ordnance."; @@ -34,7 +40,7 @@ class CfgVehicles { }; class revealMines { displayName = "Reveal Mines"; - description = "Do you want to reveal mines placed by Zeus?"; + description = "Reveal mines to allies and/or place map markers."; typeName = "NUMBER"; class values { class disable { @@ -42,22 +48,16 @@ class CfgVehicles { value = 0; }; class partial { - name = "Reveal to sides friendly with Zeus unit"; + name = "Reveal to Allies"; value = 1; }; class full { - name = "Add map markers and reveal to sides friendly with Zeus unit"; + name = "Allies + Map Markers"; value = 2; default = 1; }; }; }; - class remoteWind { - displayName = "Reveal Remote Control"; - description = "Play a wind sound when Zeus remote controls a unit."; - typeName = "BOOL"; - defaultValue = 1; - }; }; class ModuleDescription { description = "Provides control over various aspects of Zeus."; diff --git a/addons/zeus/functions/fnc_bi_moduleCurator.sqf b/addons/zeus/functions/fnc_bi_moduleCurator.sqf index 333053c8eb..92375d3114 100644 --- a/addons/zeus/functions/fnc_bi_moduleCurator.sqf +++ b/addons/zeus/functions/fnc_bi_moduleCurator.sqf @@ -12,6 +12,8 @@ * Public: No */ +#include "script_component.hpp" + _logic = _this select 0; _units = _this select 1; _activated = _this select 2; @@ -151,7 +153,7 @@ if (_activated) then { } foreach (_logic getvariable ["channels",[]]); // Added by ACE_zeus to toggle ascension messages - if (GETMVAR(QGVAR(zeusAscension),true)) then { + if (GETMVAR(GVAR(zeusAscension),true)) then { //--- Sent notification to all assigned players { if (isplayer _x) then { @@ -191,7 +193,7 @@ if (_activated) then { }; // Added by ACE_zeus to toggle eagle - if (GETMVAR(QGVAR(zeusBird),true)) then { + if (GETMVAR(GVAR(zeusBird),true)) then { //--- Create bird _birdType = _logic getvariable ["birdType","eagle_f"]; if (_birdType != "") then { @@ -216,7 +218,7 @@ if (_activated) then { _addons call bis_fnc_activateaddons; // Added by ACE_zeus to toggle eagle - if (GETMVAR(QGVAR(zeusBird),true)) then { + if (GETMVAR(GVAR(zeusBird),true)) then { //--- Locality changed _logic addeventhandler [ "local", diff --git a/addons/zeus/functions/fnc_bi_moduleMine.sqf b/addons/zeus/functions/fnc_bi_moduleMine.sqf index df1c55dbf1..73395f48c2 100644 --- a/addons/zeus/functions/fnc_bi_moduleMine.sqf +++ b/addons/zeus/functions/fnc_bi_moduleMine.sqf @@ -12,6 +12,8 @@ * Public: No */ +#include "script_component.hpp" + _logic = _this select 0; _units = _this select 1; _activated = _this select 2; @@ -23,7 +25,7 @@ if (_activated) then { _explosive attachto [_logic]; // Added by ACE_zeus to control if mines are revealed - _revealMines = GETMVAR(QGVAR(revealMines),2); + _revealMines = GETMVAR(GVAR(revealMines),2); if (_revealMines > 0) then { //--- Reveal the mine to curator's side { diff --git a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf index 047f5ac5eb..29a329ade5 100644 --- a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf +++ b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf @@ -13,6 +13,8 @@ * Public: No */ +#include "script_component.hpp" + _fnc_scriptNameParentTemp = if !(isnil '_fnc_scriptName') then {_fnc_scriptName} else {'BIS_fnc_moduleProjectile'}; private ['_fnc_scriptNameParent']; _fnc_scriptNameParent = _fnc_scriptNameParentTemp; @@ -135,7 +137,7 @@ if (_activated) then { _soundSource = if (_soundSourceClass != "") then {createSoundSource [_soundSourceClass,_pos,[],0]} else {objnull}; // Added by ACE_zeus to toggle ordnance radio message - if (GETMVAR(QGVAR(radioOrdnance),true)) then { + if (GETMVAR(GVAR(radioOrdnance),true)) then { //--- Play radio warning [] call _fnc_playRadio; }; diff --git a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf index e57ee98b5c..557d13f81f 100644 --- a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf +++ b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf @@ -12,6 +12,8 @@ * Public: No */ +#include "script_component.hpp" + _logic = _this select 0; _units = _this select 1; _activated = _this select 2; @@ -46,7 +48,7 @@ if (_activated && local _logic && !isnull curatorcamera) then { _unit setvariable ["bis_fnc_moduleRemoteControl_owner",player,true]; // Added by ACE_zeus to toggle remote control wind sound - if (GETMVAR(QGVAR(remoteWind),true)) then { + if (GETMVAR(GVAR(remoteWind),true)) then { //--- Play wind cue to all players [format ["wind%1",ceil random 5],"bis_fnc_playsound"] call bis_fnc_mp; }; From 7cf52d13ca80c673fde07321d91d92f033ee9096 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Mon, 11 May 2015 18:06:01 +0100 Subject: [PATCH 22/51] Disable zeus settings by default Fixed newline characters --- addons/common/functions/fnc_readSettingFromModule.sqf | 2 +- addons/zeus/ACE_Settings.hpp | 10 +++++----- addons/zeus/CfgFactionClasses.hpp | 2 +- addons/zeus/CfgVehicles.hpp | 2 +- addons/zeus/config.cpp | 2 +- addons/zeus/functions/fnc_bi_moduleCurator.sqf | 8 ++++---- addons/zeus/functions/fnc_bi_moduleMine.sqf | 7 +++---- addons/zeus/functions/fnc_bi_moduleProjectile.sqf | 4 ++-- addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf | 4 ++-- addons/zeus/functions/fnc_moduleZeusSettings.sqf | 2 +- addons/zeus/script_component.hpp | 2 +- 11 files changed, 22 insertions(+), 23 deletions(-) diff --git a/addons/common/functions/fnc_readSettingFromModule.sqf b/addons/common/functions/fnc_readSettingFromModule.sqf index 518df8ed43..c92bb4ab94 100644 --- a/addons/common/functions/fnc_readSettingFromModule.sqf +++ b/addons/common/functions/fnc_readSettingFromModule.sqf @@ -24,4 +24,4 @@ if (isNil {_logic getVariable _moduleVariable}) exitWith { }; // Set the setting globally and force it -[_settingName, _logic getVariable _moduleVariable, true, true] call FUNC(setSetting); \ No newline at end of file +[_settingName, _logic getVariable _moduleVariable, true, true] call FUNC(setSetting); diff --git a/addons/zeus/ACE_Settings.hpp b/addons/zeus/ACE_Settings.hpp index 179a211664..536790ba26 100644 --- a/addons/zeus/ACE_Settings.hpp +++ b/addons/zeus/ACE_Settings.hpp @@ -1,23 +1,23 @@ class ACE_Settings { class GVAR(zeusAscension) { typeName = "BOOL"; - value = 1; + value = 0; }; class GVAR(zeusBird) { typeName = "BOOL"; - value = 1; + value = 0; }; class GVAR(remoteWind) { typeName = "BOOL"; - value = 1; + value = 0; }; class GVAR(radioOrdnance) { typeName = "BOOL"; - value = 1; + value = 0; }; class GVAR(revealMines) { typeName = "SCALAR"; - value = 2; + value = 0; values[] = {"Disabled", "Partially", "Fully"}; }; }; diff --git a/addons/zeus/CfgFactionClasses.hpp b/addons/zeus/CfgFactionClasses.hpp index 5d4fe23018..bf34546727 100644 --- a/addons/zeus/CfgFactionClasses.hpp +++ b/addons/zeus/CfgFactionClasses.hpp @@ -3,4 +3,4 @@ class CfgFactionClasses { class ADDON: NO_CATEGORY { displayName = "ACE Zeus"; }; -}; \ No newline at end of file +}; diff --git a/addons/zeus/CfgVehicles.hpp b/addons/zeus/CfgVehicles.hpp index 53c859309a..a7671232a7 100644 --- a/addons/zeus/CfgVehicles.hpp +++ b/addons/zeus/CfgVehicles.hpp @@ -77,4 +77,4 @@ class CfgVehicles { class ModuleRemoteControl_F: Module_F { function = QUOTE(DFUNC(bi_moduleRemoteControl)); }; -}; \ No newline at end of file +}; diff --git a/addons/zeus/config.cpp b/addons/zeus/config.cpp index cea8c64f76..4bdc1cd5e1 100644 --- a/addons/zeus/config.cpp +++ b/addons/zeus/config.cpp @@ -15,4 +15,4 @@ class CfgPatches { #include "CfgEventHandlers.hpp" #include "CfgFactionClasses.hpp" #include "CfgVehicles.hpp" -#include "ACE_Settings.hpp" \ No newline at end of file +#include "ACE_Settings.hpp" diff --git a/addons/zeus/functions/fnc_bi_moduleCurator.sqf b/addons/zeus/functions/fnc_bi_moduleCurator.sqf index 92375d3114..a2ccf537bc 100644 --- a/addons/zeus/functions/fnc_bi_moduleCurator.sqf +++ b/addons/zeus/functions/fnc_bi_moduleCurator.sqf @@ -153,7 +153,7 @@ if (_activated) then { } foreach (_logic getvariable ["channels",[]]); // Added by ACE_zeus to toggle ascension messages - if (GETMVAR(GVAR(zeusAscension),true)) then { + if GVAR(zeusAscension) then { //--- Sent notification to all assigned players { if (isplayer _x) then { @@ -193,7 +193,7 @@ if (_activated) then { }; // Added by ACE_zeus to toggle eagle - if (GETMVAR(GVAR(zeusBird),true)) then { + if GVAR(zeusBird) then { //--- Create bird _birdType = _logic getvariable ["birdType","eagle_f"]; if (_birdType != "") then { @@ -218,7 +218,7 @@ if (_activated) then { _addons call bis_fnc_activateaddons; // Added by ACE_zeus to toggle eagle - if (GETMVAR(GVAR(zeusBird),true)) then { + if GVAR(zeusBird) then { //--- Locality changed _logic addeventhandler [ "local", @@ -330,4 +330,4 @@ if (_activated) then { player call bis_fnc_curatorRespawn; }; -}; \ No newline at end of file +}; diff --git a/addons/zeus/functions/fnc_bi_moduleMine.sqf b/addons/zeus/functions/fnc_bi_moduleMine.sqf index 73395f48c2..b5063c7fed 100644 --- a/addons/zeus/functions/fnc_bi_moduleMine.sqf +++ b/addons/zeus/functions/fnc_bi_moduleMine.sqf @@ -25,15 +25,14 @@ if (_activated) then { _explosive attachto [_logic]; // Added by ACE_zeus to control if mines are revealed - _revealMines = GETMVAR(GVAR(revealMines),2); - if (_revealMines > 0) then { + if (GVAR(revealMines) > 0) then { //--- Reveal the mine to curator's side { _side = (getassignedcuratorunit _x) call bis_fnc_objectSide; _side revealmine _explosive; } foreach (objectcurators _logic); - if (_revealMines > 1) then { + if (GVAR(revealMines) > 1) then { //--- Mark minefields in the map [] spawn bis_fnc_drawMinefields; }; @@ -46,4 +45,4 @@ if (_activated) then { if (isnull _logic) then {deletevehicle _explosive;} else {_explosive setdamage 1;}; deletevehicle _logic; }; -}; \ No newline at end of file +}; diff --git a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf index 29a329ade5..c4d0277388 100644 --- a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf +++ b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf @@ -137,7 +137,7 @@ if (_activated) then { _soundSource = if (_soundSourceClass != "") then {createSoundSource [_soundSourceClass,_pos,[],0]} else {objnull}; // Added by ACE_zeus to toggle ordnance radio message - if (GETMVAR(GVAR(radioOrdnance),true)) then { + if GVAR(radioOrdnance) then { //--- Play radio warning [] call _fnc_playRadio; }; @@ -194,4 +194,4 @@ if (_activated) then { } else { ["Cannot create projectile, 'ammo' config attribute is missing in %1",typeof _logic] call bis_fnc_error; }; -}; \ No newline at end of file +}; diff --git a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf index 557d13f81f..3efbaa0775 100644 --- a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf +++ b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf @@ -48,7 +48,7 @@ if (_activated && local _logic && !isnull curatorcamera) then { _unit setvariable ["bis_fnc_moduleRemoteControl_owner",player,true]; // Added by ACE_zeus to toggle remote control wind sound - if (GETMVAR(GVAR(remoteWind),true)) then { + if GVAR(remoteWind) then { //--- Play wind cue to all players [format ["wind%1",ceil random 5],"bis_fnc_playsound"] call bis_fnc_mp; }; @@ -168,4 +168,4 @@ if (_activated && local _logic && !isnull curatorcamera) then { [objnull,_error] call bis_fnc_showCuratorFeedbackMessage; }; deletevehicle _logic; -}; \ No newline at end of file +}; diff --git a/addons/zeus/functions/fnc_moduleZeusSettings.sqf b/addons/zeus/functions/fnc_moduleZeusSettings.sqf index 5963d7216c..3a582f7196 100644 --- a/addons/zeus/functions/fnc_moduleZeusSettings.sqf +++ b/addons/zeus/functions/fnc_moduleZeusSettings.sqf @@ -26,4 +26,4 @@ if !(_activated) exitWith {}; [_logic, QGVAR(zeusBird), "zeusBird"] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(radioOrdnance), "radioOrdnance"] call EFUNC(common,readSettingFromModule); [_logic, QGVAR(revealMines), "revealMines"] call EFUNC(common,readSettingFromModule); -[_logic, QGVAR(remoteWind), "remoteWind"] call EFUNC(common,readSettingFromModule); \ No newline at end of file +[_logic, QGVAR(remoteWind), "remoteWind"] call EFUNC(common,readSettingFromModule); diff --git a/addons/zeus/script_component.hpp b/addons/zeus/script_component.hpp index d5a4ec1bcc..7211b28f7d 100644 --- a/addons/zeus/script_component.hpp +++ b/addons/zeus/script_component.hpp @@ -9,4 +9,4 @@ #define DEBUG_SETTINGS DEBUG_SETTINGS_ZEUS #endif -#include "\z\ace\addons\main\script_macros.hpp" \ No newline at end of file +#include "\z\ace\addons\main\script_macros.hpp" From f6cdad62cad352491c9d5e4a6b6b53a5e75cc09e Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Mon, 11 May 2015 19:04:04 +0100 Subject: [PATCH 23/51] Added parenthesis --- addons/zeus/functions/fnc_bi_moduleCurator.sqf | 6 +++--- addons/zeus/functions/fnc_bi_moduleProjectile.sqf | 2 +- addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/zeus/functions/fnc_bi_moduleCurator.sqf b/addons/zeus/functions/fnc_bi_moduleCurator.sqf index a2ccf537bc..9ae35a4ce4 100644 --- a/addons/zeus/functions/fnc_bi_moduleCurator.sqf +++ b/addons/zeus/functions/fnc_bi_moduleCurator.sqf @@ -153,7 +153,7 @@ if (_activated) then { } foreach (_logic getvariable ["channels",[]]); // Added by ACE_zeus to toggle ascension messages - if GVAR(zeusAscension) then { + if (GVAR(zeusAscension)) then { //--- Sent notification to all assigned players { if (isplayer _x) then { @@ -193,7 +193,7 @@ if (_activated) then { }; // Added by ACE_zeus to toggle eagle - if GVAR(zeusBird) then { + if (GVAR(zeusBird)) then { //--- Create bird _birdType = _logic getvariable ["birdType","eagle_f"]; if (_birdType != "") then { @@ -218,7 +218,7 @@ if (_activated) then { _addons call bis_fnc_activateaddons; // Added by ACE_zeus to toggle eagle - if GVAR(zeusBird) then { + if (GVAR(zeusBird)) then { //--- Locality changed _logic addeventhandler [ "local", diff --git a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf index c4d0277388..6e2ee35387 100644 --- a/addons/zeus/functions/fnc_bi_moduleProjectile.sqf +++ b/addons/zeus/functions/fnc_bi_moduleProjectile.sqf @@ -137,7 +137,7 @@ if (_activated) then { _soundSource = if (_soundSourceClass != "") then {createSoundSource [_soundSourceClass,_pos,[],0]} else {objnull}; // Added by ACE_zeus to toggle ordnance radio message - if GVAR(radioOrdnance) then { + if (GVAR(radioOrdnance)) then { //--- Play radio warning [] call _fnc_playRadio; }; diff --git a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf index 3efbaa0775..57b325b585 100644 --- a/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf +++ b/addons/zeus/functions/fnc_bi_moduleRemoteControl.sqf @@ -48,7 +48,7 @@ if (_activated && local _logic && !isnull curatorcamera) then { _unit setvariable ["bis_fnc_moduleRemoteControl_owner",player,true]; // Added by ACE_zeus to toggle remote control wind sound - if GVAR(remoteWind) then { + if (GVAR(remoteWind)) then { //--- Play wind cue to all players [format ["wind%1",ceil random 5],"bis_fnc_playsound"] call bis_fnc_mp; }; From 228786f3ad5758a63f96376e4d3a6f2c02146f13 Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Tue, 12 May 2015 12:26:24 +0100 Subject: [PATCH 24/51] Putting the bird in its cage --- addons/zeus/CfgVehicles.hpp | 2 +- addons/zeus/XEH_preInit.sqf | 1 + .../zeus/functions/fnc_moduleCuratorDelay.sqf | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 addons/zeus/functions/fnc_moduleCuratorDelay.sqf diff --git a/addons/zeus/CfgVehicles.hpp b/addons/zeus/CfgVehicles.hpp index a7671232a7..a1f71f405a 100644 --- a/addons/zeus/CfgVehicles.hpp +++ b/addons/zeus/CfgVehicles.hpp @@ -66,7 +66,7 @@ class CfgVehicles { }; class ModuleCurator_F: Module_F { - function = QUOTE(DFUNC(bi_moduleCurator)); + function = QUOTE(DFUNC(moduleCuratorDelay)); }; class ModuleMine_F: ModuleEmpty_F { function = QUOTE(DFUNC(bi_moduleMine)); diff --git a/addons/zeus/XEH_preInit.sqf b/addons/zeus/XEH_preInit.sqf index e7bb1b96a5..5841245e65 100644 --- a/addons/zeus/XEH_preInit.sqf +++ b/addons/zeus/XEH_preInit.sqf @@ -6,6 +6,7 @@ PREP(bi_moduleCurator); PREP(bi_moduleMine); PREP(bi_moduleProjectile); PREP(bi_moduleRemoteControl); +PREP(moduleCuratorDelay); PREP(moduleZeusSettings); ADDON = true; diff --git a/addons/zeus/functions/fnc_moduleCuratorDelay.sqf b/addons/zeus/functions/fnc_moduleCuratorDelay.sqf new file mode 100644 index 0000000000..734cf1a999 --- /dev/null +++ b/addons/zeus/functions/fnc_moduleCuratorDelay.sqf @@ -0,0 +1,19 @@ +/* + * Author: SilentSpike + * Function that delays the execution of the curator module function + * Allows ascension and bird settings to be set by module beforehand + * + * Arguments: + * 0: The module logic <LOGIC> + * 1: units <ARRAY> + * 2: activated <BOOL> + * + * Return Value: + * None <NIL> + * + * Public: No + */ + +#include "script_component.hpp" + +[{_this spawn DFUNC(bi_moduleCurator);},_this] call EFUNC(common,execNextFrame); From 6a821715a04b3f8f4f57c41859ec12adbcf66542 Mon Sep 17 00:00:00 2001 From: Grzegorz Sikora <gienkov.grzegorz@gmail.com> Date: Tue, 12 May 2015 00:24:12 +0200 Subject: [PATCH 25/51] Stringtable modules Conflicts: addons/missionmodules/CfgVehicles.hpp addons/respawn/CfgVehicles.hpp --- addons/advanced_ballistics/CfgVehicles.hpp | 43 +- addons/advanced_ballistics/stringtable.xml | 80 ++++ addons/ballistics/CfgVehicles.hpp | 2 +- addons/ballistics/stringtable.xml | 6 +- addons/captives/CfgVehicles.hpp | 6 +- addons/captives/stringtable.xml | 8 + addons/common/CfgVehicles.hpp | 40 +- addons/common/config.cpp | 4 +- addons/common/stringtable.xml | 60 +++ addons/explosives/CfgModule.hpp | 28 +- addons/explosives/stringtable.xml | 32 ++ addons/hearing/CfgVehicles.hpp | 13 +- addons/hearing/stringtable.xml | 24 ++ addons/interaction/CfgVehicles.hpp | 13 +- addons/interaction/stringtable.xml | 34 +- addons/map/CfgVehicles.hpp | 56 +-- addons/map/stringtable.xml | 77 +++- addons/medical/CfgFactionClasses.hpp | 2 +- addons/medical/CfgVehicles.hpp | 219 +++++----- addons/medical/config.cpp | 2 +- .../functions/fnc_actionCheckPulseLocal.sqf | 2 +- addons/medical/stringtable.xml | 378 +++++++++++++++++- addons/microdagr/CfgVehicles.hpp | 18 +- addons/microdagr/stringtable.xml | 28 ++ addons/missileguidance/ACE_Settings.hpp | 2 +- addons/missileguidance/stringtable.xml | 12 + addons/missionmodules/CfgFactionClasses.hpp | 2 +- addons/missionmodules/CfgVehicles.hpp | 34 +- addons/missionmodules/stringtable.xml | 73 ++++ addons/mk6mortar/CfgVehicles.hpp | 18 +- addons/mk6mortar/stringtable.xml | 32 ++ addons/nametags/CfgVehicles.hpp | 44 +- addons/nametags/config.cpp | 6 +- addons/nametags/stringtable.xml | 96 +++++ addons/optionsmenu/CfgVehicles.hpp | 10 +- addons/optionsmenu/stringtable.xml | 44 ++ addons/respawn/CfgVehicleClasses.hpp | 2 +- addons/respawn/CfgVehicles.hpp | 42 +- addons/respawn/stringtable.xml | 56 +++ addons/switchunits/CfgVehicles.hpp | 51 +-- addons/switchunits/stringtable.xml | 64 +++ addons/vehiclelock/CfgVehicles.hpp | 28 +- addons/vehiclelock/stringtable.xml | 52 +++ addons/weather/CfgVehicles.hpp | 31 +- addons/weather/stringtable.xml | 56 +++ addons/winddeflection/CfgVehicles.hpp | 23 +- addons/winddeflection/stringtable.xml | 40 ++ 47 files changed, 1656 insertions(+), 337 deletions(-) create mode 100644 addons/missionmodules/stringtable.xml diff --git a/addons/advanced_ballistics/CfgVehicles.hpp b/addons/advanced_ballistics/CfgVehicles.hpp index fda4b9a8ff..4e42f35f72 100644 --- a/addons/advanced_ballistics/CfgVehicles.hpp +++ b/addons/advanced_ballistics/CfgVehicles.hpp @@ -2,7 +2,7 @@ class CfgVehicles { class ACE_Module; class GVAR(ModuleSettings): ACE_Module { scope = 2; - displayName = "Advanced Ballistics"; + displayName = "$STR_ACE_AdvancedBallistics_DisplayName"; icon = QUOTE(PATHTOF(UI\Icon_Module_Wind_ca.paa)); category = "ACE"; function = QUOTE(DFUNC(initModuleSettings)); @@ -12,26 +12,26 @@ class CfgVehicles { author = "Ruthberg"; class Arguments { class enabled { - displayName = "Advanced Ballistics"; - description = "Enables advanced ballistics"; + displayName = "$STR_ACE_AdvancedBallistics_enabled_DisplayName"; + description = "$STR_ACE_AdvancedBallistics_enabled_Description"; typeName = "BOOL"; defaultValue = 0; }; class alwaysSimulateForSnipers { - displayName = "Always Enabled For Snipers"; - description = "Always enables advanced ballistics when high power optics are used"; + displayName = "$STR_ACE_AdvancedBallistics_alwaysSimulateForSnipers_DisplayName"; + description = "$STR_ACE_AdvancedBallistics_alwaysSimulateForSnipers_Description"; typeName = "BOOL"; defaultValue = 1; }; class disabledInFullAutoMode { - displayName = "Disabled In FullAuto Mode"; - description = "Disables the advanced ballistics during full auto fire"; + displayName = "$STR_ACE_AdvancedBallistics_disabledInFullAutoMod_DisplayName"; + description = "$STR_ACE_AdvancedBallistics_disabledInFullAutoMod_Description"; typeName = "BOOL"; defaultValue = 0; }; class onlyActiveForLocalPlayers { - displayName = "Disabled For Non Local Players"; - description = "Disables the advanced ballistics for bullets coming from other players (enable this if you encounter frame drops during heavy firefights in multiplayer)"; + displayName = "$STR_ACE_AdvancedBallistics_onlyActiveForLocalPlayers_DisplayName"; + description = "$STR_ACE_AdvancedBallistics_onlyActiveForLocalPlayers_Description"; typeName = "BOOL"; defaultValue = 1; }; @@ -44,35 +44,38 @@ class CfgVehicles { }; */ class ammoTemperatureEnabled { - displayName = "Enable Ammo Temperature Simulation"; - description = "Muzzle velocity varies with ammo temperature"; + displayName = "$STR_ACE_AdvancedBallistics_ammoTemperatureEnabled_DisplayName"; + description = "$STR_ACE_AdvancedBallistics_ammoTemperatureEnabled_Description"; typeName = "BOOL"; defaultValue = 1; }; class barrelLengthInfluenceEnabled { - displayName = "Enable Barrel Length Simulation"; - description = "Muzzle velocity varies with barrel length"; + displayName = "$STR_ACE_AdvancedBallistics_barrelLengthInfluenceEnabled_DisplayName"; + description = "$STR_ACE_AdvancedBallistics_barrelLengthInfluenceEnabled_Description"; typeName = "BOOL"; defaultValue = 1; }; class bulletTraceEnabled { - displayName = "Enable Bullet Trace Effect"; - description = "Enables a bullet trace effect to high caliber bullets (only visible when looking through high power optics)"; + displayName = "$STR_ACE_AdvancedBallistics_bulletTraceEnabled_DisplayName"; + description = "$STR_ACE_AdvancedBallistics_bulletTraceEnabled_Description"; typeName = "BOOL"; defaultValue = 1; }; class simulationInterval { - displayName = "Simulation Interval"; - description = "Defines the interval between every calculation step"; + displayName = "$STR_ACE_AdvancedBallistics_simulationInterval_DisplayName"; + description = "$STR_ACE_AdvancedBallistics_simulationInterval_Description"; typeName = "NUMBER"; defaultValue = 0.0; }; class simulationRadius { - displayName = "Simulation Radius"; - description = "Defines the radius around the player (in meters) at which advanced ballistics are applied to projectiles"; + displayName = "$STR_ACE_AdvancedBallistics_simulationRadius_DisplayName"; + description = "$STR_ACE_AdvancedBallistics_simulationRadius_Description"; typeName = "NUMBER"; defaultValue = 3000; }; }; + class ModuleDescription { + description = "$STR_ACE_AdvancedBallistics_Description"; + }; }; -}; +}; \ No newline at end of file diff --git a/addons/advanced_ballistics/stringtable.xml b/addons/advanced_ballistics/stringtable.xml index 0de8071754..565e4bd801 100644 --- a/addons/advanced_ballistics/stringtable.xml +++ b/addons/advanced_ballistics/stringtable.xml @@ -25,5 +25,85 @@ <Czech>Zobrazit úhloměr</Czech> <Portuguese>Mostrar Transferidor</Portuguese> </Key> + <Key ID="STR_ACE_AdvancedBallistics_DisplayName"> + <English>Advanced Ballistics</English> + <Polish>Zaawansowana balistyka</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_enabled_DisplayName"> + <English>Advanced Ballistics</English> + <Polish>Zaawansowana balistyka</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_enabled_Description"> + <English>Enables advanced ballistics</English> + <Polish>Aktywuje zaawansowaną balistykę</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_alwaysSimulateForSnipers_DisplayName"> + <English>Always Enabled For Snipers</English> + <Polish>Zawsze akt. dla snajp.</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_alwaysSimulateForSnipers_Description"> + <English>Always enables advanced ballistics when high power optics are used</English> + <Polish>Aktywuje zaawansowaną balistykę zawsze, kiedy używana jest optyka</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_disabledInFullAutoMod_DisplayName"> + <English>Disabled In FullAuto Mode</English> + <Polish>Wył. podczas ognia auto.</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_disabledInFullAutoMod_Description"> + <English>Disables the advanced ballistics during full auto fire</English> + <Polish>Dezaktywuje zaawansowaną balistykę podczas ognia automatycznego</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_onlyActiveForLocalPlayers_DisplayName"> + <English>Disabled For Non Local Players</English> + <Polish>Wyłącz dla nielok. graczy</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_onlyActiveForLocalPlayers_Description"> + <English>Disables the advanced ballistics for bullets coming from other players (enable this if you encounter frame drops during heavy firefights in multiplayer)</English> + <Polish>Dezaktywuje zaawansowaną balistykę dla pocisków pochodzących od innych graczy(aktywuj tą opcję jeżeli odczuwasz spadki FPS podczas sporych strzelanin w MP)</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_ammoTemperatureEnabled_DisplayName"> + <English>Enable Ammo Temperature Simulation</English> + <Polish>Symulacja temp. amunicji</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_ammoTemperatureEnabled_Description"> + <English>Muzzle velocity varies with ammo temperature</English> + <Polish>Prędkość wylotowa pocisku jest zależna od temperatury amunicji</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_barrelLengthInfluenceEnabled_DisplayName"> + <English>Enable Barrel Length Simulation</English> + <Polish>Symulacja długości lufy</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_barrelLengthInfluenceEnabled_Description"> + <English>Muzzle velocity varies with barrel length</English> + <Polish>Prędkość wylotowa pocisku jest zależna od długości lufy</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_bulletTraceEnabled_DisplayName"> + <English>Enable Bullet Trace Effect</English> + <Polish>Efekt smugi pocisku</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_bulletTraceEnabled_Description"> + <English>Enables a bullet trace effect to high caliber bullets (only visible when looking through high power optics)</English> + <Polish>Aktywuje efekt smugi pocisku dla pocisków wysokokalibrowych (widoczne tylko podczas patrzenia przez optykę)</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_simulationInterval_DisplayName"> + <English>Simulation Interval</English> + <Polish>Interwał symulacji</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_simulationInterval_Description"> + <English>Defines the interval between every calculation step</English> + <Polish>Określa interwał pomiędzy każdym krokiem kalkulacji</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_simulationRadius_DisplayName"> + <English>Simulation Radius</English> + <Polish>Zasięg symulacji</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_simulationRadius_Description"> + <English>Defines the radius around the player (in meters) at which advanced ballistics are applied to projectiles</English> + <Polish>Określa obszar naokoło gracza (w metrach), na którym zaawansowana balistyka jest aplikowana dla pocisków</Polish> + </Key> + <Key ID="STR_ACE_AdvancedBallistics_Description"> + <English></English> + <Polish>Moduł ten pozwala aktywować zaawansowaną balistykę biorącą przy obliczeniach trajektorii lotu pocisku pod uwagę takie rzeczy jak temperatura powietrza, ciśnienie atmosferyczne, wilgotność powietrza, siły Coriolisa i Eotvosa, grawitację a także broń z jakiej wykonywany jest strzał oraz rodzaj amunicji. Wszystko to sprowadza się na bardzo dokładne odwzorowanie balistyki.</Polish> + </Key> </Package> </Project> \ No newline at end of file diff --git a/addons/ballistics/CfgVehicles.hpp b/addons/ballistics/CfgVehicles.hpp index 82e7fef5e3..0ad697d91e 100644 --- a/addons/ballistics/CfgVehicles.hpp +++ b/addons/ballistics/CfgVehicles.hpp @@ -190,7 +190,7 @@ class CfgVehicles { class ACE_Box_Ammo: NATO_Box_Base { scope = 2; accuracy = 1000; - displayName = "[ACE] Ammo Supply Crate"; + displayName = "$STR_ACE_AmmoSupplyCrate_DisplayName"; model = "\A3\weapons_F\AmmoBoxes\AmmoBox_F"; author = "$STR_ACE_Common_ACETeam"; class TransportMagazines { diff --git a/addons/ballistics/stringtable.xml b/addons/ballistics/stringtable.xml index 7c6d9c85ad..85ac44b4de 100644 --- a/addons/ballistics/stringtable.xml +++ b/addons/ballistics/stringtable.xml @@ -1592,5 +1592,9 @@ <Portuguese>Calibre: 12.7x99mm (AMAX)<br/>Cartuchos: 5</Portuguese> <Hungarian>Kaliber: 12,7x99mm (AMAX)<br />Lövedékek: 5</Hungarian> </Key> + <Key ID="STR_ACE_AmmoSupplyCrate_DisplayName"> + <English>[ACE] Ammo Supply Crate</English> + <Polish>[ACE] Skrzynka z amunicją</Polish> + </Key> </Package> -</Project> \ No newline at end of file +</Project> diff --git a/addons/captives/CfgVehicles.hpp b/addons/captives/CfgVehicles.hpp index 1e2eb3f201..91c47824fd 100644 --- a/addons/captives/CfgVehicles.hpp +++ b/addons/captives/CfgVehicles.hpp @@ -161,7 +161,7 @@ class CfgVehicles { class GVAR(ModuleSurrender): Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Make Unit Surrender"; + displayName = "$STR_ACE_Captives_ModuleSurrender_DisplayName"; //Make Unit Surrender function = QUOTE(DFUNC(moduleSurrender)); scope = 2; //show in editor scopeCurator = 2; //show in zeus @@ -172,8 +172,8 @@ class CfgVehicles { functionPriority = 0; class Arguments {}; class ModuleDescription: ModuleDescription { - description = "Sync a unit to make them surrender.<br/>Source: ace_captives"; + description = "$STR_ACE_Captives_ModuleSurrender_Description"; //Sync a unit to make them surrender.<br/>Source: ace_captives sync[] = {"AnyAI"}; }; }; -}; +}; \ No newline at end of file diff --git a/addons/captives/stringtable.xml b/addons/captives/stringtable.xml index def173c55b..07cf780e19 100644 --- a/addons/captives/stringtable.xml +++ b/addons/captives/stringtable.xml @@ -193,5 +193,13 @@ <Hungarian>Semmi sincs az egér alatt</Hungarian> <Italian>Nessuna selezione</Italian> </Key> + <Key ID="STR_ACE_Captives_ModuleSurrender_DisplayName"> + <English>Make Unit Surrender</English> + <Polish>Poddaj się!</Polish> + </Key> + <Key ID="STR_ACE_Captives_ModuleSurrender_Description"> + <English>Sync a unit to make them surrender.<br />Source: ace_captives</English> + <Polish>Zsynchronizuj z jednostką aby sprawić by się poddała<br />Źródło: ace_captives</Polish> + </Key> </Package> </Project> diff --git a/addons/common/CfgVehicles.hpp b/addons/common/CfgVehicles.hpp index 5a00c038e7..70d84b376c 100644 --- a/addons/common/CfgVehicles.hpp +++ b/addons/common/CfgVehicles.hpp @@ -25,72 +25,82 @@ class CfgVehicles { // += needs a non inherited entry in that class, otherwise it simply overwrites //#include <DefaultItems.hpp> - class Module_F; - class ACE_ModuleCheckPBOs: Module_F { + class Logic; + class Module_F: Logic { + class ModuleDescription {}; + }; + class ACE_ModuleCheckPBOs: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Check PBOs"; + displayName = "$STR_ACE_Common_CheckPBO_DisplayName"; function = QFUNC(moduleCheckPBOs); scope = 2; isGlobal = 1; icon = QUOTE(PATHTOF(UI\Icon_Module_CheckPBO_ca.paa)); class Arguments { class Action { - displayName = "Action"; - description = "What to do with people who do not have the right PBOs?"; + displayName = "$STR_ACE_Common_CheckPBO_Action_DisplayName"; + description = "$STR_ACE_Common_CheckPBO_Action_Description"; class values { class WarnOnce { default = 1; - name = "Warn once"; + name = "$STR_ACE_Common_CheckPBO_Action_WarnOnce"; value = 0; }; class Warn { - name = "Warn (permanent)"; + name = "$STR_ACE_Common_CheckPBO_Action_WarnPerm"; value = 1; }; class Kick { - name = "Kick"; + name = "$STR_ACE_Common_CheckPBO_Action_Kick"; value = 2; }; }; }; class CheckAll { - displayName = "Check all addons"; - description = "Check all addons instead of only those of ACE?"; + displayName = "$STR_ACE_Common_CheckPBO_CheckAll_DisplayName"; + description = "$STR_ACE_Common_CheckPBO_CheckAll_Description"; typeName = "BOOL"; class values { class WarnOnce { default = 1; - name = "No"; + name = "$STR_ACE_Common_CheckPBO_CheckAll_No"; value = 0; }; class Warn { - name = "Yes"; + name = "$STR_ACE_Common_CheckPBO_CheckAll_Yes"; value = 1; }; }; }; class Whitelist { - displayName = "Whitelist"; - description = "What addons are allowed regardless?"; + displayName = "$STR_ACE_Common_CheckPBO_Whitelist_DisplayName"; + description = "$STR_ACE_Common_CheckPBO_Whitelist_Description"; typeName = "STRING"; class values { default = "[]"; }; }; }; + class ModuleDescription: ModuleDescription { + description = "$STR_ACE_Common_CheckPBO_Description"; + }; }; class ACE_ModuleLSDVehicles: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "LSD Vehicles"; + displayName = "$STR_ACE_Common_LSDVehicles_DisplayName"; function = "ACE_Common_fnc_moduleLSDVehicles"; scope = 2; icon = QUOTE(PATHTOF(UI\Icon_Module_LSD_ca.paa)); isGlobal = 1; class Arguments { }; + class ModuleDescription: ModuleDescription { + description = "$STR_ACE_Common_LSDVehicles_Description"; + sync[] = {"AnyVehicle"}; + }; }; class Box_NATO_Support_F; diff --git a/addons/common/config.cpp b/addons/common/config.cpp index 27647f8d00..3f1e5a6308 100644 --- a/addons/common/config.cpp +++ b/addons/common/config.cpp @@ -101,7 +101,7 @@ class ACE_Settings { isClientSettable = 1; displayName = "$STR_ACE_Common_SettingFeedbackIconsName"; description = "$STR_ACE_Common_SettingFeedbackIconsDesc"; - values[] = {"Hide", "Top right, downwards", "Top right, to the left", "Top left, downwards", "Top left, to the right"}; + values[] = {"$STR_ACE_Common_Hide", "$STR_ACE_Common_TopRightDown", "$STR_ACE_Common_TopRightLeft", "$STR_ACE_Common_TopLeftDown", "$STR_ACE_Common_TopLeftRight"}; }; class GVAR(SettingProgressBarLocation) { value = 0; @@ -110,7 +110,7 @@ class ACE_Settings { isClientSettable = 1; displayName = "$STR_ACE_Common_SettingProgressbarLocationName"; description = "$STR_ACE_Common_SettingProgressbarLocationDesc"; - values[] = {"Top", "Bottom"}; + values[] = {"$STR_ACE_Common_Top", "$STR_ACE_Common_Bottom"}; }; class GVAR(displayTextColor) { value[] = {0,0,0,0.1}; diff --git a/addons/common/stringtable.xml b/addons/common/stringtable.xml index 8d28704362..4ddc0112d8 100644 --- a/addons/common/stringtable.xml +++ b/addons/common/stringtable.xml @@ -470,5 +470,65 @@ <French>Une banane est un fruit qui, d'un point de vue botanique, fait partie du groupe des baies. Produite par plusieurs sortes de grandes plantes à fleurs herbacées du type Musa.</French> <Portuguese>A banana é uma fruta comestível, botanicamente uma baga, produzida por vários tipos de plantas herbáceas grandes do genero Musa.</Portuguese> </Key> + <Key ID="STR_ACE_Common_CheckPBO_DisplayName"> + <English>Check PBOs</English> + <Polish>Sprawdzaj PBO</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_Description"> + <English></English> + <Polish>Sprawdzaj spójność addonów z serwerem</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_Action_DisplayName"> + <English>Action</English> + <Polish>Akcja</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_Action_Description"> + <English>What to do with people who do not have the right PBOs?</English> + <Polish>Co zrobić z graczami, którzy nie mają właściwych PBO?</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_Action_WarnOnce"> + <English>Warn once</English> + <Polish>Ostrzeż raz</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_Action_WarnPerm"> + <English>Warn (permanent)</English> + <Polish>Ostrzeżenie (permanentne)</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_Action_Kick"> + <English>Kick</English> + <Polish>Kick</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_CheckAll_DisplayName"> + <English>Check all addons</English> + <Polish>Sprawdź wsz. addony</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_CheckAll_Description"> + <English>Check all addons instead of only those of ACE?</English> + <Polish>Sprawdzaj wszystkie addony czy tylko te z ACE?</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_CheckAll_No"> + <English>No</English> + <Polish>Tylko ACE</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_CheckAll_Yes"> + <English>Yes</English> + <Polish>Wszystkie</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_Whitelist_DisplayName"> + <English>Whitelist</English> + <Polish>Biała lista</Polish> + </Key> + <Key ID="STR_ACE_Common_CheckPBO_Whitelist_Description"> + <English>What addons are allowed regardless?</English> + <Polish>Jakie addony są dozwolone?</Polish> + </Key> + <Key ID="STR_ACE_Common_LSDVehicles_DisplayName"> + <English>LSD Vehicles</English> + <Polish>Pojazdy LSD</Polish> + </Key> + <Key ID="STR_ACE_Common_LSDVehicles_Description"> + <English>Adds LSD effect to synchronized vehicle</English> + <Polish>Dodaje efekt LSD pod zsynchronizowany pojazd</Polish> + </Key> </Package> </Project> diff --git a/addons/explosives/CfgModule.hpp b/addons/explosives/CfgModule.hpp index b4f7b65a83..50b59fc55d 100644 --- a/addons/explosives/CfgModule.hpp +++ b/addons/explosives/CfgModule.hpp @@ -1,44 +1,50 @@ -class Module_F; +class Logic; +class Module_F: Logic { + class ModuleDescription {}; +}; class ACE_ModuleExplosive: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Explosive System"; + displayName = "$STR_ACE_Explosive_Module_DisplayName"; function = QUOTE(FUNC(module)); scope = 2; isGlobal = 1; icon = PATHTOF(UI\Icon_Module_Explosives_ca.paa); class Arguments { class RequireSpecialist { - displayName = "Require specialists?"; - description = "Require explosive specialists to disable explosives? Default: No"; + displayName = "$STR_ACE_Explosive_RequireSpecialist_DisplayName"; + description = "$STR_ACE_Explosive_RequireSpecialist_Description"; typeName = "BOOL"; class values { class Yes { - name = "Yes"; + name = "$STR_ACE_Explosive_Yes"; value = 1; }; class No { default = 1; - name = "No"; + name = "$STR_ACE_Explosive_No"; value = 0; }; }; }; class PunishNonSpecialists { - displayName = "Punish non-specialists?"; - description = "Increase the time it takes to complete actions for non-specialists? Default: Yes"; + displayName = "$STR_ACE_Explosive_PunishNonSpecialists_DisplayName"; + description = "$STR_ACE_Explosive_PunishNonSpecialists_Description"; typeName = "BOOL"; class values { class Yes { default = 1; - name = "Yes"; + name = "$STR_ACE_Explosive_Yes"; value = 1; }; class No { - name = "No"; + name = "$STR_ACE_Explosive_No"; value = 0; }; }; }; }; -}; + class ModuleDescription: ModuleDescription { + description = "$STR_ACE_Explosive_Module_Description"; + }; +}; \ No newline at end of file diff --git a/addons/explosives/stringtable.xml b/addons/explosives/stringtable.xml index 9d885c236c..5eb5d28512 100644 --- a/addons/explosives/stringtable.xml +++ b/addons/explosives/stringtable.xml @@ -505,5 +505,37 @@ <Italian>Raccogli</Italian> <Portuguese>Pegar</Portuguese> </Key> + <Key ID="STR_ACE_Explosive_Module_DisplayName"> + <English>Explosive System</English> + <Polish>System ładunków wybuchowych</Polish> + </Key> + <Key ID="STR_ACE_Explosive_RequireSpecialist_DisplayName"> + <English>Require specialists?</English> + <Polish>Wymagaj specjalistów?</Polish> + </Key> + <Key ID="STR_ACE_Explosive_RequireSpecialist_Description"> + <English>Require explosive specialists to disable explosives? Default: No</English> + <Polish>Wymagać saperów do rozbrajania ładunków wybuchowych? Domyślnie: Nie</Polish> + </Key> + <Key ID="STR_ACE_Explosive_Yes"> + <English>Yes</English> + <Polish>Tak</Polish> + </Key> + <Key ID="STR_ACE_Explosive_No"> + <English>No</English> + <Polish>Nie</Polish> + </Key> + <Key ID="STR_ACE_Explosive_PunishNonSpecialists_DisplayName"> + <English>Punish non-specialists?</English> + <Polish>Karaj nie-specjalistów?</Polish> + </Key> + <Key ID="STR_ACE_Explosive_PunishNonSpecialists_Description"> + <English>Increase the time it takes to complete actions for non-specialists? Default: Yes</English> + <Polish>Zwiększyć ilość wymaganego czasu do ukończenia akcji dla nie-specjalistów? Domyślnie: Tak</Polish> + </Key> + <Key ID="STR_ACE_Explosive_Module_Description"> + <English></English> + <Polish>Moduł ten pozwala dostosować opcje związane z ładunkami wybuchowymi, ich podkładaniem oraz rozbrajaniem.</Polish> + </Key> </Package> </Project> diff --git a/addons/hearing/CfgVehicles.hpp b/addons/hearing/CfgVehicles.hpp index 6c77255384..d20d067981 100644 --- a/addons/hearing/CfgVehicles.hpp +++ b/addons/hearing/CfgVehicles.hpp @@ -98,21 +98,24 @@ class CfgVehicles { class ACE_ModuleHearing: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Hearing"; + displayName = "$STR_ACE_Hearing_Module_DisplayName"; //Hearing function = QFUNC(moduleHearing); scope = 2; isGlobal = 1; icon = PATHTOF(UI\Icon_Module_Hearing_ca.paa); class Arguments { class EnableCombatDeafness { - displayName = "Enable combat deafness?"; - description = "Enable combat deafness?"; + displayName = "$STR_ACE_Hearing_CombatDeafness_DisplayName"; //Enable combat deafness? + description = "$STR_ACE_Hearing_CombatDeafness_Description"; //Enable combat deafness? typeName = "BOOL"; class values { - class Yes { name = "Yes"; value = 1; default = 1; }; - class No { name = "No"; value = 0; }; + class Yes { name = "$STR_ACE_Hearing_CombatDeafness_Yes"; value = 1; default = 1; }; //yes + class No { name = "$STR_ACE_Hearing_CombatDeafness_No"; value = 0; }; //no }; }; + }; + class ModuleDescription { + description = "$STR_ACE_Hearing_Module_Description"; }; }; }; diff --git a/addons/hearing/stringtable.xml b/addons/hearing/stringtable.xml index e6f59604a3..e532768fd9 100644 --- a/addons/hearing/stringtable.xml +++ b/addons/hearing/stringtable.xml @@ -109,5 +109,29 @@ <Italian>Disabilita i fischi nelle orecchie</Italian> <Portuguese>Desabilitar zumbido de ouvidos</Portuguese> </Key> + <Key ID="STR_ACE_Hearing_Module_DisplayName"> + <English>Hearing</English> + <Polish>Słuch</Polish> + </Key> + <Key ID="STR_ACE_Hearing_CombatDeafness_DisplayName"> + <English>Enable combat deafness?</English> + <Polish>Wł. głuchotę bojową</Polish> + </Key> + <Key ID="STR_ACE_Hearing_CombatDeafness_Description"> + <English>Enable combat deafness?</English> + <Polish>Możliwość chwilowej utraty słuchu przy głośnych wystrzałach i jednoczesnym braku włożonych stoperów</Polish> + </Key> + <Key ID="STR_ACE_Hearing_CombatDeafness_Yes"> + <English>Yes</English> + <Polish>Tak</Polish> + </Key> + <Key ID="STR_ACE_Hearing_CombatDeafness_No"> + <English>No</English> + <Polish>Nie</Polish> + </Key> + <Key ID="STR_ACE_Hearing_Module_Description"> + <English></English> + <Polish>Głuchota bojowa pojawia się w momentach, kiedy stoimy w pobliżu broni wielkokalibrowej bez ochrony słuchu, lub np. podczas ostrzału artyleryjskiego. Moduł ten pozwala na włączenie lub wyłączenie tego efektu.</Polish> + </Key> </Package> </Project> diff --git a/addons/interaction/CfgVehicles.hpp b/addons/interaction/CfgVehicles.hpp index 5548311718..9968c490e1 100644 --- a/addons/interaction/CfgVehicles.hpp +++ b/addons/interaction/CfgVehicles.hpp @@ -4,21 +4,24 @@ class CfgVehicles { class ACE_ModuleInteraction: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Interaction System"; + displayName = "$STR_ACE_InteractionSystem_Module_DisplayName"; function = "ACE_Interaction_fnc_moduleInteraction"; scope = 2; isGlobal = 1; icon = PATHTOF(UI\Icon_Module_Interaction_ca.paa); class Arguments { class EnableTeamManagement { - displayName = "Enable Team Management"; - description = "Should players be allowed to use the Team Management Menu? Default: Yes"; + displayName = "$STR_ACE_InteractionSystem_EnableTeamManagement_DisplayName"; + description = "$STR_ACE_InteractionSystem_EnableTeamManagement_Description"; typeName = "BOOL"; class values { - class Yes { default = 1; name = "Yes"; value = 1;}; - class No { name = "No"; value = 0; }; + class Yes { default = 1; name = "$STR_ACE_InteractionSystem_EnableTeamManagement_Yes"; value = 1;}; + class No { name = "$STR_ACE_InteractionSystem_EnableTeamManagement_No"; value = 0; }; }; }; + }; + class ModuleDescription { + description = "$STR_ACE_InteractionSystem_Module_Description"; }; }; diff --git a/addons/interaction/stringtable.xml b/addons/interaction/stringtable.xml index 32a901507b..153b94a1d9 100644 --- a/addons/interaction/stringtable.xml +++ b/addons/interaction/stringtable.xml @@ -522,7 +522,7 @@ <German>Rot</German> <Spanish>Rojo</Spanish> <French>Rouge</French> - <Polish>Czerwony</Polish> + <Polish>Czerwonych</Polish> <Czech>Červený</Czech> <Russian>Красный</Russian> <Portuguese>Vermelha</Portuguese> @@ -534,7 +534,7 @@ <German>Grün</German> <Spanish>Verde</Spanish> <French>Vert</French> - <Polish>Zielony</Polish> + <Polish>Zielonych</Polish> <Czech>Zelený</Czech> <Russian>Зеленый</Russian> <Portuguese>Verde</Portuguese> @@ -546,7 +546,7 @@ <German>Blau</German> <Spanish>Azul</Spanish> <French>Bleu</French> - <Polish>Niebieski</Polish> + <Polish>Niebieskich</Polish> <Czech>Modrý</Czech> <Russian>Синий</Russian> <Portuguese>Azul</Portuguese> @@ -558,7 +558,7 @@ <German>Gelb</German> <Spanish>Amarillo</Spanish> <French>Jaune</French> - <Polish>Żółty</Polish> + <Polish>Żółtych</Polish> <Czech>Žlutý</Czech> <Russian>Жёлтый</Russian> <Portuguese>Amarela</Portuguese> @@ -666,7 +666,7 @@ <German>Du bist Gruppe %1 beigetreten</German> <Spanish>Te has unido al equipo %1</Spanish> <French>Tu as rejoint l'équipe %1</French> - <Polish>Dołączyłeś do drużyny %1</Polish> + <Polish>Dołączyłeś do %1</Polish> <Czech>Připojil ses do %1 týmu</Czech> <Russian>Вы присоединились к группе %1</Russian> <Portuguese>Você uniu-se à Equipe %1</Portuguese> @@ -793,5 +793,29 @@ <Italian>Passeggeri</Italian> <Portuguese>Passageiros</Portuguese> </Key> + <Key ID="STR_ACE_InteractionSystem_Module_DisplayName"> + <English>Interaction System</English> + <Polish>System interakcji</Polish> + </Key> + <Key ID="STR_ACE_InteractionSystem_EnableTeamManagement_DisplayName"> + <English>Enable Team Management</English> + <Polish>Wł. zarządzanie drużyną</Polish> + </Key> + <Key ID="STR_ACE_InteractionSystem_EnableTeamManagement_Description"> + <English>Should players be allowed to use the Team Management Menu? Default: Yes</English> + <Polish>Czy gracze mogą korzystać z menu zarządzania drużyną? Domyślnie: Tak</Polish> + </Key> + <Key ID="STR_ACE_InteractionSystem_EnableTeamManagement_Yes"> + <English>Yes</English> + <Polish>Tak</Polish> + </Key> + <Key ID="STR_ACE_InteractionSystem_EnableTeamManagement_No"> + <English>No</English> + <Polish>Nie</Polish> + </Key> + <Key ID="STR_ACE_InteractionSystem_Module_Description"> + <English></English> + <Polish>Na zarządzanie drużyną składa się: przydział kolorów dla członków drużyny, przejmowanie dowodzenia, dołączanie/opuszczanie drużyn.</Polish> + </Key> </Package> </Project> diff --git a/addons/map/CfgVehicles.hpp b/addons/map/CfgVehicles.hpp index 612cadb006..150ac23930 100644 --- a/addons/map/CfgVehicles.hpp +++ b/addons/map/CfgVehicles.hpp @@ -3,74 +3,80 @@ class CfgVehicles { class ACE_ModuleMap: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Map"; + displayName = "$STR_ACE_Map_Module_DisplayName"; function = QFUNC(moduleMap); scope = 2; isGlobal = 1; icon = PATHTOF(UI\Icon_Module_Map_ca.paa); class Arguments { class MapIllumination { - displayName = "Map illumination?"; - description = "Calculate dynamic map illumination based on light conditions?"; + displayName = "$STR_ACE_Map_MapIllumination_DisplayName"; + description = "$STR_ACE_Map_MapIllumination_Description"; typeName = "BOOL"; class values { - class Yes { name = "Yes"; value = 1; default = 1; }; - class No { name = "No"; value = 0; }; + class Yes { name = "$STR_ACE_Map_Yes"; value = 1; default = 1; }; + class No { name = "$STR_ACE_Map_No"; value = 0; }; }; }; class MapShake { - displayName = "Map shake?"; - description = "Make map shake when walking?"; + displayName = "$STR_ACE_Map_MapShake_DisplayName"; + description = "$STR_ACE_Map_MapShake_Description"; typeName = "BOOL"; class values { - class Yes { name = "Yes"; value = 1; default = 1;}; - class No { name = "No"; value = 0; }; + class Yes { name = "$STR_ACE_Map_Yes"; value = 1; default = 1;}; + class No { name = "$STR_ACE_Map_No"; value = 0; }; }; }; class MapLimitZoom { - displayName = "Limit map zoom?"; - description = "Limit the amount of zoom available for the map?"; + displayName = "$STR_ACE_Map_MapLimitZoom_DisplayName"; + description = "$STR_ACE_Map_MapLimitZoom_Description"; typeName = "BOOL"; class values { - class Yes { name = "Yes"; value = 1; }; - class No { name = "No"; value = 0; default = 1;}; + class Yes { name = "$STR_ACE_Map_Yes"; value = 1; }; + class No { name = "$STR_ACE_Map_No"; value = 0; default = 1;}; }; }; class MapShowCursorCoordinates { - displayName = "Show cursor coordinates?"; - description = "Show the grid coordinates on the mouse pointer?"; + displayName = "$STR_ACE_Map_MapShowCursorCoordinates_DisplayName"; + description = "$STR_ACE_Map_MapShowCursorCoordinates_Description"; typeName = "BOOL"; class values { - class Yes { name = "Yes"; value = 1; }; - class No { name = "No"; value = 0; default = 1;}; + class Yes { name = "$STR_ACE_Map_Yes"; value = 1; }; + class No { name = "$STR_ACE_Map_No"; value = 0; default = 1;}; }; }; + }; + class ModuleDescription { + description = "$STR_ACE_Map_Module_Description"; }; }; class ACE_ModuleBlueForceTracking: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Blue Force Tracking"; + displayName = "$STR_ACE_Map_BFT_Module_DisplayName"; function = QFUNC(blueForceTrackingModule); scope = 2; isGlobal = 1; icon = PATHTOF(UI\Icon_Module_BFTracking_ca.paa); class Arguments { class Interval { - displayName = "Interval"; - description = "How often the markers should be refreshed (in seconds)"; + displayName = "$STR_ACE_Map_BFT_Interval_DisplayName"; + description = "$STR_ACE_Map_BFT_Interval_Description"; defaultValue = 1; }; class HideAiGroups { - displayName = "Hide AI groups?"; - description = "Hide markers for 'AI only' groups?"; + displayName = "$STR_ACE_Map_BFT_HideAiGroups_DisplayName"; + description = "$STR_ACE_Map_BFT_HideAiGroups_Description"; typeName = "BOOL"; class values { - class Yes { name = "Yes"; value = 1; }; - class No { name = "No"; value = 0; default = 1; }; + class Yes { name = "$STR_ACE_Map_Yes"; value = 1; }; + class No { name = "$STR_ACE_Map_No"; value = 0; default = 1; }; }; }; + }; + class ModuleDescription { + description = "$STR_ACE_Map_BFT_Module_Description"; }; }; -}; +}; \ No newline at end of file diff --git a/addons/map/stringtable.xml b/addons/map/stringtable.xml index 4423bbcfb4..0c25016653 100644 --- a/addons/map/stringtable.xml +++ b/addons/map/stringtable.xml @@ -1,6 +1,77 @@ <?xml version="1.0" encoding="utf-8"?> <Project name="ACE"> - <Package name="Map"> - - </Package> + <Package name="Map"> + <Key ID="STR_ACE_Map_Module_DisplayName"> + <English>Map</English> + <Polish>Mapa</Polish> + </Key> + <Key ID="STR_ACE_Map_MapIllumination_DisplayName"> + <English>Map illumination?</English> + <Polish>Oświetlenie mapy</Polish> + </Key> + <Key ID="STR_ACE_Map_MapIllumination_Description"> + <English>Calculate dynamic map illumination based on light conditions?</English> + <Polish>Oblicza dynamiczne oświetlenie mapy bazujące na warunkach oświetleniowych</Polish> + </Key> + <Key ID="STR_ACE_Map_Yes"> + <English>Yes</English> + <Polish>Tak</Polish> + </Key> + <Key ID="STR_ACE_Map_No"> + <English>No</English> + <Polish>Nie</Polish> + </Key> + <Key ID="STR_ACE_Map_MapShake_DisplayName"> + <English>Map shake?</English> + <Polish>Drżenie mapy</Polish> + </Key> + <Key ID="STR_ACE_Map_MapShake_Description"> + <English>Make map shake when walking?</English> + <Polish>Ekran mapy drży podczas ruchu</Polish> + </Key> + <Key ID="STR_ACE_Map_MapLimitZoom_DisplayName"> + <English>Limit map zoom?</English> + <Polish>Ograniczony zoom</Polish> + </Key> + <Key ID="STR_ACE_Map_MapLimitZoom_Description"> + <English>Limit the amount of zoom available for the map?</English> + <Polish>Ogranicza maksymalny stopień przybliżenia mapy</Polish> + </Key> + <Key ID="STR_ACE_Map_MapShowCursorCoordinates_DisplayName"> + <English>Show cursor coordinates?</English> + <Polish>Koordynaty pod kursorem</Polish> + </Key> + <Key ID="STR_ACE_Map_MapShowCursorCoordinates_Description"> + <English>Show the grid coordinates on the mouse pointer?</English> + <Polish>Pokazuje pod kursorem koordynaty wskazanego kwadratu mapy</Polish> + </Key> + <Key ID="STR_ACE_Map_Module_Description"> + <English></English> + <Polish>Moduł ten pozwala dostosować opcje widoku ekranu mapy.</Polish> + </Key> + <Key ID="STR_ACE_Map_BFT_Module_DisplayName"> + <English>Blue Force Tracking</English> + <Polish>Blue Force Tracking</Polish> + </Key> + <Key ID="STR_ACE_Map_BFT_Interval_DisplayName"> + <English>Interval</English> + <Polish>Interwał</Polish> + </Key> + <Key ID="STR_ACE_Map_BFT_Interval_Description"> + <English>How often the markers should be refreshed (in seconds)</English> + <Polish>Jak często markery powinny być odświeżane (w sekundach)</Polish> + </Key> + <Key ID="STR_ACE_Map_BFT_HideAiGroups_DisplayName"> + <English>Hide AI groups?</English> + <Polish>Ukryj grupy AI</Polish> + </Key> + <Key ID="STR_ACE_Map_BFT_HideAiGroups_Description"> + <English>Hide markers for 'AI only' groups?</English> + <Polish>Ukrywa markery dla grup złożonych tylko z AI</Polish> + </Key> + <Key ID="STR_ACE_Map_BFT_Module_Description"> + <English></English> + <Polish>Pozwala śledzić na mapie pozycje sojuszniczych jednostek za pomocą markerów BFT.</Polish> + </Key> + </Package> </Project> \ No newline at end of file diff --git a/addons/medical/CfgFactionClasses.hpp b/addons/medical/CfgFactionClasses.hpp index e98b1f84ec..67e3404e91 100644 --- a/addons/medical/CfgFactionClasses.hpp +++ b/addons/medical/CfgFactionClasses.hpp @@ -1,6 +1,6 @@ class CfgFactionClasses { class NO_CATEGORY; class ADDON: NO_CATEGORY { - displayName = "ACE Medical"; + displayName = "$STR_ACE_Medical_Category_DisplayName"; }; }; diff --git a/addons/medical/CfgVehicles.hpp b/addons/medical/CfgVehicles.hpp index 4054a2ee1e..aac43de0ed 100644 --- a/addons/medical/CfgVehicles.hpp +++ b/addons/medical/CfgVehicles.hpp @@ -12,7 +12,7 @@ class CfgVehicles { // TODO localization for all the modules class ACE_moduleMedicalSettings: ACE_Module { scope = 2; - displayName = "Medical Settings [ACE]"; + displayName = "$STR_ACE_MedicalSettings_Module_DisplayName"; icon = QUOTE(PATHTOF(UI\Icon_Module_Medical_ca.paa)); category = "ACE_medical"; function = QUOTE(DFUNC(moduleMedicalSettings)); @@ -22,78 +22,78 @@ class CfgVehicles { author = "$STR_ACE_Common_ACETeam"; class Arguments { class level { - displayName = "Medical Level"; - description = "What is the medical simulation level?"; + displayName = "$STR_ACE_MedicalSettings_level_DisplayName"; + description = "$STR_ACE_MedicalSettings_level_Description"; typeName = "NUMBER"; class values { class normal { - name = "Basic"; + name = "$STR_ACE_MedicalSettings_basic"; value = 1; default = 1; }; class full { - name = "Advanced"; + name = "$STR_ACE_MedicalSettings_advanced"; value = 2; }; }; }; class medicSetting { - displayName = "Medics setting"; - description = "What is the level of detail prefered for medics?"; + displayName = "$STR_ACE_MedicalSettings_medicSetting_DisplayName"; + description = "$STR_ACE_MedicalSettings_medicSetting_Description"; typeName = "NUMBER"; class values { class disable { - name = "Disable medics"; + name = "$STR_ACE_MedicalSettings_medicSetting_disable"; value = 0; }; class normal { - name = "Normal"; + name = "$STR_ACE_MedicalSettings_basic"; value = 1; default = 1; }; class full { - name = "Advanced"; + name = "$STR_ACE_MedicalSettings_advanced"; value = 2; }; }; }; class allowLitterCreation { - displayName = "Enable Litter"; - description = "Enable litter being created upon treatment"; + displayName = "$STR_ACE_MedicalSettings_allowLitterCreation_DisplayName"; + description = "$STR_ACE_MedicalSettings_allowLitterCreation_Description"; typeName = "BOOL"; defaultValue = 1; }; class litterCleanUpDelay { - displayName = "Life time of litter objects"; - description = "How long should litter objects stay? In seconds. -1 is forever."; + displayName = "$STR_ACE_MedicalSettings_litterCleanUpDelay_DisplayName"; + description = "$STR_ACE_MedicalSettings_litterCleanUpDelay_Description"; typeName = "NUMBER"; defaultValue = 1800; }; class enableScreams { - displayName = "Enable Screams"; - description = "Enable screaming by injuried units"; + displayName = "$STR_ACE_MedicalSettings_enableScreams_DisplayName"; + description = "$STR_ACE_MedicalSettings_enableScreams_Description"; typeName = "BOOL"; defaultValue = 1; }; class playerDamageThreshold { - displayName = "Player Damage"; - description = "What is the damage a player can take before being killed?"; + displayName = "$STR_ACE_MedicalSettings_playerDamageThreshold_DisplayName"; + description = "$STR_ACE_MedicalSettings_playerDamageThreshold_Description"; typeName = "NUMBER"; defaultValue = 1; }; class AIDamageThreshold { - displayName = "AI Damage"; - description = "What is the damage an AI can take before being killed?"; + displayName = "$STR_ACE_MedicalSettings_AIDamageThreshold_DisplayName"; + description = "$STR_ACE_MedicalSettings_AIDamageThreshold_Description"; typeName = "NUMBER"; defaultValue = 1; }; class enableUnconsciousnessAI { - displayName = "AI Unconsciousness"; - description = "Allow AI to go unconscious"; + displayName = "$STR_ACE_MedicalSettings_enableUnconsciousnessAI_DisplayName"; + description = "$STR_ACE_MedicalSettings_enableUnconsciousnessAI_Description"; typeName = "NUMBER"; class values { class disable { - name = "Disabled"; + name = "$STR_ACE_Medical_disabled"; value = 0; }; class normal { @@ -102,45 +102,45 @@ class CfgVehicles { default = 1; }; class full { - name = "Enabled"; + name = "$STR_ACE_Medical_enabled"; value = 2; }; }; }; class preventInstaDeath { - displayName = "Prevent instant death"; - description = "Have a unit move to unconscious instead of death"; + displayName = "$STR_ACE_MedicalSettings_preventInstaDeath_DisplayName"; + description = "$STR_ACE_MedicalSettings_preventInstaDeath_Description"; typeName = "BOOL"; defaultValue = 0; }; class bleedingCoefficient { - displayName = "Bleeding coefficient"; - description = "Coefficient to modify the bleeding speed"; + displayName = "$STR_ACE_MedicalSettings_bleedingCoefficient_DisplayName"; + description = "$STR_ACE_MedicalSettings_bleedingCoefficient_Description"; typeName = "NUMBER"; defaultValue = 1; }; class painCoefficient { - displayName = "Pain coefficient"; - description = "Coefficient to modify the pain intensity"; + displayName = "$STR_ACE_MedicalSettings_painCoefficient_DisplayName"; + description = "$STR_ACE_MedicalSettings_painCoefficient_Description"; typeName = "NUMBER"; defaultValue = 1; }; class keepLocalSettingsSynced { - displayName = "Sync status"; - description = "Keep unit status synced. Recommended on."; + displayName = "$STR_ACE_MedicalSettings_keepLocalSettingsSynced_DisplayName"; + description = "$STR_ACE_MedicalSettings_keepLocalSettingsSynced_Description"; typeName = "BOOL"; defaultValue = 1; }; }; class ModuleDescription { - description = "Provides a medical system for both players and AI."; + description = "$STR_ACE_MedicalSettings_Module_Description"; sync[] = {}; }; }; class ACE_moduleAdvancedMedicalSettings: ACE_Module { scope = 2; - displayName = "Advanced Medical Settings [ACE]"; + displayName = "$STR_ACE_AdvancedMedicalSettings_Module_DisplayName"; icon = QUOTE(PATHTOF(UI\Icon_Module_Medical_ca.paa)); category = "ACE_medical"; function = QUOTE(FUNC(moduleAdvancedMedicalSettings)); @@ -151,80 +151,80 @@ class CfgVehicles { author = "$STR_ACE_Common_ACETeam"; class Arguments { class enableFor { - displayName = "Enabled for"; - description = "Select what units the advanced medical system will be enabled for"; + displayName = "$STR_ACE_AdvancedMedicalSettings_enableFor_DisplayName"; + description = "$STR_ACE_AdvancedMedicalSettings_enableFor_Description"; typeName = "NUMBER"; class values { class playableUnits { - name = "Players only."; + name = "$STR_ACE_Medical_playeronly"; value = 0; default = 1; }; class playableUnitsAndAI { - name = "Players and AI"; + name = "$STR_ACE_Medical_playersandai"; value = 1; }; }; }; class enableAdvancedWounds { - displayName = "Enable Advanced wounds"; - description = "Allow reopening of bandaged wounds?"; + displayName = "$STR_ACE_AdvancedMedicalSettings_enableAdvancedWounds_DisplayName"; + description = "$STR_ACE_AdvancedMedicalSettings_enableAdvancedWounds_Description"; typeName = "BOOL"; defaultValue = 0; }; class enableVehicleCrashes { - displayName = "Vehicle Crashes"; - description = "Do units take damage from a vehicle crash?"; + displayName = "$STR_ACE_AdvancedMedicalSettings_enableVehicleCrashes_DisplayName"; + description = "$STR_ACE_AdvancedMedicalSettings_enableVehicleCrashes_Description"; typeName = "BOOL"; defaultValue = 1; }; class medicSetting_PAK { - displayName = "Allow PAK"; - description = "Who can use the PAK for full heal?"; + displayName = "$STR_ACE_AdvancedMedicalSettings_medicSetting_PAK_DisplayName"; + description = "$STR_ACE_AdvancedMedicalSettings_medicSetting_PAK_Description"; typeName = "NUMBER"; class values { - class anyone { name = "Anyone"; value = 0; }; - class Medic { name = "Medics only"; value = 1; default = 1; }; - class Special { name = "Doctors only"; value = 2; }; + class anyone { name = "$STR_ACE_AdvancedMedicalSettings_anyone"; value = 0; }; + class Medic { name = "$STR_ACE_AdvancedMedicalSettings_Medic"; value = 1; default = 1; }; + class Special { name = "$STR_ACE_AdvancedMedicalSettings_Special"; value = 2; }; }; }; class consumeItem_PAK { - displayName = "Remove PAK on use"; - description = "Should PAK be removed on usage?"; + displayName = "$STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_DisplayName"; + description = "$STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_Description"; typeName = "NUMBER"; class values { - class keep { name = "No"; value = 0; }; - class remove { name = "Yes"; value = 1; default = 1; }; + class keep { name = "$STR_ACE_Medical_No"; value = 0; }; + class remove { name = "$STR_ACE_Medical_Yes"; value = 1; default = 1; }; }; }; class useLocation_PAK { - displayName = "Locations PAK"; - description = "Where can the personal aid kit be used?"; + displayName = "$STR_ACE_AdvancedMedicalSettings_useLocation_PAK_DisplayName"; + description = "$STR_ACE_AdvancedMedicalSettings_useLocation_PAK_Description"; typeName = "NUMBER"; class values { - class anywhere { name = "Anywhere"; value = 0; }; - class vehicle { name = "Medical Vehicles"; value = 1; }; - class facility { name = "Medical facility"; value = 2; }; - class vehicleAndFacility { name = "Vehicles & facility"; value = 3; default = 1; }; - class disabled { name = "Disabled"; value = 4;}; + class anywhere { name = "$STR_ACE_AdvancedMedicalSettings_anywhere"; value = 0; }; + class vehicle { name = "$STR_ACE_AdvancedMedicalSettings_vehicle"; value = 1; }; + class facility { name = "$STR_ACE_AdvancedMedicalSettings_facility"; value = 2; }; + class vehicleAndFacility { name = "$STR_ACE_AdvancedMedicalSettings_vehicleAndFacility"; value = 3; default = 1; }; + class disabled { name = "$STR_ACE_AdvancedMedicalSettings_disabled"; value = 4;}; }; }; class medicSetting_SurgicalKit: medicSetting_PAK { - displayName = "Allow Surgical kit (Adv)"; - description = "Who can use the surgical kit?"; + displayName = "$STR_ACE_AdvancedMedicalSettings_medicSetting_SurgicalKit_DisplayName"; + description = "$STR_ACE_AdvancedMedicalSettings_medicSetting_SurgicalKit_Description"; }; class consumeItem_SurgicalKit: consumeItem_PAK { - displayName = "Remove Surgical kit (Adv)"; - description = "Should Surgical kit be removed on usage?"; + displayName = "$STR_ACE_AdvancedMedicalSettings_consumeItem_SurgicalKit_DisplayName"; + description = "$STR_ACE_AdvancedMedicalSettings_consumeItem_SurgicalKit_Description"; }; class useLocation_SurgicalKit: useLocation_PAK { - displayName = "Locations Surgical kit (Adv)"; - description = "Where can the Surgical kit be used?"; + displayName = "$STR_ACE_AdvancedMedicalSettings_useLocation_SurgicalKit_DisplayName"; + description = "$STR_ACE_AdvancedMedicalSettings_useLocation_SurgicalKit_Description"; }; }; class ModuleDescription { - description = "Configure the treatment settings from ACE Medical"; + description = "$STR_ACE_AdvancedMedicalSettings_Module_Description"; sync[] = {}; }; }; @@ -232,7 +232,7 @@ class CfgVehicles { class ACE_moduleReviveSettings: ACE_Module { scope = 2; - displayName = "Revive Settings [ACE]"; + displayName = "$STR_ACE_ReviveSettings_Module_DisplayName"; icon = QUOTE(PATHTOF(UI\Icon_Module_Medical_ca.paa)); category = "ACE_medical"; function = QUOTE(DFUNC(moduleReviveSettings)); @@ -242,37 +242,37 @@ class CfgVehicles { author = "$STR_ACE_Common_ACETeam"; class Arguments { class enableRevive { - displayName = "Enable Revive"; - description = "Enable a basic revive system"; + displayName = "$STR_ACE_ReviveSettings_enableRevive_DisplayName"; + description = "$STR_ACE_ReviveSettings_enableRevive_Description"; typeName = "NUMBER"; defaultValue = 0; class values { - class disable { name = "Disabled"; value = 0; default = 1;}; - class playerOnly { name = "Player only"; value = 1; }; - class playerAndAI { name = "Player & AI"; value = 2; }; + class disable { name = "$STR_ACE_Medical_disabled"; value = 0; default = 1;}; + class playerOnly { name = "$STR_ACE_Medical_playeronly"; value = 1; }; + class playerAndAI { name = "$STR_ACE_Medical_playersandai"; value = 2; }; }; }; class maxReviveTime { - displayName = "Max Revive time"; - description = "Max amount of seconds a unit can spend in revive state"; + displayName = "$STR_ACE_ReviveSettings_maxReviveTime_DisplayName"; + description = "$STR_ACE_ReviveSettings_maxReviveTime_Description"; typeName = "NUMBER"; defaultValue = 120; }; class amountOfReviveLives { - displayName = "Max Revive lives"; - description = "Max amount of lives a unit. 0 or -1 is disabled."; + displayName = "$STR_ACE_ReviveSettings_amountOfReviveLives_DisplayName"; + description = "$STR_ACE_ReviveSettings_amountOfReviveLives_Description"; typeName = "NUMBER"; defaultValue = -1; }; }; class ModuleDescription { - description = "Provides a medical system for both players and AI."; + description = "$STR_ACE_ReviveSettings_Module_Description"; sync[] = {}; }; }; class ACE_moduleAssignMedicRoles: Module_F { scope = 2; - displayName = "Set Medic Class [ACE]"; + displayName = "$STR_ACE_AssignMedicRoles_Module_DisplayName"; icon = QUOTE(PATHTOF(UI\Icon_Module_Medical_ca.paa)); category = "ACE_medical"; function = QUOTE(FUNC(moduleAssignMedicRoles)); @@ -283,41 +283,41 @@ class CfgVehicles { author = "$STR_ACE_Common_ACETeam"; class Arguments { class EnableList { - displayName = "List"; - description = "List of unit names that will be classified as medic, separated by commas."; + displayName = "$STR_ACE_AssignMedicRoles_EnableList_DisplayName"; + description = "$STR_ACE_AssignMedicRoles_EnableList_Description"; defaultValue = ""; typeName = "STRING"; }; class role { - displayName = "Is Medic"; - description = "Medics allow for more advanced treatment in case of Advanced Medic roles enabled"; + displayName = "$STR_ACE_AssignMedicRoles_role_DisplayName"; + description = "$STR_ACE_AssignMedicRoles_role_Description"; typeName = "NUMBER"; class values { class none { - name = "None"; + name = "$STR_ACE_AssignMedicRoles_role_none"; value = 0; }; class medic { - name = "Regular medic"; + name = "$STR_ACE_AssignMedicRoles_role_medic"; value = 1; default = 1; }; class doctor { - name = "Doctor (Only Advanced Medics)"; + name = "$STR_ACE_AssignMedicRoles_role_doctor"; value = 2; }; }; }; }; class ModuleDescription { - description = "Assigns the ACE medic class to a unit"; + description = "$STR_ACE_AssignMedicRoles_Module_Description"; sync[] = {}; }; }; class ACE_moduleAssignMedicVehicle: Module_F { scope = 2; - displayName = "Set Medical Vehicle [ACE]"; + displayName = "$STR_ACE_AssignMedicVehicle_Module_DisplayName"; icon = QUOTE(PATHTOF(UI\Icon_Module_Medical_ca.paa)); category = "ACE_medical"; function = QUOTE(FUNC(moduleAssignMedicalVehicle)); @@ -328,22 +328,22 @@ class CfgVehicles { author = "$STR_ACE_Common_ACETeam"; class Arguments { class EnableList { - displayName = "List"; - description = "List of vehicles that will be classified as medical vehicle, separated by commas."; + displayName = "$STR_ACE_AssignMedicVehicle_EnableList_DisplayName"; + description = "$STR_ACE_AssignMedicVehicle_EnableList_Description"; defaultValue = ""; typeName = "STRING"; }; class enabled { - displayName = "Is Medical Vehicle"; - description = "Whatever or not the objects in the list will be a medical vehicle."; + displayName = "$STR_ACE_AssignMedicVehicle_enabled_DisplayName"; + description = "$STR_ACE_AssignMedicVehicle_enabled_Description"; typeName = "NUMBER"; class values { class none { - name = "No"; + name = "$STR_ACE_Medical_No"; value = 0; }; class medic { - name = "Yes"; + name = "$STR_ACE_Medical_Yes"; value = 1; default = 1; }; @@ -351,13 +351,13 @@ class CfgVehicles { }; }; class ModuleDescription { - description = "Assigns the ACE medic class to a unit"; + description = "$STR_ACE_AssignMedicVehicle_Module_Description"; sync[] = {}; }; }; class ACE_moduleAssignMedicalFacility: Module_F { scope = 2; - displayName = "Set Medical Facility [ACE]"; + displayName = "$STR_ACE_AssignMedicalFacility_Module_DisplayName"; icon = QUOTE(PATHTOF(UI\Icon_Module_Medical_ca.paa)); category = "ACE_medical"; function = QUOTE(FUNC(moduleAssignMedicalFacility)); @@ -368,13 +368,13 @@ class CfgVehicles { author = "$STR_ACE_Common_ACETeam"; class Arguments { class enabled { - displayName = "Is Medical Facility"; - description = "Registers an object as a medical facility for CMS"; + displayName = "$STR_ACE_AssignMedicalFacility_enabled_DisplayName"; + description = "$STR_ACE_AssignMedicalFacility_enabled_Description"; typeName = "BOOL"; }; }; class ModuleDescription { - description = "Defines an object as a medical facility for CMS. This allows for more advanced treatments. Can be used on buildings and vehicles. "; + description = "$STR_ACE_AssignMedicalFacility_Module_Description"; sync[] = {}; }; }; @@ -897,7 +897,7 @@ class CfgVehicles { class ACE_medicalSupplyCrate: NATO_Box_Base { scope = 2; accuracy = 1000; - displayName = "[ACE] Medical Supply Crate (Basic)"; + displayName = "$STR_ACE_medicalSupplyCrate"; model = PATHTOF(data\ace_medcrate.p3d); author = "$STR_ACE_Common_ACETeam"; class TransportItems { @@ -932,7 +932,7 @@ class CfgVehicles { }; }; class ACE_medicalSupplyCrate_advanced: ACE_medicalSupplyCrate { - displayName = "[ACE] Medical Supply Crate (Advanced)"; + displayName = "$STR_ACE_medicalSupplyCrate_advanced"; class TransportItems { class ACE_fieldDressing { name = "ACE_fieldDressing"; @@ -1017,3 +1017,24 @@ class CfgVehicles { }; }; }; + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/medical/config.cpp b/addons/medical/config.cpp index 566de29f91..cd0fe0e66c 100644 --- a/addons/medical/config.cpp +++ b/addons/medical/config.cpp @@ -6,7 +6,7 @@ class CfgPatches { weapons[] = {"ACE_fieldDressing", "ACE_packingBandage", "ACE_elasticBandage", "ACE_tourniquet", "ACE_morphine", "ACE_atropine", "ACE_epinephrine", "ACE_plasmaIV", "ACE_plasmaIV_500", "ACE_plasmaIV_250", "ACE_bloodIV", "ACE_bloodIV_500", "ACE_bloodIV_250", "ACE_salineIV", "ACE_salineIV_500", "ACE_salineIV_250", "ACE_quikclot", "ACE_personalAidKit", "ACE_surgicalKit", "ACE_bodyBag"}; requiredVersion = REQUIRED_VERSION; requiredAddons[] = {"ace_interaction","ace_modules", "ace_apl"}; - author[] = {"Glowbal", "KoffienFlummi"}; + author[] = {"Glowbal", "KoffeinFlummi"}; authorUrl = ""; VERSION_CONFIG; }; diff --git a/addons/medical/functions/fnc_actionCheckPulseLocal.sqf b/addons/medical/functions/fnc_actionCheckPulseLocal.sqf index 85e9bee828..b283068ec7 100644 --- a/addons/medical/functions/fnc_actionCheckPulseLocal.sqf +++ b/addons/medical/functions/fnc_actionCheckPulseLocal.sqf @@ -24,7 +24,7 @@ if (!alive _unit) then { _heartRate = 0; }; _heartRateOutput = "STR_ACE_Medical_Check_Pulse_Output_5"; -_logOutPut = "No heart rate"; +_logOutPut = localize "STR_ACE_Medical_Check_Pulse_None"; if (_heartRate > 1.0) then { if ([_caller] call FUNC(isMedic)) then { diff --git a/addons/medical/stringtable.xml b/addons/medical/stringtable.xml index 215d9ae766..50f3d67110 100644 --- a/addons/medical/stringtable.xml +++ b/addons/medical/stringtable.xml @@ -1290,7 +1290,7 @@ <French>Trousse chirurgicale</French> <Russian>Хирургический набор</Russian> <Spanish>Kit quirúrgico</Spanish> - <Polish>Zestaw do szycia ran</Polish> + <Polish>Zestaw chirurgiczny</Polish> <German>Operationsset</German> <Hungarian>Sebészeti készlet</Hungarian> <Italian>Kit chirurgico</Italian> @@ -1585,6 +1585,10 @@ <Czech>%1 zkontroloval srdeční tep: %2</Czech> <Portuguese>%1 verificou a frequência cardíaca: %2</Portuguese> </Key> + <Key ID="STR_ACE_Medical_Check_Pulse_None"> + <English>None</English> + <Polish>Brak</Polish> + </Key> <Key ID="STR_ACE_Medical_Check_Pulse_Weak"> <English>Weak</English> <German>Schwach</German> @@ -2701,5 +2705,377 @@ <Russian>Снятие жгута ...</Russian> <Italian>Togliendo il laccio emostatico ...</Italian> </Key> + <Key ID="STR_ACE_Medical_Category_DisplayName"> + <English>ACE Medical</English> + <Polish>ACE Opcje medyczne</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_Module_DisplayName"> + <English>Medical Settings [ACE]</English> + <Polish>Ustawienia medyczne [ACE]</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_level_DisplayName"> + <English>Medical Level</English> + <Polish>Poziom medyczny</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_level_Description"> + <English>What is the medical simulation level?</English> + <Polish>Jaki jest poziom symulacji medycznej?</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_basic"> + <English>Basic</English> + <Polish>Podstawowy</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_advanced"> + <English>Advanced</English> + <Polish>Zaawansowany</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_medicSetting_DisplayName"> + <English>Medics setting</English> + <Polish>Poziom medyków</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_medicSetting_Description"> + <English>What is the level of detail prefered for medics?</English> + <Polish>Jaki jest poziom detali medycznych wyświetlanych dla medyków?</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_medicSetting_disable"> + <English>Disable medics</English> + <Polish>Wyłącz medyków</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_allowLitterCreation_DisplayName"> + <English>Enable Litter</English> + <Polish>Aktywuj odpadki</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_allowLitterCreation_Description"> + <English>Enable litter being created upon treatment</English> + <Polish>Twórz odpadki medyczne podczas leczenia</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_litterCleanUpDelay_DisplayName"> + <English>Life time of litter objects</English> + <Polish>Długość życia odpadków</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_litterCleanUpDelay_Description"> + <English>How long should litter objects stay? In seconds. -1 is forever.</English> + <Polish>Ile czasu musi upłynąć, aby odpadki zaczęły znikać? W sekundach. -1 dla nieskończoności.</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_enableScreams_DisplayName"> + <English>Enable Screams</English> + <Polish>Aktywuj wrzaski</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_enableScreams_Description"> + <English>Enable screaming by injuried units</English> + <Polish>Aktywuj wrzeszczenie z bólu przez ranne jednostki</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_playerDamageThreshold_DisplayName"> + <English>Player Damage</English> + <Polish>Próg obrażeń graczy</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_playerDamageThreshold_Description"> + <English>What is the damage a player can take before being killed?</English> + <Polish>Jaki jest próg obrażeń, jakie gracz może otrzymać zanim zostanie zabity?</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_AIDamageThreshold_DisplayName"> + <English>AI Damage</English> + <Polish>Próg obrażeń AI</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_AIDamageThreshold_Description"> + <English>What is the damage an AI can take before being killed?</English> + <Polish>Jaki jest próg obrażeń, jakie AI może otrzymać zanim zostanie zabite?</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_enableUnconsciousnessAI_DisplayName"> + <English>AI Unconsciousness</English> + <Polish>Nieprzytomność AI</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_enableUnconsciousnessAI_Description"> + <English>Allow AI to go unconscious</English> + <Polish>Czy AI może być nieprzytomne od odniesionych obrażeń?</Polish> + </Key> + <Key ID="STR_ACE_Medical_disabled"> + <English>Disabled</English> + <Polish>Wyłączone</Polish> + </Key> + <Key ID="STR_ACE_Medical_enabled"> + <English>Enabled</English> + <Polish>Włączone</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_preventInstaDeath_DisplayName"> + <English>Prevent instant death</English> + <Polish>Wył. natychmiast. śmierć</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_preventInstaDeath_Description"> + <English>Have a unit move to unconscious instead of death</English> + <Polish>Spraw, aby jednostka została przeniesiona do stanu nieprzytomności zamiast ginąć na miejscu od śmiertelnych obrażeń</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_bleedingCoefficient_DisplayName"> + <English>Bleeding coefficient</English> + <Polish>Mnożnik krwawienia</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_bleedingCoefficient_Description"> + <English>Coefficient to modify the bleeding speed</English> + <Polish>Mnożnik modyfikujący prędkość wykrwawiania się</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_painCoefficient_DisplayName"> + <English>Pain coefficient</English> + <Polish>Mnożnik bólu</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_painCoefficient_Description"> + <English>Coefficient to modify the pain intensity</English> + <Polish>Mnożnik modyfikujący intensywność bólu</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_keepLocalSettingsSynced_DisplayName"> + <English>Sync status</English> + <Polish>Synchronizuj status</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_keepLocalSettingsSynced_Description"> + <English>Keep unit status synced. Recommended on.</English> + <Polish>Utrzymuj synchronizację statusu jednostek. Zalecane zostawienie tej opcji włączonej.</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_Module_Description"> + <English>Provides a medical system for both players and AI.</English> + <Polish>Moduł ten dostarcza system medyczny dla graczy oraz AI.</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_Module_DisplayName"> + <English>Advanced Medical Settings [ACE]</English> + <Polish>Zaawansowane ustawienia medyczne [ACE]</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableFor_DisplayName"> + <English>Enabled for</English> + <Polish>Aktywne dla</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableFor_Description"> + <English>Select what units the advanced medical system will be enabled for</English> + <Polish>Wybierz dla kogo zaawansowany system medyczny będzie aktywny</Polish> + </Key> + <Key ID="STR_ACE_Medical_playeronly"> + <English>Players only</English> + <Polish>Tylko dla graczy</Polish> + </Key> + <Key ID="STR_ACE_Medical_playersandai"> + <English>Players and AI</English> + <Polish>Gracze oraz AI</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableAdvancedWounds_DisplayName"> + <English>Enable Advanced wounds</English> + <Polish>Akt. zaawansowane rany</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableAdvancedWounds_Description"> + <English>Allow reopening of bandaged wounds?</English> + <Polish>Pozwól na otwieranie się zabandażowanych ran?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableVehicleCrashes_DisplayName"> + <English>Vehicle Crashes</English> + <Polish>Obrażenia od kolizji</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableVehicleCrashes_Description"> + <English>Do units take damage from a vehicle crash?</English> + <Polish>Czy jednostki otrzymują obrażenia w wyniku kolizji pojazdów?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_PAK_DisplayName"> + <English>Allow PAK</English> + <Polish>Ust. apteczek osobistych</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_PAK_Description"> + <English>Who can use the PAK for full heal?</English> + <Polish>Kto może skorzystać z apteczki osobistej w celu pełnego uleczenia?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_anyone"> + <English>Anyone</English> + <Polish>Wszyscy</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_Medic"> + <English>Medics only</English> + <Polish>Tylko medycy</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_Special"> + <English>Doctors only</English> + <Polish>Tylko doktorzy</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_DisplayName"> + <English>Remove PAK on use</English> + <Polish>Usuń apteczkę po użyciu</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_Description"> + <English>Should PAK be removed on usage?</English> + <Polish>Czy apteczka osobista powinna zniknąć z ekwipunku po jej użyciu?</Polish> + </Key> + <Key ID="STR_ACE_Medical_No"> + <English>No</English> + <Polish>Nie</Polish> + </Key> + <Key ID="STR_ACE_Medical_Yes"> + <English>Yes</English> + <Polish>Tak</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_PAK_DisplayName"> + <English>Locations PAK</English> + <Polish>Ogr. apteczek osobistych</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_PAK_Description"> + <English>Where can the personal aid kit be used?</English> + <Polish>Gdzie można korzystać z apteczek osobistych?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_anywhere"> + <English>Anywhere</English> + <Polish>Wszędzie</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_vehicle"> + <English>Medical vehicles</English> + <Polish>Pojazdy medyczne</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_facility"> + <English>Medical facility</English> + <Polish>Budynki medyczne</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_vehicleAndFacility"> + <English>Vehicles & facility</English> + <Polish>Pojazdy i budynki medyczne</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_disabled"> + <English>Disabled</English> + <Polish>Wyłączone</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_SurgicalKit_DisplayName"> + <English>Allow Surgical kit (Adv)</English> + <Polish>Ust. zestawu chirurg.</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_SurgicalKit_Description"> + <English>Who can use the surgical kit?</English> + <Polish>Kto może skorzystać z zestawu chirurgicznego w celu zszycia ran?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_SurgicalKit_DisplayName"> + <English>Remove Surgical kit (Adv)</English> + <Polish>Usuń zest. chir. po użyciu</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_SurgicalKit_Description"> + <English>Should Surgical kit be removed on usage?</English> + <Polish>Czy zestaw chirurgiczny powinien zniknąć z ekwipunku po jego użyciu?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_SurgicalKit_DisplayName"> + <English>Locations Surgical kit (Adv)</English> + <Polish>Ogr. zestawu chirurg.</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_SurgicalKit_Description"> + <English>Where can the Surgical kit be used?</English> + <Polish>Gdzie można korzystać z zestawu chirurgicznego?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_Module_Description"> + <English>Configure the treatment settings from ACE Medical</English> + <Polish>Skonfiguruj zaawansowane ustawienia leczenia systemu medycznego ACE</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_Module_DisplayName"> + <English>Revive Settings [ACE]</English> + <Polish>Ustawienia wskrzeszania [ACE]</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_enableRevive_DisplayName"> + <English>Enable Revive</English> + <Polish>Aktywuj wskrzeszanie</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_enableRevive_Description"> + <English>Enable a basic revive system</English> + <Polish>Aktywuj podstawowy system wskrzeszania</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_maxReviveTime_DisplayName"> + <English>Max Revive time</English> + <Polish>Maks. czas agonii</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_maxReviveTime_Description"> + <English>Max amount of seconds a unit can spend in revive state</English> + <Polish>Maksymalna długość agonii w sekundach (czas na wskrzeszenie)</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_amountOfReviveLives_DisplayName"> + <English>Max Revive lives</English> + <Polish>Maks. ilość wskrzeszeń</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_amountOfReviveLives_Description"> + <English>Max amount of lives a unit. 0 or -1 is disabled.</English> + <Polish>Maksymalna ilość wskrzeszeń. Wpisz 0 lub -1 aby wyłączyć.</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_Module_Description"> + <English>Provides a medical system for both players and AI.</English> + <Polish>Moduł ten aktywuje podstawowy system wskrzeszania. Jednostka po otrzymaniu śmiertelnych obrażeń przechodzi do stanu agonii, która trwa określoną długość czasu. W tym czasie aby wskrzesić i jednocześnie odratować jednostkę należy opatrzeć jej rany i wykonać RKO.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_Module_DisplayName"> + <English>Set Medic Class [ACE]</English> + <Polish>Ustaw klasę medyka [ACE]</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_EnableList_DisplayName"> + <English>List</English> + <Polish>Lista</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_EnableList_Description"> + <English>List of unit names that will be classified as medic, separated by commas.</English> + <Polish>Lista nazw jednostek, które są sklasyfikowane jako medycy, oddzielone przecinkami.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_role_DisplayName"> + <English>Is Medic</English> + <Polish>Klasa medyczna</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_role_Description"> + <English></English> + <Polish></Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_role_none"> + <English>None</English> + <Polish>Żadna</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_role_medic"> + <English>Regular medic</English> + <Polish>Zwykły medyk</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_role_doctor"> + <English>Doctor (Only Advanced Medics)</English> + <Polish>Doktor (tylko zaawansowani medycy)</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_Module_Description"> + <English>Assigns the ACE medic class to a unit</English> + <Polish>Moduł ten przypisuje klasę medyka ACE do jednostek.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_Module_DisplayName"> + <English>Set Medical Vehicle [ACE]</English> + <Polish>Ustaw pojazd medyczny [ACE]</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_EnableList_DisplayName"> + <English>List</English> + <Polish>Lista</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_EnableList_Description"> + <English>List of vehicles that will be classified as medical vehicle, separated by commas.</English> + <Polish>Lista nazw pojazdów, które są sklasyfikowane jako pojazdy medyczne, oddzielone przecinkami.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_enabled_DisplayName"> + <English>Is Medical Vehicle</English> + <Polish>Jest pojazdem med.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_enabled_Description"> + <English>Whatever or not the objects in the list will be a medical vehicle.</English> + <Polish>Czy pojazdy z tej listy są pojazdami medycznymi.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_Module_Description"> + <English>Assigns the ACE medic class to a unit</English> + <Polish>Moduł ten pozwala na przypisanie danym pojazdom statusu pojazdów medycznych. Wewnątrz takiego pojazdu można wykonywać zaawansowane zabiegi medyczne.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicalFacility_Module_DisplayName"> + <English>Set Medical Facility [ACE]</English> + <Polish>Ustaw budynek medyczny [ACE]</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicalFacility_enabled_DisplayName"> + <English>Is Medical Facility</English> + <Polish>Jest budynkiem med.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicalFacility_enabled_Description"> + <English>Registers an object as a medical facility</English> + <Polish>Przypisuje danemu obiektowi status budynku medycznego</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicalFacility_Module_Description"> + <English>Defines an object as a medical facility. This allows for more advanced treatments. Can be used on buildings and vehicles.</English> + <Polish>Moduł ten pozwala przypisać status budynku medycznego danemu obiektowi. Budynek taki pozwala na wykonywanie zaawansowanych zabiegów medycznych. Może być użyte na pojazdach i budynkach.</Polish> + </Key> + <Key ID="STR_ACE_medicalSupplyCrate"> + <English>[ACE] Medical Supply Crate (Basic)</English> + <Polish>[ACE] Skrzynka z zapasami medycznymi (podstawowa)</Polish> + </Key> + <Key ID="STR_ACE_medicalSupplyCrate_advanced"> + <English>[ACE] Medical Supply Crate (Advanced)</English> + <Polish>[ACE] Skrzynka z zapasami medycznymi (zaawansowana)</Polish> + </Key> </Package> </Project> diff --git a/addons/microdagr/CfgVehicles.hpp b/addons/microdagr/CfgVehicles.hpp index 833f7bd2f6..dc4ae7d237 100644 --- a/addons/microdagr/CfgVehicles.hpp +++ b/addons/microdagr/CfgVehicles.hpp @@ -44,7 +44,7 @@ class CfgVehicles { class GVAR(dagrModule): Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "MicroDAGR Map Fill"; + displayName = "$STR_ACE_Dagr_Module_DisplayName"; function = QFUNC(moduleMapFill); scope = 2; isGlobal = 1; @@ -52,18 +52,18 @@ class CfgVehicles { functionPriority = 0; class Arguments { class MapDataAvailable { - displayName = "MicroDAGR Map Fill"; // Argument label - description = "How much map data is filled on MicroDAGR's "; // Tooltip description - typeName = "NUMBER"; // Value type, can be "NUMBER", "STRING" or "BOOL" + displayName = "$STR_ACE_Dagr_MapDataAvailable_DisplayName"; + description = "$STR_ACE_Dagr_MapDataAvailable_Description"; + typeName = "NUMBER"; class values { - class None {name = "Full Satellite + Buildings"; value = MAP_DETAIL_SAT; default = 1;}; - class Side {name = "Topographical + Roads"; value = MAP_DETAIL_TOPOROADS;}; - class Unique {name = "None (Cannot use map view)"; value = MAP_DETAIL_NONE;}; + class None {name = "$STR_ACE_Dagr_None"; value = MAP_DETAIL_SAT; default = 1;}; + class Side {name = "$STR_ACE_Dagr_Side"; value = MAP_DETAIL_TOPOROADS;}; + class Unique {name = "$STR_ACE_Dagr_Unique"; value = MAP_DETAIL_NONE;}; }; }; }; class ModuleDescription: ModuleDescription { - description = "Controls how much data is filled on the microDAGR items. Less data restricts the map view to show less on the minimap.<br/>Source: microDAGR.pbo"; + description = "$STR_ACE_Dagr_Module_Description"; }; }; @@ -73,4 +73,4 @@ class CfgVehicles { MACRO_ADDITEM(ACE_microDAGR,10); }; }; -}; +}; \ No newline at end of file diff --git a/addons/microdagr/stringtable.xml b/addons/microdagr/stringtable.xml index af2b303f2b..c8fa993b46 100644 --- a/addons/microdagr/stringtable.xml +++ b/addons/microdagr/stringtable.xml @@ -301,5 +301,33 @@ <Italian>Chiudi MicroDAGR</Italian> <Portuguese>Fechar MicroDAGR</Portuguese> </Key> + <Key ID="STR_ACE_Dagr_Module_DisplayName"> + <English>MicroDAGR Map Fill</English> + <Polish>Wypełnienie mapy MicroDAGR</Polish> + </Key> + <Key ID="STR_ACE_Dagr_MapDataAvailable_DisplayName"> + <English>MicroDAGR Map Fill</English> + <Polish>Wypełnienie mapy MicroDAGR</Polish> + </Key> + <Key ID="STR_ACE_Dagr_MapDataAvailable_Description"> + <English>How much map data is filled on MicroDAGR's</English> + <Polish>Jak duża część informacji mapy jest załadowana do MicroDAGR?</Polish> + </Key> + <Key ID="STR_ACE_Dagr_None"> + <English>Full Satellite + Buildings</English> + <Polish>Pełna satelitarna + budynki</Polish> + </Key> + <Key ID="STR_ACE_Dagr_Side"> + <English>Topographical + Roads</English> + <Polish>Topograficzna + drogi</Polish> + </Key> + <Key ID="STR_ACE_Dagr_Unique"> + <English>None (Cannot use map view)</English> + <Polish>Żadna (wyłącza ekran mapy)</Polish> + </Key> + <Key ID="STR_ACE_Dagr_Module_Description"> + <English>Controls how much data is filled on the microDAGR items. Less data restricts the map view to show less on the minimap.<br />Source: microDAGR.pbo</English> + <Polish>Moduł ten pozwala kontrolować jak duża ilość informacji jest załadowana do przedmiotów MicroDAGR. Mniejsza ilość danych ogranicza widok mapy pokazując mniej rzeczy na minimapie.<br />Źródło: microDAGR.pbo</Polish> + </Key> </Package> </Project> diff --git a/addons/missileguidance/ACE_Settings.hpp b/addons/missileguidance/ACE_Settings.hpp index d489ef15f3..c04e6c080c 100644 --- a/addons/missileguidance/ACE_Settings.hpp +++ b/addons/missileguidance/ACE_Settings.hpp @@ -5,6 +5,6 @@ class ACE_Settings { isClientSettable = 1; displayName = "$STR_ACE_MissileGuidance"; description = "$STR_ACE_MissileGuidance_Desc"; - values[] = {"Off", "Player Only", "Player and AI"}; + values[] = {"$STR_ACE_MissileGuidance_Off", "$STR_ACE_MissileGuidance_PlayerOnly", "$STR_ACE_MissileGuidance_PlayerAndAi"}; }; }; \ No newline at end of file diff --git a/addons/missileguidance/stringtable.xml b/addons/missileguidance/stringtable.xml index dcb2be486c..3c551493a5 100644 --- a/addons/missileguidance/stringtable.xml +++ b/addons/missileguidance/stringtable.xml @@ -97,5 +97,17 @@ <Hungarian>Hellfire II AGM-114K lézer-irányított rakéta</Hungarian> <Russian>Управляемая ракета лазерного наведения Hellfire II AGM-114K</Russian> </Key> + <Key ID="STR_ACE_MissileGuidance_Off"> + <English>Off</English> + <Polish>Wyłącz</Polish> + </Key> + <Key ID="STR_ACE_MissileGuidance_PlayerOnly"> + <English>Player Only</English> + <Polish>Tylko gracz</Polish> + </Key> + <Key ID="STR_ACE_MissileGuidance_PlayerAndAi"> + <English>Player and AI</English> + <Polish>Gracz oraz AI</Polish> + </Key> </Package> </Project> diff --git a/addons/missionmodules/CfgFactionClasses.hpp b/addons/missionmodules/CfgFactionClasses.hpp index 792f4d31e3..6f320805fb 100644 --- a/addons/missionmodules/CfgFactionClasses.hpp +++ b/addons/missionmodules/CfgFactionClasses.hpp @@ -1,6 +1,6 @@ class CfgFactionClasses { class NO_CATEGORY; class ACE_missionModules: NO_CATEGORY { - displayName = "ACE Mission Modules"; + displayName = "$STR_ACE_MissionModules_Category_DisplayName"; }; }; \ No newline at end of file diff --git a/addons/missionmodules/CfgVehicles.hpp b/addons/missionmodules/CfgVehicles.hpp index 35a937c660..a08e78f17b 100644 --- a/addons/missionmodules/CfgVehicles.hpp +++ b/addons/missionmodules/CfgVehicles.hpp @@ -8,7 +8,7 @@ class CfgVehicles { // TODO make a curator variant for this class ACE_moduleAmbianceSound: Module_F { scope = 2; - displayName = "Ambiance Sounds [ACE]"; + displayName = "$STR_ACE_MissionModules_AmbianceSounds_DisplayName"; icon = QUOTE(PATHTOF(UI\Icon_Module_Ambient_Sounds_ca.paa)); category = "ACE_missionModules"; function = QUOTE(FUNC(moduleAmbianceSound)); @@ -18,51 +18,51 @@ class CfgVehicles { author = "$STR_ACE_Common_ACETeam"; class Arguments { class soundFiles { - displayName = "Sounds"; - description = "Class names of the ambiance sounds to be played. Seperated by ','"; + displayName = "$STR_ACE_MissionModules_AmbianceSounds_soundFiles_DisplayName"; + description = "$STR_ACE_MissionModules_AmbianceSounds_soundFiles_Description"; typeName = "STRING"; defaultValue = ""; }; class minimalDistance { - displayName = "Minimal Distance"; - description = "Used for calculating a random position and sets the minimal distance between the players and the played sound file(s)"; + displayName = "$STR_ACE_MissionModules_AmbianceSounds_minimalDistance_DisplayName"; + description = "$STR_ACE_MissionModules_AmbianceSounds_minimalDistance_Description"; typeName = "NUMBER"; defaultValue = 400; }; class maximalDistance { - displayName = "Maximum Distance"; - description = "Used for calculating a random position and sets the maximum distance between the players and the played sound file(s)"; + displayName = "$STR_ACE_MissionModules_AmbianceSounds_maximalDistance_DisplayName"; + description = "$STR_ACE_MissionModules_AmbianceSounds_maximalDistance_Description"; typeName = "NUMBER"; defaultValue = 900; }; class minimalDelay { - displayName = "Minimal Delay"; - description = "Minimal delay between sounds played"; + displayName = "$STR_ACE_MissionModules_AmbianceSounds_minimalDelay_DisplayName"; + description = "$STR_ACE_MissionModules_AmbianceSounds_minimalDelay_Description"; typeName = "NUMBER"; defaultValue = 10; }; class maximalDelay { - displayName = "Maximum Delay"; - description = "Maximum delay between sounds played"; + displayName = "$STR_ACE_MissionModules_AmbianceSounds_maximalDelay_DisplayName"; + description = "$STR_ACE_MissionModules_AmbianceSounds_maximalDelay_Description"; typeName = "NUMBER"; defaultValue = 170; }; class followPlayers { - displayName = "Follow Players"; - description = "Follow players. If set to false, loop will play sounds only nearby logic position."; + displayName = "$STR_ACE_MissionModules_AmbianceSounds_followPlayers_DisplayName"; + description = "$STR_ACE_MissionModules_AmbianceSounds_followPlayers_Description"; typeName = "BOOL"; defaultValue = 0; }; class soundVolume { - displayName = "Volume"; - description = "The volume of the sounds played"; + displayName = "$STR_ACE_MissionModules_AmbianceSounds_soundVolume_DisplayName"; + description = "$STR_ACE_MissionModules_AmbianceSounds_soundVolume_Description"; typeName = "NUMBER"; defaultValue = 1; }; }; class ModuleDescription { - description = "Ambiance sounds loop (synced across MP)"; + description = "$STR_ACE_MissionModules_AmbianceSounds_Description"; sync[] = {}; }; }; -}; +}; \ No newline at end of file diff --git a/addons/missionmodules/stringtable.xml b/addons/missionmodules/stringtable.xml new file mode 100644 index 0000000000..12d70602c2 --- /dev/null +++ b/addons/missionmodules/stringtable.xml @@ -0,0 +1,73 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project name="ACE"> + <Package name="Mission Modules"> + <Key ID="STR_ACE_MissionModules_Category_DisplayName"> + <English>ACE Mission Modules</English> + <Polish>ACE Moduły misji</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_DisplayName"> + <English>Ambiance Sounds [ACE]</English> + <Polish>Dźwięki [ACE]</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_soundFiles_DisplayName"> + <English>Sounds</English> + <Polish>Dźwięki</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_soundFiles_Description"> + <English>Classnames of the ambiance sounds played. Seperated by ','. </English> + <Polish>Classname-y dźwięków do odtwarzania. Oddzielone przy użyciu ','.</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_minimalDistance_DisplayName"> + <English>Minimal Distance</English> + <Polish>Minimalny dystans</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_minimalDistance_Description"> + <English>Minimal Distance</English> + <Polish>Minimalny dystans</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_maximalDistance_DisplayName"> + <English>Maximal Distance</English> + <Polish>Maksymalny dystans</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_maximalDistance_Description"> + <English>Maximal Distance</English> + <Polish>Maksymalny dystans</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_minimalDelay_DisplayName"> + <English>Minimal Delay</English> + <Polish>Minimalne opóźnienie</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_minimalDelay_Description"> + <English>Minimal Delay between sounds played</English> + <Polish>Minimalne opóźnienie pomiędzy odtwarzanymi dźwiękami</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_maximalDelay_DisplayName"> + <English>Maximal Delay</English> + <Polish>Maksymalne opóźnienie</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_maximalDelay_Description"> + <English>Maximal Delay between sounds played</English> + <Polish>Maksymalne opóźnienie pomiędzy odtwarzanymi dźwiękami</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_followPlayers_DisplayName"> + <English>Follow Players</English> + <Polish>Podążaj za graczami</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_followPlayers_Description"> + <English>Follow players. If set to false, loop will play sounds only nearby logic position.</English> + <Polish>Podążaj za graczami. Jeżeli ustawione na 'Nie', pętla będzie odtwarzana tylko w pobliżu pozycji logiki.</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_soundVolume_DisplayName"> + <English>Volume</English> + <Polish>Głośność</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_soundVolume_Description"> + <English>The volume of the sounds played</English> + <Polish>Głośność odtwarzanych dźwięków</Polish> + </Key> + <Key ID="STR_ACE_MissionModules_AmbianceSounds_Description"> + <English>Ambiance sounds loop (synced across MP)</English> + <Polish>Pętla odtwarzania dzwięków (synchronizowana na MP)</Polish> + </Key> + </Package> +</Project> \ No newline at end of file diff --git a/addons/mk6mortar/CfgVehicles.hpp b/addons/mk6mortar/CfgVehicles.hpp index baf74fa2c4..e4a9d0f2a5 100644 --- a/addons/mk6mortar/CfgVehicles.hpp +++ b/addons/mk6mortar/CfgVehicles.hpp @@ -50,7 +50,7 @@ class CfgVehicles { class GVAR(module): Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "MK6 Settings"; + displayName = "$STR_ACE_mk6mortar_Module_DisplayName"; function = QFUNC(moduleInit); scope = 2; isGlobal = 0; @@ -58,26 +58,26 @@ class CfgVehicles { functionPriority = 0; class Arguments { class airResistanceEnabled { - displayName = "Air Resistance"; - description = "For Player Shots, Model Air Resistance and Wind Effects"; + displayName = "$STR_ACE_mk6mortar_airResistanceEnabled_DisplayName"; + description = "$STR_ACE_mk6mortar_airResistanceEnabled_Description"; typeName = "BOOL"; defaultValue = 1; }; class allowComputerRangefinder { - displayName = "Allow MK6 Computer"; - description = "Show the Computer and Rangefinder (these NEED to be removed if you enable air resistance)"; + displayName = "$STR_ACE_mk6mortar_allowComputerRangefinder_DisplayName"; + description = "$STR_ACE_mk6mortar_allowComputerRangefinder_Description"; typeName = "BOOL"; defaultValue = 0; }; class allowCompass { - displayName = "Allow MK6 Compass"; - description = "Show the MK6 Digital Compass"; + displayName = "$STR_ACE_mk6mortar_allowCompass_DisplayName"; + description = "$STR_ACE_mk6mortar_allowCompass_Description"; typeName = "BOOL"; defaultValue = 1; }; }; class ModuleDescription: ModuleDescription { - description = ""; + description = "$STR_ACE_mk6mortar_Module_Description"; }; }; -}; +}; \ No newline at end of file diff --git a/addons/mk6mortar/stringtable.xml b/addons/mk6mortar/stringtable.xml index fd2fe4aa4c..37c7d322ad 100644 --- a/addons/mk6mortar/stringtable.xml +++ b/addons/mk6mortar/stringtable.xml @@ -49,5 +49,37 @@ <Czech>Nabít</Czech> <Italian>Carica</Italian> </Key> + <Key ID="STR_ACE_mk6mortar_Module_DisplayName"> + <English>MK6 Settings</English> + <Polish>Moździerz MK6 - Ustawienia</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_airResistanceEnabled_DisplayName"> + <English>Air Resistance</English> + <Polish>Opór powietrza</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_airResistanceEnabled_Description"> + <English>For Player Shots, Model Air Resistance and Wind Effects</English> + <Polish>Modeluj opór powietrza oraz wpływ wiatru na tor lotu pocisku dla strzałów z moździerza MK6 przez graczy</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_allowComputerRangefinder_DisplayName"> + <English>Allow MK6 Computer</English> + <Polish>Komputer MK6</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_allowComputerRangefinder_Description"> + <English>Show the Computer and Rangefinder (these NEED to be removed if you enable air resistance)</English> + <Polish>Zezwól na komputer i dalmierz (opcja ta MUSI zostać wyłączona jeżeli aktywowałeś opór powietrza)</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_allowCompass_DisplayName"> + <English>Allow MK6 Compass</English> + <Polish>Kompas MK6</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_allowCompass_Description"> + <English>Show the MK6 Digital Compass</English> + <Polish>Pokaż kompas MK6</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_Module_Description"> + <English></English> + <Polish>Moduł ten pozwala dostosować ustawienia moździerza MK6.</Polish> + </Key> </Package> </Project> diff --git a/addons/nametags/CfgVehicles.hpp b/addons/nametags/CfgVehicles.hpp index ec005c8218..3619df195f 100644 --- a/addons/nametags/CfgVehicles.hpp +++ b/addons/nametags/CfgVehicles.hpp @@ -1,69 +1,75 @@ class CfgVehicles { - class Module_F; + class Logic; + class Module_F: Logic { + class ModuleDescription {}; + }; class ACE_ModuleNameTags : Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Name Tags"; + displayName = "$STR_ACE_NameTags_Module_DisplayName"; function = QFUNC(moduleNameTags); scope = 2; isGlobal = 1; icon = QUOTE(PATHTOF(UI\Icon_Module_NameTags_ca.paa)); class Arguments { class PlayerNamesViewDistance { - displayName = "Player Names View Dist."; - description = "Distance in meters at which player names are shown. Default: 5"; + displayName = "$STR_ACE_NameTags_PlayerNamesViewDistance_DisplayName"; + description = "$STR_ACE_NameTags_PlayerNamesViewDistance_Description"; typeName = "NUMBER"; defaultValue = 5; }; class showNamesForAI { - displayName = "Show name tags for AI?"; - description = "Show the name and rank tags for friendly AI units? Default: Do not force"; + displayName = "$STR_ACE_NameTags_showNamesForAI_DisplayName"; + description = "$STR_ACE_NameTags_showNamesForAI_Description"; typeName = "NUMBER"; class values { class DoNotForce { default = 1; - name = "Do Not Force"; + name = "$STR_ACE_NameTags_DoNotForce"; value = -1; }; class ForceHide { - name = "Force Hide"; + name = "$STR_ACE_NameTags_ForceHide"; value = 0; }; class ForceShow { - name = "Force show"; + name = "$STR_ACE_NameTags_ForceShow"; value = 1; }; }; }; class showVehicleCrewInfo { - displayName = "Show crew info?"; - description = "Show vehicle crew info, or by default allows players to choose it on their own. Default: Do Not Force"; + displayName = "$STR_ACE_NameTags_showVehicleCrewInfo_DisplayName"; + description = "$STR_ACE_NameTags_showVehicleCrewInfo_Description"; typeName = "NUMBER"; class values { class DoNotForce { default = 1; - name = "Do Not Force"; + name = "$STR_ACE_NameTags_DoNotForce"; value = -1; }; class ForceHide { - name = "Force Hide"; + name = "$STR_ACE_NameTags_ForceHide"; value = 0; }; class ForceShow { - name = "Force Show"; + name = "$STR_ACE_NameTags_ForceShow"; value = 1; }; }; }; class showCursorTagForVehicles { - displayName = "Show for Vehicles"; - description = "Show cursor NameTag for vehicle commander (only if client has name tags enabled)Default: No"; + displayName = "$STR_ACE_NameTags_showCursorTagForVehicles_DisplayName"; + description = "$STR_ACE_NameTags_showCursorTagForVehicles_Description"; typeName = "BOOL"; class values { - class Yes {name = "Yes"; value = 1;}; - class No {default = 1; name = "No"; value = 0;}; + class Yes {name = "$STR_ACE_NameTags_Yes"; value = 1;}; + class No {default = 1; name = "$STR_ACE_NameTags_No"; value = 0;}; }; }; + }; + class ModuleDescription: ModuleDescription { + description = "$STR_ACE_NameTags_Module_Description"; }; }; -}; +}; \ No newline at end of file diff --git a/addons/nametags/config.cpp b/addons/nametags/config.cpp index dce054a9ec..7a0086bfb6 100644 --- a/addons/nametags/config.cpp +++ b/addons/nametags/config.cpp @@ -27,7 +27,8 @@ class ACE_Settings { typeName = "SCALAR"; isClientSettable = 1; displayName = "$STR_ACE_NameTags_ShowPlayerNames"; - values[] = {"Disabled", "Enabled", "Only Cursor", "Only On Keypress", "Only Cursor and KeyPress"}; + description = "$STR_ACE_NameTags_ShowPlayerNames_Desc"; + values[] = {"$STR_ACE_Common_Disabled", "$STR_ACE_Common_Enabled", "$STR_ACE_Common_OnlyCursor", "$STR_ACE_Common_OnlyOnKeypress", "$STR_ACE_Common_OnlyCursorAndKeyPress"}; }; class GVAR(showPlayerRanks) { value = 1; @@ -57,7 +58,8 @@ class ACE_Settings { typeName = "SCALAR"; isClientSettable = 1; displayName = "$STR_ACE_NameTags_ShowSoundWaves"; - values[] = {"Disabled", "Use Nametag settings", "Always Show All"}; + description = "$STR_ACE_NameTags_ShowSoundWaves_Desc"; + values[] = {"$STR_ACE_Common_Disabled", "$STR_ACE_Common_NameTagSettings", "$STR_ACE_Common_AlwaysShowAll"}; }; class GVAR(PlayerNamesViewDistance) { value = 5; diff --git a/addons/nametags/stringtable.xml b/addons/nametags/stringtable.xml index 8daae5cd5d..251e8eba9a 100644 --- a/addons/nametags/stringtable.xml +++ b/addons/nametags/stringtable.xml @@ -109,5 +109,101 @@ <Italian>Colore dei nomi non appartenenti al gruppo</Italian> <Portuguese>Cor padrão do nome (unidades fora do grupo)</Portuguese> </Key> + <Key ID="STR_ACE_NameTags_Module_DisplayName"> + <English>Name Tags</English> + <Polish>Ustawienia imion</Polish> + </Key> + <Key ID="STR_ACE_NameTags_PlayerNamesViewDistance_DisplayName"> + <English>Player Names View Dist.</English> + <Polish>Zasięg imion graczy</Polish> + </Key> + <Key ID="STR_ACE_NameTags_PlayerNamesViewDistance_Description"> + <English>Distance in meters at which player names are shown. Default: 5</English> + <Polish>Dystans w metrach, na którym wyświetlane są imiona graczy. Domyślnie: 5</Polish> + </Key> + <Key ID="STR_ACE_NameTags_showNamesForAI_DisplayName"> + <English>Show name tags for AI?</English> + <Polish>Imiona AI</Polish> + </Key> + <Key ID="STR_ACE_NameTags_showNamesForAI_Description"> + <English>Show the name and rank tags for friendly AI units? Default: Do not force</English> + <Polish>Pokaż imiona i rangi przyjaznych jednostek AI? Domyślnie: Nie wymuszaj</Polish> + </Key> + <Key ID="STR_ACE_NameTags_DoNotForce"> + <English>Do Not Force</English> + <Polish>Nie wymuszaj</Polish> + </Key> + <Key ID="STR_ACE_NameTags_ForceHide"> + <English>Force Hide</English> + <Polish>Wymuś ukrycie</Polish> + </Key> + <Key ID="STR_ACE_NameTags_ForceShow"> + <English>Force show</English> + <Polish>Wymuś wyświetlanie</Polish> + </Key> + <Key ID="STR_ACE_NameTags_showVehicleCrewInfo_DisplayName"> + <English>Show crew info?</English> + <Polish>Pokaż załogę</Polish> + </Key> + <Key ID="STR_ACE_NameTags_showVehicleCrewInfo_Description"> + <English>Show vehicle crew info, or by default allows players to choose it on their own. Default: Do Not Force</English> + <Polish>Pokaż informacje o obsadzie pojazdu, lub pozwól graczom ustawić tą opcje według własnego uznania. Domyślnie: Nie wymuszaj</Polish> + </Key> + <Key ID="STR_ACE_NameTags_showCursorTagForVehicles_DisplayName"> + <English>Show for Vehicles</English> + <Polish>Pokaż dla pojazdów</Polish> + </Key> + <Key ID="STR_ACE_NameTags_showCursorTagForVehicles_Description"> + <English>Show cursor NameTag for vehicle commander (only if client has name tags enabled)Default: No</English> + <Polish>Pokazuj imię dowódcy pojazdu nad pojazdem (tylko jeżeli klient ma włączone imiona graczy). Domyślnie: Nie</Polish> + </Key> + <Key ID="STR_ACE_NameTags_Yes"> + <English>Yes</English> + <Polish>Tak</Polish> + </Key> + <Key ID="STR_ACE_NameTags_No"> + <English>No</English> + <Polish>Nie</Polish> + </Key> + <Key ID="STR_ACE_NameTags_Module_Description"> + <English></English> + <Polish>Moduł ten pozwala dostosować ustawienia i zasięg wyświetlania imion.</Polish> + </Key> + <Key ID="STR_ACE_Common_Disabled"> + <English>Disabled</English> + <Polish>Wyłączone</Polish> + </Key> + <Key ID="STR_ACE_Common_Enabled"> + <English>Enabled</English> + <Polish>Włączone</Polish> + </Key> + <Key ID="STR_ACE_Common_OnlyCursor"> + <English>Only Cursor</English> + <Polish>Tylko pod kursorem</Polish> + </Key> + <Key ID="STR_ACE_Common_OnlyOnKeypress"> + <English>Only On Keypress</English> + <Polish>Tylko po wciśnięciu klawisza</Polish> + </Key> + <Key ID="STR_ACE_Common_OnlyCursorAndKeyPress"> + <English>Only Cursor and KeyPress</English> + <Polish>Tylko pod kursorem i po wciśnięciu klawisza</Polish> + </Key> + <Key ID="STR_ACE_Common_NameTagSettings"> + <English>Use Nametag settings</English> + <Polish>Użyj ustawień imion</Polish> + </Key> + <Key ID="STR_ACE_Common_AlwaysShowAll"> + <English>Always Show All</English> + <Polish>Zawsze pokazuj wszystkie</Polish> + </Key> + <Key ID="STR_ACE_NameTags_ShowPlayerNames_Desc"> + <English></English> + <Polish>Opcja ta pozwala dostosować sposób wyświetlania imion nad głowami graczy. Opcja "Tylko po wciśnięciu klawisza" wyświetla imiona tylko przytrzymania klawisza "Modyfikator" dostępnego w menu ustawień addonów -> ACE3.</Polish> + </Key> + <Key ID="STR_ACE_NameTags_ShowSoundWaves_Desc"> + <English></English> + <Polish>Opcja ta pozwala dostosować sposób wyświetlania efektu fal dźwiękowych nad głowami mówiących graczy, wyświetlanych po przytrzymaniu klawisza PTT. Opcja ta współpracuje z TFAR oraz ACRE2.</Polish> + </Key> </Package> </Project> diff --git a/addons/optionsmenu/CfgVehicles.hpp b/addons/optionsmenu/CfgVehicles.hpp index 2a19aa2966..52895acb66 100644 --- a/addons/optionsmenu/CfgVehicles.hpp +++ b/addons/optionsmenu/CfgVehicles.hpp @@ -1,9 +1,8 @@ class CfgVehicles { class ACE_Module; - // TODO localization for all the modules class ACE_moduleAllowConfigExport: ACE_Module { scope = 2; - displayName = "Allow Config Export [ACE]"; + displayName = "$STR_AllowConfigExport_Module_DisplayName"; //icon = ""; category = "ACE"; function = QUOTE(DFUNC(moduleAllowConfigExport)); @@ -13,16 +12,15 @@ class CfgVehicles { author = "$STR_ACE_Common_ACETeam"; class Arguments { class allowconfigurationExport { - displayName = "Allow"; - description = "Allow export of all settings to a server config formatted."; + displayName = "$STR_AllowConfigExport_allowconfigurationExport_DisplayName"; + description = "$STR_AllowConfigExport_allowconfigurationExport_Description"; typeName = "BOOL"; defaultValue = 1; }; }; class ModuleDescription { - description = "When allowed, you have access to the settings modification and export in SP. Clicking export will place the formated config on your clipboard."; + description = "$STR_AllowConfigExport_Module_Description"; sync[] = {}; }; }; - }; \ No newline at end of file diff --git a/addons/optionsmenu/stringtable.xml b/addons/optionsmenu/stringtable.xml index d5de0c1426..3b649aa6c7 100644 --- a/addons/optionsmenu/stringtable.xml +++ b/addons/optionsmenu/stringtable.xml @@ -241,5 +241,49 @@ <Portuguese>Escalar o menu de opções</Portuguese> <Italian>Proporzioni della interfaccia utente</Italian> </Key> + <Key ID="STR_AllowConfigExport_Module_DisplayName"> + <English>Allow Config Export [ACE]</English> + <Polish>Pozwól na eksport ustawień [ACE]</Polish> + </Key> + <Key ID="STR_AllowConfigExport_allowconfigurationExport_DisplayName"> + <English>Allow</English> + <Polish>Zezwól</Polish> + </Key> + <Key ID="STR_AllowConfigExport_allowconfigurationExport_Description"> + <English>Allow export of all settings to a server config formatted.</English> + <Polish>Zezwól na eksport wszystkich ustawień do formatu konfiguracji serwera.</Polish> + </Key> + <Key ID="STR_AllowConfigExport_Module_Description"> + <English>When allowed, you have access to the settings modification and export in SP. Clicking export will place the formated config on your clipboard.</English> + <Polish>Jeżeli ustawione na zezwól, wtedy będziesz mieć dostęp do ekranu modyfikacji wszystich ustawień i zmiennych ACE, a także będziesz mieć możliwość eksportu tychże ustawień do formatu rozpoznawalnego przez userconfig serwera. Kliknięcie opcji Eksportuj skopiuje wszystkie ustawienia do schowka. Działa tylko w trybie SP.</Polish> + </Key> + <Key ID="STR_ACE_Common_Hide"> + <English>Hide</English> + <Polish>Ukryj</Polish> + </Key> + <Key ID="STR_ACE_Common_TopRightDown"> + <English>Top right, downwards</English> + <Polish>Po prawej u góry, w dół</Polish> + </Key> + <Key ID="STR_ACE_Common_TopRightLeft"> + <English>Top right, to the left</English> + <Polish>Po prawej u góry, do lewej</Polish> + </Key> + <Key ID="STR_ACE_Common_TopLeftDown"> + <English>Top left, downwards</English> + <Polish>Po lewej u góry, w dół</Polish> + </Key> + <Key ID="STR_ACE_Common_TopLeftRight"> + <English>Top left, to the right</English> + <Polish>Po lewej u góry, do prawej</Polish> + </Key> + <Key ID="STR_ACE_Common_Top"> + <English>Top</English> + <Polish>Góra</Polish> + </Key> + <Key ID="STR_ACE_Common_Bottom"> + <English>Bottom</English> + <Polish>Dół</Polish> + </Key> </Package> </Project> diff --git a/addons/respawn/CfgVehicleClasses.hpp b/addons/respawn/CfgVehicleClasses.hpp index 8d4eeb139c..19ed9fede8 100644 --- a/addons/respawn/CfgVehicleClasses.hpp +++ b/addons/respawn/CfgVehicleClasses.hpp @@ -1,5 +1,5 @@ class CfgVehicleClasses { class GVAR(Rallypoints) { - displayName = "ACE Respawn"; + displayName = "$STR_ACE_Respawn_EditorCategory"; }; }; diff --git a/addons/respawn/CfgVehicles.hpp b/addons/respawn/CfgVehicles.hpp index 2f963a12d3..07ef054b0d 100644 --- a/addons/respawn/CfgVehicles.hpp +++ b/addons/respawn/CfgVehicles.hpp @@ -1,9 +1,12 @@ class CfgVehicles { - class Module_F; + class Logic; + class Module_F: Logic { + class ModuleDescription {}; + }; class ACE_ModuleRespawn: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Respawn System"; + displayName = "$STR_ACE_Respawn_Module_DisplayName"; function = QFUNC(module); scope = 2; isGlobal = 1; @@ -11,43 +14,60 @@ class CfgVehicles { class Arguments { class SavePreDeathGear { - displayName = "Save Gear?"; - description = "Respawn with the gear a soldier had just before his death?"; + displayName = "$STR_ACE_Respawn_SavePreDeathGear_DisplayName"; + description = "$STR_ACE_Respawn_SavePreDeathGear_Description"; typeName = "BOOL"; - defaultValue = 0; + + class values { + class Yes { name = "$STR_ACE_Respawn_Yes"; value = 1; }; + class No { default = 1; name = "$STR_ACE_Respawn_No"; value = 0; }; + }; }; class RemoveDeadBodiesDisconnected { - displayName = "Remove bodies?"; - description = "Remove player bodies after disconnect?"; + displayName = "$STR_ACE_Respawn_RemoveDeadBodiesDisconnected_DisplayName"; + description = "$STR_ACE_Respawn_RemoveDeadBodiesDisconnected_Description"; typeName = "BOOL"; - defaultValue = 1; + + class values { + class Yes { default = 1; name = "$STR_ACE_Respawn_Yes"; value = 1; }; + class No { name = "$STR_ACE_Respawn_No"; value = 0; }; + }; }; + }; + class ModuleDescription: ModuleDescription { + description = "$STR_ACE_Respawn_Module_Description"; }; }; class ACE_ModuleFriendlyFire: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Friendly Fire Messages"; + displayName = "$STR_ACE_FriendlyFire_Module_DisplayName"; function = QFUNC(moduleFriendlyFire); scope = 2; isGlobal = 1; icon = QUOTE(PATHTOF(UI\Icon_Module_FriendlyFire_ca.paa)); class Arguments {}; + class ModuleDescription: ModuleDescription { + description = "$STR_ACE_FriendlyFire_Module_Description"; + }; }; class ACE_ModuleRallypoint: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Rallypoint System"; + displayName = "$STR_ACE_Rallypoint_Module_DisplayName"; function = QFUNC(moduleRallypoint); scope = 2; isGlobal = 1; icon = QUOTE(PATHTOF(UI\Icon_Module_Rallypoint_ca.paa)); class Arguments {}; + class ModuleDescription: ModuleDescription { + description = "$STR_ACE_Rallypoint_Module_Description"; + }; }; // team leader @@ -55,7 +75,7 @@ class CfgVehicles { class CAManBase : Man { class ACE_SelfActions { class ACE_MoveRallypoint { - displayName = "Move Rallypoint"; + displayName = "$STR_ACE_Rallypoint_MoveRallypoint"; condition = QUOTE([ARR_2(_player, side group _player)] call FUNC(canMoveRallypoint)); statement = QUOTE([ARR_2(_player, side group _player)] call FUNC(moveRallypoint)); showDisabled = 0; diff --git a/addons/respawn/stringtable.xml b/addons/respawn/stringtable.xml index 539bb4b530..a9965dd2a4 100644 --- a/addons/respawn/stringtable.xml +++ b/addons/respawn/stringtable.xml @@ -145,5 +145,61 @@ <Czech>Rallypoint Nezávislý</Czech> <Portuguese>Ponto de encontro Independente</Portuguese> </Key> + <Key ID="STR_ACE_Respawn_Module_DisplayName"> + <English>Respawn System</English> + <Polish>System odrodzenia</Polish> + </Key> + <Key ID="STR_ACE_Respawn_SavePreDeathGear_DisplayName"> + <English>Save Gear?</English> + <Polish>Zapisać ekwipunek?</Polish> + </Key> + <Key ID="STR_ACE_Respawn_SavePreDeathGear_Description"> + <English>Respawn with the gear a soldier had just before his death?</English> + <Polish>Odradzaj z ekwipunkiem jaki żołnierz miał tuż przed swoją śmiercią?</Polish> + </Key> + <Key ID="STR_ACE_Respawn_Yes"> + <English>Yes</English> + <Polish>Tak</Polish> + </Key> + <Key ID="STR_ACE_Respawn_No"> + <English>No</English> + <Polish>Nie</Polish> + </Key> + <Key ID="STR_ACE_Respawn_RemoveDeadBodiesDisconnected_DisplayName"> + <English>Remove bodies?</English> + <Polish>Usuwać ciała?</Polish> + </Key> + <Key ID="STR_ACE_Respawn_RemoveDeadBodiesDisconnected_Description"> + <English>Remove player bodies after disconnect?</English> + <Polish>Usuwaj ciała graczy po rozłączeniu z serwera?</Polish> + </Key> + <Key ID="STR_ACE_Respawn_Module_Description"> + <English></English> + <Polish>Moduł ten pozwala dostosować ustawienia odrodzenia (respawnu).</Polish> + </Key> + <Key ID="STR_ACE_FriendlyFire_Module_DisplayName"> + <English>Friendly Fire Messages</English> + <Polish>Wiadomości Friendly Fire</Polish> + </Key> + <Key ID="STR_ACE_FriendlyFire_Module_Description"> + <English></English> + <Polish>Użycie tego modułu na misji spowoduje wyświetlenie wiadomości na czacie w przypadku, kiedy zostanie popełniony friendly fire - wyświetlona zostanie wtedy wiadomość kto kogo zabił.</Polish> + </Key> + <Key ID="STR_ACE_Rallypoint_Module_DisplayName"> + <English>Rallypoint System</English> + <Polish>System punktu zbiórki</Polish> + </Key> + <Key ID="STR_ACE_Rallypoint_Module_Description"> + <English></English> + <Polish>Moduł ten pozwala zastosować na misji "punkt zbiórki", do którego można szybko przeteleportować się z "bazy". Wymaga postawienia odpowiednich obiektów na mapie - bazy oraz flagi. Obydwa dostępne są w kategorii Puste -> ACE Odrodzenie.</Polish> + </Key> + <Key ID="STR_ACE_Rallypoint_MoveRallypoint"> + <English>Move Rallypoint</English> + <Polish>Przenieś punkt zbiórki</Polish> + </Key> + <Key ID="STR_ACE_Respawn_EditorCategory"> + <English>ACE Respawn</English> + <Polish>ACE Odrodzenie</Polish> + </Key> </Package> </Project> diff --git a/addons/switchunits/CfgVehicles.hpp b/addons/switchunits/CfgVehicles.hpp index 429970b1a0..1e041a3f4f 100644 --- a/addons/switchunits/CfgVehicles.hpp +++ b/addons/switchunits/CfgVehicles.hpp @@ -3,63 +3,66 @@ class CfgVehicles { class ACE_ModuleSwitchUnits: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "SwitchUnits System"; + displayName = "$STR_ACE_SwitchUnits_Module_DisplayName"; function = FUNC(module); scope = 2; isGlobal = 1; icon = QUOTE(PATHTOF(UI\Icon_Module_SwitchUnits_ca.paa)); class Arguments { class SwitchToWest { - displayName = "Switch to West?"; - description = "Allow switching to west units?"; + displayName = "$STR_ACE_SwitchUnits_SwitchToWest_DisplayName"; + description = "$STR_ACE_SwitchUnits_SwitchToWest_Description"; typeName = "BOOL"; class values { - class Yes {name = "Yes"; value = 1;}; - class No {default = 1; name = "No"; value = 0;}; + class Yes {name = "$STR_ACE_SwitchUnits_Yes"; value = 1;}; + class No {default = 1; name = "$STR_ACE_SwitchUnits_Yes"; value = 0;}; }; }; class SwitchToEast { - displayName = "Switch to East?"; - description = "Allow switching to east units?"; + displayName = "$STR_ACE_SwitchUnits_SwitchToEast_DisplayName"; + description = "$STR_ACE_SwitchUnits_SwitchToEast_Description"; typeName = "BOOL"; class values { - class Yes {name = "Yes"; value = 1;}; - class No {default = 1; name = "No"; value = 0;}; + class Yes {name = "$STR_ACE_SwitchUnits_Yes"; value = 1;}; + class No {default = 1; name = "$STR_ACE_SwitchUnits_No"; value = 0;}; }; }; class SwitchToIndependent { - displayName = "Switch to Independent?"; - description = "Allow switching to independent units?"; + displayName = "$STR_ACE_SwitchUnits_SwitchToIndependent_DisplayName"; + description = "$STR_ACE_SwitchUnits_SwitchToIndependent_Description"; typeName = "BOOL"; class values { - class Yes {name = "Yes"; value = 1;}; - class No {default = 1; name = "No"; value = 0;}; + class Yes {name = "$STR_ACE_SwitchUnits_Yes"; value = 1;}; + class No {default = 1; name = "$STR_ACE_SwitchUnits_No"; value = 0;}; }; }; class SwitchToCivilian { - displayName = "Switch to Civilian?"; - description = "Allow switching to civilian units?"; + displayName = "$STR_ACE_SwitchUnits_SwitchToCivilian_DisplayName"; + description = "$STR_ACE_SwitchUnits_SwitchToCivilian_Description"; typeName = "BOOL"; class values { - class Yes {name = "Yes"; value = 1;}; - class No {default = 1; name = "No"; value = 0;}; + class Yes {name = "$STR_ACE_SwitchUnits_Yes"; value = 1;}; + class No {default = 1; name = "$STR_ACE_SwitchUnits_No"; value = 0;}; }; }; class EnableSafeZone { - displayName = "Enable Safe Zone?"; - description = "Enable a safe zone around enemy units? Players can't switch to units inside of the safe zone."; + displayName = "$STR_ACE_SwitchUnits_EnableSafeZone_DisplayName"; + description = "$STR_ACE_SwitchUnits_EnableSafeZone_Description"; typeName = "BOOL"; class values { - class Yes {default = 1; name = "Yes"; value = 1;}; - class No {name = "No"; value = 0;}; + class Yes {default = 1; name = "$STR_ACE_SwitchUnits_Yes"; value = 1;}; + class No {name = "$STR_ACE_SwitchUnits_No"; value = 0;}; }; }; class SafeZoneRadius { - displayName = "Safe Zone Radius"; - description = "The safe zone around players from a different team. Default: 200"; + displayName = "$STR_ACE_SwitchUnits_SafeZoneRadius_DisplayName"; + description = "$STR_ACE_SwitchUnits_SafeZoneRadius_Description"; typeName = "NUMBER"; defaultValue = 100; }; + }; + class ModuleDescription { + description = "$STR_ACE_SwitchUnits_Module_Description"; }; }; -}; +}; \ No newline at end of file diff --git a/addons/switchunits/stringtable.xml b/addons/switchunits/stringtable.xml index 8121e3e61e..c1e7fc2d57 100644 --- a/addons/switchunits/stringtable.xml +++ b/addons/switchunits/stringtable.xml @@ -25,5 +25,69 @@ <Italian>Questa unità è troppo vicina al nemico.</Italian> <Portuguese>Essa unidade está muito perta do inimigo.</Portuguese> </Key> + <Key ID="STR_ACE_SwitchUnits_Yes"> + <English>Yes</English> + <Polish>Tak</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_No"> + <English>No</English> + <Polish>Nie</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_Module_DisplayName"> + <English>SwitchUnits System</English> + <Polish>System zmiany stron</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_SwitchToWest_DisplayName"> + <English>Switch to West?</English> + <Polish>Zmiana na Zachód?</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_SwitchToWest_Description"> + <English>Allow switching to west units?</English> + <Polish>Pozwolić zmieniać graczom stronę na Zachód?</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_SwitchToEast_DisplayName"> + <English>Switch to East?</English> + <Polish>Zmiana na Wschód?</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_SwitchToEast_Description"> + <English>Allow switching to east units?</English> + <Polish>Pozwolić zmieniać graczom stronę na Wschód?</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_SwitchToIndependent_DisplayName"> + <English>Switch to Independent?</English> + <Polish>Zmiana na Ruch Oporu?</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_SwitchToIndependent_Description"> + <English>Allow switching to independent units?</English> + <Polish>Pozwolić zmieniać stronę na Ruch Oporu?</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_SwitchToCivilian_DisplayName"> + <English>Switch to Civilian?</English> + <Polish>Zmiana na Cywili?</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_SwitchToCivilian_Description"> + <English>Allow switching to civilian units?</English> + <Polish>Pozwolić zmieniać stronę na Cywili?</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_EnableSafeZone_DisplayName"> + <English>Enable Safe Zone?</English> + <Polish>Aktywuj bezp. strefę?</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_EnableSafeZone_Description"> + <English>Enable a safe zone around enemy units? Players can't switch to units inside of the safe zone.</English> + <Polish>Aktywuje bezpieczną strefę wokół jednostek przeciwnika. Gracze nie mogą zmieniać strony wewnątrz tej strefy.</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_SafeZoneRadius_DisplayName"> + <English>Safe Zone Radius</English> + <Polish>Promień bezp. strefy</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_SafeZoneRadius_Description"> + <English>The safe zone around players from a different team. Default: 200</English> + <Polish>Promień bezpiecznej strefy wokół graczy z innych drużyn. Domyślnie: 200</Polish> + </Key> + <Key ID="STR_ACE_SwitchUnits_Module_Description"> + <English></English> + <Polish></Polish> + </Key> </Package> </Project> diff --git a/addons/vehiclelock/CfgVehicles.hpp b/addons/vehiclelock/CfgVehicles.hpp index 94bcf34317..8436657676 100644 --- a/addons/vehiclelock/CfgVehicles.hpp +++ b/addons/vehiclelock/CfgVehicles.hpp @@ -69,7 +69,7 @@ class CfgVehicles { class ACE_VehicleLock_ModuleSetup: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Vehicle Lock Setup"; + displayName = "$STR_ACE_VehicleLock_Module_DisplayName"; function = QFUNC(moduleInit); scope = 2; isGlobal = 0; @@ -77,37 +77,37 @@ class CfgVehicles { functionPriority = 0; class Arguments { class LockVehicleInventory { - displayName = "Lock Vehicle Inventory"; - description = "Locks the inventory of locked vehicles"; + displayName = "$STR_ACE_VehicleLock_LockVehicleInventory_DisplayName"; + description = "$STR_ACE_VehicleLock_LockVehicleInventory_Description"; typeName = "BOOL"; defaultValue = 0; }; class VehicleStartingLockState { - displayName = "Vehicle Starting Lock State"; // Argument label - description = "Set lock state for all vehicles (removes ambiguous lock states)"; // Tooltip description + displayName = "$STR_ACE_VehicleLock_VehicleStartingLockState_DisplayName"; // Argument label + description = "$STR_ACE_VehicleLock_VehicleStartingLockState_Description"; // Tooltip description typeName = "NUMBER"; // Value type, can be "NUMBER", "STRING" or "BOOL" class values { - class None {name = "As Is"; value = 0; default = 1;}; - class Side {name = "Locked"; value = 1;}; - class Unique {name = "Unlocked"; value = 2;}; + class None {name = "$STR_ACE_VehicleLock_VehicleStartingLockState_AsIs"; value = 0; default = 1;}; + class Side {name = "$STR_ACE_VehicleLock_VehicleStartingLockState_Locked"; value = 1;}; + class Unique {name = "$STR_ACE_VehicleLock_VehicleStartingLockState_Unlocked"; value = 2;}; }; }; class DefaultLockpickStrength { - displayName = "Default Lockpick Strength"; - description = "Default Time to lockpick (in seconds). Default: 10"; + displayName = "$STR_ACE_VehicleLock_DefaultLockpickStrength_DisplayName"; + description = "$STR_ACE_VehicleLock_DefaultLockpickStrength_Description"; typeName = "NUMBER"; // Value type, can be "NUMBER", "STRING" or "BOOL" defaultValue = "10"; // Default text filled in the input box }; }; class ModuleDescription: ModuleDescription { - description = "Settings for lockpick strength and initial vehicle lock state. Removes ambiguous lock states.<br/>Source: vehiclelock.pbo"; + description = "$STR_ACE_VehicleLock_Module_Description"; }; }; class ACE_VehicleLock_ModuleSyncedAssign: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "Vehicle Key Assign"; + displayName = "$STR_ACE_VehicleLock_VehicleKeyAssign_Module_DisplayName"; function = QFUNC(moduleSync); scope = 2; isGlobal = 0; @@ -115,8 +115,8 @@ class CfgVehicles { functionPriority = 0; class Arguments {}; class ModuleDescription: ModuleDescription { - description = "Sync with vehicles and players. Will handout custom keys to players for every synced vehicle. Only valid for objects present at mission start.<br/>Source: vehiclelock.pbo"; + description = "$STR_ACE_VehicleLock_VehicleKeyAssign_Module_Description"; sync[] = {"AnyPlayer", "AnyVehicle"}; }; }; -}; +}; \ No newline at end of file diff --git a/addons/vehiclelock/stringtable.xml b/addons/vehiclelock/stringtable.xml index 6ccfc8347b..4738d045df 100644 --- a/addons/vehiclelock/stringtable.xml +++ b/addons/vehiclelock/stringtable.xml @@ -133,5 +133,57 @@ <Italian>Una chaive che apr ela maggior parte dei veicoli civili</Italian> <Portuguese>Uma chave que abre a maioria dos veículos civis.</Portuguese> </Key> + <Key ID="STR_ACE_VehicleLock_Module_DisplayName"> + <English>Vehicle Lock Setup</English> + <Polish>Ustawienie blokady pojazdów</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_LockVehicleInventory_DisplayName"> + <English>Lock Vehicle Inventory</English> + <Polish>Zablokuj ekwipunek pojazdu</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_LockVehicleInventory_Description"> + <English>Locks the inventory of locked vehicles</English> + <Polish>Blokuje dostęp do ekwipunku pojazdu</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_VehicleStartingLockState_DisplayName"> + <English>Vehicle Starting Lock State</English> + <Polish>Początkowy stan blok. poj.</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_VehicleStartingLockState_Description"> + <English>Set lock state for all vehicles (removes ambiguous lock states)</English> + <Polish>Ustawia początkowy stan blokady dla wszystkich pojazdów (usuwa dwuznaczne stany blokady)</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_VehicleStartingLockState_AsIs"> + <English>As Is</English> + <Polish>Jak jest</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_VehicleStartingLockState_Locked"> + <English>Locked</English> + <Polish>Zablokowany</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_VehicleStartingLockState_Unlocked"> + <English>Unlocked</English> + <Polish>Odblokowany</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_DefaultLockpickStrength_DisplayName"> + <English>Default Lockpick Strength</English> + <Polish>Czas włamywania</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_DefaultLockpickStrength_Description"> + <English>Default Time to lockpick (in seconds). Default: 10</English> + <Polish>Domyślny czas potrzebny na otwarcie pojazdu (w sekundach). Domyślnie: 10</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_Module_Description"> + <English>Settings for lockpick strength and initial vehicle lock state. Removes ambiguous lock states.<br />Source: vehiclelock.pbo</English> + <Polish>Ustawienia czasu włamywania oraz domyślnego stanu blokady pojazdów. Wyłącza dwuznaczne ustawienia blokady. Moduł ten umożliwia więc np. zamknięcie pojazdów przeciwnika na klucz tak, że gracze bez odpowiedniego sprzętu (wytrycha) nie będą mogli ich używać.<br />Źródło: vehiclelock.pbo</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_VehicleKeyAssign_Module_DisplayName"> + <English>Vehicle Key Assign</English> + <Polish>Przydział kluczyka do pojazdu</Polish> + </Key> + <Key ID="STR_ACE_VehicleLock_VehicleKeyAssign_Module_Description"> + <English>Sync with vehicles and players. Will handout custom keys to players for every synced vehicle. Only valid for objects present at mission start.<br />Source: vehiclelock.pbo</English> + <Polish>Zsynchronizuj z pojazdami i graczami. Rozda klucze dla graczy dla każdego zsynchronizowanego pojazdu. Działa tylko na pojazdy obecne na misji od samego początku (postawione w edytorze).<br />Źródło: vehiclelock.pbo</Polish> + </Key> </Package> </Project> diff --git a/addons/weather/CfgVehicles.hpp b/addons/weather/CfgVehicles.hpp index 3de925e446..d2b5bddcba 100644 --- a/addons/weather/CfgVehicles.hpp +++ b/addons/weather/CfgVehicles.hpp @@ -2,7 +2,7 @@ class CfgVehicles { class ACE_Module; class GVAR(ModuleSettings): ACE_Module { scope = 2; - displayName = "Weather"; + displayName = "$STR_ACE_Weather_Module_DisplayName"; icon = QUOTE(PATHTOF(UI\Icon_Module_Wind_ca.paa)); category = "ACE"; function = QUOTE(DFUNC(initModuleSettings)); @@ -12,41 +12,44 @@ class CfgVehicles { author = "$STR_ACE_Common_ACETeam"; class Arguments { class enableServerController { - displayName = "Weather propagation"; - description = "Enables sever side weather propagation"; + displayName = "$STR_ACE_Weather_enableServerController_DisplayName"; + description = "$STR_ACE_Weather_enableServerController_Description"; typeName = "BOOL"; defaultValue = 1; }; class useACEWeather { - displayName = "ACE Weather"; - description = "Overrides the default weather (editor, mission settings) with ACE weather (map based)"; + displayName = "$STR_ACE_Weather_useACEWeather_DisplayName"; + description = "$STR_ACE_Weather_useACEWeather_Description"; typeName = "BOOL"; defaultValue = 1; }; class syncRain { - displayName = "Sync Rain"; - description = "Synchronizes rain"; + displayName = "$STR_ACE_Weather_syncRain_DisplayName"; + description = "$STR_ACE_Weather_syncRain_Description"; typeName = "BOOL"; defaultValue = 1; }; class syncWind { - displayName = "Sync Wind"; - description = "Synchronizes wind"; + displayName = "$STR_ACE_Weather_syncWind_DisplayName"; + description = "$STR_ACE_Weather_syncWind_Description"; typeName = "BOOL"; defaultValue = 1; }; class syncMisc { - displayName = "Sync Misc"; - description = "Synchronizes lightnings, rainbow, fog, ..."; + displayName = "$STR_ACE_Weather_syncMisc_DisplayName"; + description = "$STR_ACE_Weather_syncMisc_Description"; typeName = "BOOL"; defaultValue = 1; }; class serverUpdateInterval { - displayName = "Update Interval"; - description = "Defines the interval (seconds) between weather updates"; + displayName = "$STR_ACE_Weather_serverUpdateInterval_DisplayName"; + description = "$STR_ACE_Weather_serverUpdateInterval_Description"; typeName = "NUMBER"; defaultValue = 60; }; }; + class ModuleDescription { + description = "$STR_ACE_Weather_Module_Description"; + }; }; -}; +}; \ No newline at end of file diff --git a/addons/weather/stringtable.xml b/addons/weather/stringtable.xml index 2008fc7bc1..02c0964e03 100644 --- a/addons/weather/stringtable.xml +++ b/addons/weather/stringtable.xml @@ -13,5 +13,61 @@ <Czech>Zobrazit informace o větru</Czech> <Portuguese>Mostrar informação do vento</Portuguese> </Key> + <Key ID="STR_ACE_Weather_Module_DisplayName"> + <English>Weather</English> + <Polish>Pogoda</Polish> + </Key> + <Key ID="STR_ACE_Weather_Module_Description"> + <English>Multiplayer synchronized ACE weather module</English> + <Polish>Synchronizowana pogoda ACE</Polish> + </Key> + <Key ID="STR_ACE_Weather_enableServerController_DisplayName"> + <English>Weather propagation</English> + <Polish>Zmiany pogody</Polish> + </Key> + <Key ID="STR_ACE_Weather_enableServerController_Description"> + <English>Enables server side weather propagation</English> + <Polish>Aktywuje zmiany pogody po stronie serwera</Polish> + </Key> + <Key ID="STR_ACE_Weather_useACEWeather_DisplayName"> + <English>ACE Weather</English> + <Polish>Pogoda ACE</Polish> + </Key> + <Key ID="STR_ACE_Weather_useACEWeather_Description"> + <English>Overrides the default weather (editor, mission settings) with ACE weather (map based)</English> + <Polish>Nadpisuje domyślne ustawienia pogody (edytor, wywiad) przy użyciu pogody ACE (zależna od mapy)</Polish> + </Key> + <Key ID="STR_ACE_Weather_syncRain_DisplayName"> + <English>Sync Rain</English> + <Polish>Synchronizuj deszcz</Polish> + </Key> + <Key ID="STR_ACE_Weather_syncRain_Description"> + <English>Synchronizes rain</English> + <Polish>Synchronizuje deszcz</Polish> + </Key> + <Key ID="STR_ACE_Weather_syncWind_DisplayName"> + <English>Sync Wind</English> + <Polish>Synchronizuj wiatr</Polish> + </Key> + <Key ID="STR_ACE_Weather_syncWind_Description"> + <English>Synchronizes wind</English> + <Polish>Synchronizuje wiatr</Polish> + </Key> + <Key ID="STR_ACE_Weather_syncMisc_DisplayName"> + <English>Sync Misc</English> + <Polish>Synchronizuj różne</Polish> + </Key> + <Key ID="STR_ACE_Weather_syncMisc_Description"> + <English>Synchronizes lightnings, rainbow, fog, ...</English> + <Polish>Synchronizuje pioruny, tęcze, mgłę, ...</Polish> + </Key> + <Key ID="STR_ACE_Weather_serverUpdateInterval_DisplayName"> + <English>Update Interval</English> + <Polish>Interwał aktualizacji</Polish> + </Key> + <Key ID="STR_ACE_Weather_serverUpdateInterval_Description"> + <English>Defines the interval (seconds) between weather updates</English> + <Polish>Określa interwał (sekundy) pomiędzy aktualizacjami pogody</Polish> + </Key> </Package> </Project> \ No newline at end of file diff --git a/addons/winddeflection/CfgVehicles.hpp b/addons/winddeflection/CfgVehicles.hpp index 1c24c0a386..2ce9421071 100644 --- a/addons/winddeflection/CfgVehicles.hpp +++ b/addons/winddeflection/CfgVehicles.hpp @@ -2,7 +2,7 @@ class CfgVehicles { class ACE_Module; class GVAR(ModuleSettings): ACE_Module { scope = 2; - displayName = "Wind Deflection"; + displayName = "$STR_ACE_WEATHER_WINDDEFLECTION_DISPLAYNAME"; //WIND DEFLECTION icon = QUOTE(PATHTOF(UI\Icon_Module_Wind_ca.paa)); category = "ACE"; function = QUOTE(DFUNC(initModuleSettings)); @@ -12,29 +12,32 @@ class CfgVehicles { author = "$STR_ACE_Common_ACETeam"; class Arguments { class enabled { - displayName = "Wind Deflection"; - description = "Enables wind deflection"; + displayName = "$STR_ACE_WEATHER_DEFLECTIONMODULE_DISPLAYNAME"; + description = "$STR_ACE_WEATHER_DEFLECTIONMODULE_DESCRIPTION"; typeName = "BOOL"; defaultValue = 1; }; class vehicleEnabled { - displayName = "Vehicle Enabled"; - description = "Enables wind deflection for static/vehicle gunners"; + displayName = "$STR_ACE_WEATHER_VEHICLEENABLED_DISPLAYNAME"; + description = "$STR_ACE_WEATHER_VEHICLEENABLED_DESCRIPTION"; typeName = "BOOL"; defaultValue = 1; }; class simulationInterval { - displayName = "Simulation Interval"; - description = "Defines the interval between every calculation step"; + displayName = "$STR_ACE_WEATHER_SIMULATIONINTERVAL_DISPLAYNAME"; + description = "$STR_ACE_WEATHER_SIMULATIONINTERVAL_DESCRIPTION"; typeName = "NUMBER"; defaultValue = 0.05; }; class simulationRadius { - displayName = "Simulation Radius"; - description = "Defines the radius around the player (in meters) at which projectiles are wind deflected"; + displayName = "$STR_ACE_WEATHER_SIMULATIONRADIUS_DISPLAYNAME"; + description = "$STR_ACE_WEATHER_SIMULATIONRADIUS_DESCRIPTION"; typeName = "NUMBER"; defaultValue = 3000; }; }; + class ModuleDescription { + description = "$STR_ACE_WEATHER_WINDDEFLECTION_DESCRIPTION"; + }; }; -}; +}; \ No newline at end of file diff --git a/addons/winddeflection/stringtable.xml b/addons/winddeflection/stringtable.xml index 4ebcc81bee..515591bd32 100644 --- a/addons/winddeflection/stringtable.xml +++ b/addons/winddeflection/stringtable.xml @@ -62,6 +62,46 @@ <Italian>Umidità: %1%</Italian> <Portuguese>Humidade: %1%</Portuguese> </Key> + <Key ID="STR_ACE_WEATHER_WINDDEFLECTION_DISPLAYNAME"> + <English>Wind Deflection</English> + <Polish>Wpływ wiatru</Polish> + </Key> + <Key ID="STR_ACE_WEATHER_DEFLECTIONMODULE_DISPLAYNAME"> + <English>Wind Deflection</English> + <Polish>Wpływ wiatru</Polish> + </Key> + <Key ID="STR_ACE_WEATHER_DEFLECTIONMODULE_DESCRIPTION"> + <English>Enables wind deflection</English> + <Polish>Aktywuje wpływ wiatru na trajektorię lotu pocisków</Polish> + </Key> + <Key ID="STR_ACE_WEATHER_VEHICLEENABLED_DISPLAYNAME"> + <English>Vehicle Enabled</English> + <Polish>Włączone dla pojazdów</Polish> + </Key> + <Key ID="STR_ACE_WEATHER_VEHICLEENABLED_DESCRIPTION"> + <English>Enables wind deflection for static/vehicle gunners</English> + <Polish>Aktywuje wpływ wiatru na trajektorię lotu pocisków dla broni statycznej i na pojazdach</Polish> + </Key> + <Key ID="STR_ACE_WEATHER_SIMULATIONINTERVAL_DISPLAYNAME"> + <English>Simulation Interval</English> + <Polish>Interwał symulacji</Polish> + </Key> + <Key ID="STR_ACE_WEATHER_SIMULATIONINTERVAL_DESCRIPTION"> + <English>Defines the interval between every calculation step</English> + <Polish>Określa interwał pomiędzy każdym krokiem kalkulacji</Polish> + </Key> + <Key ID="STR_ACE_WEATHER_SIMULATIONRADIUS_DISPLAYNAME"> + <English>Simulation Radius</English> + <Polish>Zasięg symulacji</Polish> + </Key> + <Key ID="STR_ACE_WEATHER_SIMULATIONRADIUS_DESCRIPTION"> + <English>Defines the radius around the player (in meters) at which projectiles are wind deflected</English> + <Polish>Określa obszar naokoło gracza (w metrach), na którym pociski są znoszone przez wiatr</Polish> + </Key> + <Key ID="STR_ACE_WEATHER_WINDDEFLECTION_DESCRIPTION"> + <English>Wind influence on projectiles trajectory</English> + <Polish>Wpływ wiatru na trajektorię lotu pocisków</Polish> + </Key> </Container> </Package> </Project> From 156bba33213e09f8a6a9368d86ae6fdad151ed2f Mon Sep 17 00:00:00 2001 From: Grzegorz Sikora <gienkov.grzegorz@gmail.com> Date: Sat, 9 May 2015 20:37:57 +0200 Subject: [PATCH 26/51] Yes/No to BOOL Conflicts: addons/common/CfgVehicles.hpp addons/common/stringtable.xml addons/explosives/stringtable.xml addons/hearing/CfgVehicles.hpp addons/hearing/stringtable.xml addons/interaction/stringtable.xml addons/map/CfgVehicles.hpp addons/map/stringtable.xml addons/medical/CfgVehicles.hpp addons/medical/stringtable.xml addons/nametags/stringtable.xml addons/respawn/stringtable.xml addons/switchunits/CfgVehicles.hpp addons/switchunits/stringtable.xml Conflicts: addons/common/CfgVehicles.hpp addons/common/stringtable.xml addons/explosives/stringtable.xml addons/hearing/stringtable.xml addons/interaction/stringtable.xml addons/map/CfgVehicles.hpp addons/map/stringtable.xml addons/medical/CfgVehicles.hpp addons/medical/stringtable.xml addons/nametags/stringtable.xml addons/respawn/stringtable.xml addons/switchunits/CfgVehicles.hpp addons/switchunits/stringtable.xml --- addons/common/CfgVehicles.hpp | 14 ++------- addons/common/stringtable.xml | 22 +++++--------- addons/explosives/CfgModule.hpp | 24 ++------------- addons/explosives/stringtable.xml | 24 +++++---------- addons/hearing/CfgVehicles.hpp | 11 +++---- addons/hearing/stringtable.xml | 12 ++------ addons/interaction/CfgVehicles.hpp | 5 +--- addons/interaction/stringtable.xml | 38 +++++++---------------- addons/map/CfgVehicles.hpp | 26 ++++------------ addons/map/stringtable.xml | 8 ----- addons/medical/CfgVehicles.hpp | 44 ++++----------------------- addons/medical/stringtable.xml | 48 ++++++++++-------------------- addons/nametags/CfgVehicles.hpp | 5 +--- addons/nametags/stringtable.xml | 34 ++++++++------------- addons/respawn/CfgVehicles.hpp | 12 ++------ addons/respawn/stringtable.xml | 10 ------- addons/switchunits/CfgVehicles.hpp | 25 ++++------------ addons/switchunits/stringtable.xml | 8 ----- 18 files changed, 85 insertions(+), 285 deletions(-) diff --git a/addons/common/CfgVehicles.hpp b/addons/common/CfgVehicles.hpp index 70d84b376c..65bf2d7058 100644 --- a/addons/common/CfgVehicles.hpp +++ b/addons/common/CfgVehicles.hpp @@ -61,17 +61,7 @@ class CfgVehicles { displayName = "$STR_ACE_Common_CheckPBO_CheckAll_DisplayName"; description = "$STR_ACE_Common_CheckPBO_CheckAll_Description"; typeName = "BOOL"; - class values { - class WarnOnce { - default = 1; - name = "$STR_ACE_Common_CheckPBO_CheckAll_No"; - value = 0; - }; - class Warn { - name = "$STR_ACE_Common_CheckPBO_CheckAll_Yes"; - value = 1; - }; - }; + defaultValue = 0; }; class Whitelist { displayName = "$STR_ACE_Common_CheckPBO_Whitelist_DisplayName"; @@ -134,4 +124,4 @@ class CfgVehicles { }; }; }; -}; +}; \ No newline at end of file diff --git a/addons/common/stringtable.xml b/addons/common/stringtable.xml index 4ddc0112d8..5b908a9133 100644 --- a/addons/common/stringtable.xml +++ b/addons/common/stringtable.xml @@ -275,7 +275,7 @@ <French>Désactiver menu commande</French> <Russian>Выключить командное меню</Russian> <Hungarian>Parancsnoki menü kikapcsolása</Hungarian> - <Italian>Disabilita menù di comando</Italian> + <Italian>Disabilita Menù di comando</Italian> <Portuguese>Desabilitar menu de comando</Portuguese> </Key> <Key ID="STR_ACE_Common_Unknown"> @@ -308,11 +308,11 @@ <Spanish>Aceptar peticiones</Spanish> <Polish>Akceptuj prośby</Polish> <Czech>Přijmout žádost</Czech> + <Italian>Accetta Richieste</Italian> <French>Accepter requête</French> <Russian>Принять запросы</Russian> <Hungarian>Kérések elfogadása</Hungarian> <Portuguese>Aceitar Pedido</Portuguese> - <Italian>Accetta la richiesta</Italian> </Key> <Key ID="STR_ACE_ACTION_DECLINE_REQUEST_KEY_TITLE"> <English>Decline Requests</English> @@ -320,11 +320,11 @@ <Spanish>Rechazar peticiones</Spanish> <Polish>Ignoruj prośby</Polish> <Czech>Zamítnout žádost</Czech> + <Italian>Rifiuta Richieste</Italian> <Russian>Отклонить запросы</Russian> <French>Rejeter requête</French> <Hungarian>Kérések elutasítása</Hungarian> <Portuguese>Rejeitar pedido</Portuguese> - <Italian>Rifiuta la richiesta</Italian> </Key> <Key ID="STR_ACE_ACTION_ACCEPT_REQUEST_KEY_TOOLTIP"> <English>Accept Requests send by other players. These can be requests to use / share equipment, perform certain actions.</English> @@ -402,7 +402,7 @@ <English>Hint Background color</English> <German>Hintergrundfarbe der Hinweise</German> <Spanish>Color de fondo de las notificaciones</Spanish> - <Italian>Colore di sfondo dei suggerimenti</Italian> + <Italian>Colore di sfondo dei Suggerimenti</Italian> <Russian>Цвет фона всплывающих подсказок</Russian> <Polish>Kolor tła powiadomień</Polish> <French>Notification: couleur de l'arrière plan</French> @@ -414,7 +414,7 @@ <English>The color of the background from the ACE hints.</English> <German>Die Hintergrundfarbe der ACE-Hinweise.</German> <Spanish>El color de fondo de las notificaciones del ACE</Spanish> - <Italian>Il colore di sfondo dei suggerimenti di ACE.</Italian> + <Italian>Il colore di sfondo dei suggerimenti dell'ACE.</Italian> <Russian>Цвет фона всплывающих подсказок АСЕ.</Russian> <Polish>Kolor tła dla powiadomień ACE</Polish> <French>Notification ACE: couleur de l'arrière plan</French> @@ -426,7 +426,7 @@ <English>Hint text font color</English> <German>Textfarbe der Hinweise</German> <Spanish>Color del texto de las notificaciones</Spanish> - <Italian>Il colore del testo dei suggerimenti</Italian> + <Italian>Il colore del Testo dei Suggerimenti</Italian> <Russian>Цвет шрифта всплывающих подсказок</Russian> <Polish>Kolor tekstu powiadomień</Polish> <French>Notification: couleur du texte</French> @@ -438,7 +438,7 @@ <English>The color of the text font from the ACE hints. This color is the default color for all text displayed through the ACE Hint system, if the hint text has no other color specified.</English> <German>Wähle die Textfarbe für ACE-Hinweise. Die gewählte Farbe wird als Standartfarbe der Hinweise angezeigt, wenn der Hinweis selbst keine spezifische Farbe hat. </German> <Spanish>El color del texto de las notificaciones del ACE. Este es el color predeterminado para todo el texto que se muestra a través del sistema de notificaciones del ACE, si el texto de notificación no tiene otro color especificado.</Spanish> - <Italian>Il colore del testo dei suggerimenti di ACE. Questo è il colore predefinito per tutto il testo mostrato dal sistema di suggerimenti di ACE quando il colore del testo non ha altro colore specificato.</Italian> + <Italian>Il colore del testo dei suggerimenti dell'ACE. Questo è il colore standard per tutti i caratteri mostrati dal sistema di suggerimenti dell'ACE, se il colore del testo non è specificato.</Italian> <Russian>Цвет шрифта текста всплывающих подсказок АСЕ. Этот цвет является стандартным для всего текста, транслирующегося через систему подсказок АСЕ, если не установлено другого цвета для текста подсказок.</Russian> <Polish>Kolor tekstu dla powiadomień ACE. Ten kolor jest domyślnym dla wszystkich tekstów wyświetlanych poprzez System Powiadomień ACE, jeżeli dla powiadomienia nie określono innego koloru.</Polish> <French>Notification ACE: couleur du texte. C'est la couleur par défaut de tout texte affiché dans les notifications ACE, si aucune couleur n'est spécifiée pour les notifications</French> @@ -506,14 +506,6 @@ <English>Check all addons instead of only those of ACE?</English> <Polish>Sprawdzaj wszystkie addony czy tylko te z ACE?</Polish> </Key> - <Key ID="STR_ACE_Common_CheckPBO_CheckAll_No"> - <English>No</English> - <Polish>Tylko ACE</Polish> - </Key> - <Key ID="STR_ACE_Common_CheckPBO_CheckAll_Yes"> - <English>Yes</English> - <Polish>Wszystkie</Polish> - </Key> <Key ID="STR_ACE_Common_CheckPBO_Whitelist_DisplayName"> <English>Whitelist</English> <Polish>Biała lista</Polish> diff --git a/addons/explosives/CfgModule.hpp b/addons/explosives/CfgModule.hpp index 50b59fc55d..9159babc2d 100644 --- a/addons/explosives/CfgModule.hpp +++ b/addons/explosives/CfgModule.hpp @@ -15,33 +15,13 @@ class ACE_ModuleExplosive: Module_F { displayName = "$STR_ACE_Explosive_RequireSpecialist_DisplayName"; description = "$STR_ACE_Explosive_RequireSpecialist_Description"; typeName = "BOOL"; - class values { - class Yes { - name = "$STR_ACE_Explosive_Yes"; - value = 1; - }; - class No { - default = 1; - name = "$STR_ACE_Explosive_No"; - value = 0; - }; - }; + defaultValue = 0; }; class PunishNonSpecialists { displayName = "$STR_ACE_Explosive_PunishNonSpecialists_DisplayName"; description = "$STR_ACE_Explosive_PunishNonSpecialists_Description"; typeName = "BOOL"; - class values { - class Yes { - default = 1; - name = "$STR_ACE_Explosive_Yes"; - value = 1; - }; - class No { - name = "$STR_ACE_Explosive_No"; - value = 0; - }; - }; + defaultValue = 1; }; }; class ModuleDescription: ModuleDescription { diff --git a/addons/explosives/stringtable.xml b/addons/explosives/stringtable.xml index 5eb5d28512..42b5160030 100644 --- a/addons/explosives/stringtable.xml +++ b/addons/explosives/stringtable.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project name="ACE"> <Package name="Explosives"> <Key ID="STR_ACE_Explosives_Menu"> @@ -368,7 +368,7 @@ <Polish>Wybierz zapalnik</Polish> <French>Sélectionner une mise à feu</French> <Czech>Zvolit Detonátor</Czech> - <Italian>Seleziona un attivatore</Italian> + <Italian>Seleziona un Attivatore</Italian> <Hungarian>Gyújtóeszköz kiválasztása</Hungarian> <Portuguese>Selecionar um Gatilho</Portuguese> <Russian>Выберите детонатор</Russian> @@ -392,7 +392,7 @@ <German>Druckplatte</German> <French>Plaque de pression</French> <Czech>Nášlapná nástraha</Czech> - <Italian>Piastra a pressione</Italian> + <Italian>Piastra a Pressione</Italian> <Hungarian>Nyomólap</Hungarian> <Portuguese>Placa de pressão</Portuguese> <Russian>Нажимная плита</Russian> @@ -404,7 +404,7 @@ <German>Stolperdraht</German> <French>Fil de détente</French> <Czech>Nástražný drát</Czech> - <Italian>Filo a inciampo</Italian> + <Italian>Filo a Inciampo</Italian> <Hungarian>Botlódrót</Hungarian> <Portuguese>Linha de tração</Portuguese> <Russian>Растяжка</Russian> @@ -440,7 +440,7 @@ <German>Infrarotsensor (Seitenangriff)</German> <French>Capteur IR (de flanc)</French> <Czech>IR Značkovač (Výbuch stranou)</Czech> - <Italian>Sensore IR (attacco laterale)</Italian> + <Italian>Sensore IR (Attacco laterale)</Italian> <Hungarian>Infravörös szenzor (Side Attack)</Hungarian> <Portuguese>Sensor infravermelho (ataque lateral)</Portuguese> <Russian>ИК сенсор (детонация вбок)</Russian> @@ -452,7 +452,7 @@ <German>Magnetfeldsensor (Bodenangriff)</German> <French>Capteur magnétique (par le bas)</French> <Czech>Magnetický Senzor (Výbuch ze spoda)</Czech> - <Italian>Sensore Magnetico di Prossimità (attacco inferiore)</Italian> + <Italian>Sensore Magnetico di Prossimità (Attacco inferiore)</Italian> <Hungarian>Mágneses mező érzékelő (Bottom Attack)</Hungarian> <Portuguese>Influência magnética (ataque inferior)</Portuguese> <Russian>Магнитный сенсор (детонация вверх)</Russian> @@ -462,7 +462,7 @@ <German>Keine Sprengladungen auf diesem Auslöser.</German> <Spanish>Ningún explosivo en el detonador.</Spanish> <French>Pas d'explosif à mettre à feu.</French> - <Italian>Nessun esplosivo</Italian> + <Italian>Nessun esplosivo sul sensore.</Italian> <Czech>Žádná výbušnina k odpálení.</Czech> <Hungarian>Nincs robbanóanyag a gyújtóeszközhöz kötve.</Hungarian> <Polish>Brak ładunków na zapalnik.</Polish> @@ -491,7 +491,7 @@ <Hungarian>Robbanóanyagok távoli robbantásához</Hungarian> <Portuguese>Usado para detonar remotamente o explosivo quando solto.</Portuguese> <Russian>Используется для дистанционного подрыва, после смерти оператора.</Russian> - <Italian>Usato per attivare a distanza esplosivi al momento del rilascio</Italian> + <Italian>Usato per attivare esplosivi al momento del rilascio</Italian> </Key> <Key ID="STR_ACE_Explosives_Pickup"> <English>Pick up</English> @@ -517,14 +517,6 @@ <English>Require explosive specialists to disable explosives? Default: No</English> <Polish>Wymagać saperów do rozbrajania ładunków wybuchowych? Domyślnie: Nie</Polish> </Key> - <Key ID="STR_ACE_Explosive_Yes"> - <English>Yes</English> - <Polish>Tak</Polish> - </Key> - <Key ID="STR_ACE_Explosive_No"> - <English>No</English> - <Polish>Nie</Polish> - </Key> <Key ID="STR_ACE_Explosive_PunishNonSpecialists_DisplayName"> <English>Punish non-specialists?</English> <Polish>Karaj nie-specjalistów?</Polish> diff --git a/addons/hearing/CfgVehicles.hpp b/addons/hearing/CfgVehicles.hpp index d20d067981..6cec04a242 100644 --- a/addons/hearing/CfgVehicles.hpp +++ b/addons/hearing/CfgVehicles.hpp @@ -98,20 +98,17 @@ class CfgVehicles { class ACE_ModuleHearing: Module_F { author = "$STR_ACE_Common_ACETeam"; category = "ACE"; - displayName = "$STR_ACE_Hearing_Module_DisplayName"; //Hearing + displayName = "$STR_ACE_Hearing_Module_DisplayName"; function = QFUNC(moduleHearing); scope = 2; isGlobal = 1; icon = PATHTOF(UI\Icon_Module_Hearing_ca.paa); class Arguments { class EnableCombatDeafness { - displayName = "$STR_ACE_Hearing_CombatDeafness_DisplayName"; //Enable combat deafness? - description = "$STR_ACE_Hearing_CombatDeafness_Description"; //Enable combat deafness? + displayName = "$STR_ACE_Hearing_CombatDeafness_DisplayName"; + description = "$STR_ACE_Hearing_CombatDeafness_Description"; typeName = "BOOL"; - class values { - class Yes { name = "$STR_ACE_Hearing_CombatDeafness_Yes"; value = 1; default = 1; }; //yes - class No { name = "$STR_ACE_Hearing_CombatDeafness_No"; value = 0; }; //no - }; + defaultValue = 1; }; }; class ModuleDescription { diff --git a/addons/hearing/stringtable.xml b/addons/hearing/stringtable.xml index e532768fd9..ae7bea38a2 100644 --- a/addons/hearing/stringtable.xml +++ b/addons/hearing/stringtable.xml @@ -106,7 +106,7 @@ <Czech>Vypnout pískání v uších</Czech> <Polish>Wyłącz dzwonienie w uszach</Polish> <Hungarian>Fülcsengés letiltása</Hungarian> - <Italian>Disabilita i fischi nelle orecchie</Italian> + <Italian>Disabilita il ronzio</Italian> <Portuguese>Desabilitar zumbido de ouvidos</Portuguese> </Key> <Key ID="STR_ACE_Hearing_Module_DisplayName"> @@ -121,17 +121,9 @@ <English>Enable combat deafness?</English> <Polish>Możliwość chwilowej utraty słuchu przy głośnych wystrzałach i jednoczesnym braku włożonych stoperów</Polish> </Key> - <Key ID="STR_ACE_Hearing_CombatDeafness_Yes"> - <English>Yes</English> - <Polish>Tak</Polish> - </Key> - <Key ID="STR_ACE_Hearing_CombatDeafness_No"> - <English>No</English> - <Polish>Nie</Polish> - </Key> <Key ID="STR_ACE_Hearing_Module_Description"> <English></English> <Polish>Głuchota bojowa pojawia się w momentach, kiedy stoimy w pobliżu broni wielkokalibrowej bez ochrony słuchu, lub np. podczas ostrzału artyleryjskiego. Moduł ten pozwala na włączenie lub wyłączenie tego efektu.</Polish> </Key> </Package> -</Project> +</Project> \ No newline at end of file diff --git a/addons/interaction/CfgVehicles.hpp b/addons/interaction/CfgVehicles.hpp index 9968c490e1..03466c1986 100644 --- a/addons/interaction/CfgVehicles.hpp +++ b/addons/interaction/CfgVehicles.hpp @@ -14,10 +14,7 @@ class CfgVehicles { displayName = "$STR_ACE_InteractionSystem_EnableTeamManagement_DisplayName"; description = "$STR_ACE_InteractionSystem_EnableTeamManagement_Description"; typeName = "BOOL"; - class values { - class Yes { default = 1; name = "$STR_ACE_InteractionSystem_EnableTeamManagement_Yes"; value = 1;}; - class No { name = "$STR_ACE_InteractionSystem_EnableTeamManagement_No"; value = 0; }; - }; + defaultValue = 1; }; }; class ModuleDescription { diff --git a/addons/interaction/stringtable.xml b/addons/interaction/stringtable.xml index 153b94a1d9..0e6e89b74c 100644 --- a/addons/interaction/stringtable.xml +++ b/addons/interaction/stringtable.xml @@ -1,4 +1,4 @@ -<?xml version="1.0" encoding="utf-8"?> +<?xml version="1.0" encoding="utf-8"?> <Project name="ACE"> <Package name="Interaction"> <Key ID="STR_ACE_Interaction_MainAction"> @@ -119,7 +119,7 @@ <Russian>Меню взаимодействия (с собой)</Russian> <Hungarian>Cselekvő menü (saját) </Hungarian> <Portuguese>Menu de Interação (Individual)</Portuguese> - <Italian>Menù interazione (individuale)</Italian> + <Italian>Menù interazione (Individuale)</Italian> </Key> <Key ID="STR_ACE_Interaction_OpenDoor"> <English>Open / Close Door</English> @@ -263,7 +263,7 @@ <Russian>Жесты</Russian> <Hungarian>Kézjelek</Hungarian> <Portuguese>Gestos</Portuguese> - <Italian>Gesti</Italian> + <Italian>Segnali gestuali</Italian> </Key> <Key ID="STR_ACE_Interaction_Gestures_Attack"> <English>Attack</English> @@ -443,7 +443,7 @@ <Czech>Někdo tě poklepal na PRAVÉ rameno</Czech> <Russian>Вас похлопали по ПРАВОМУ плечу</Russian> <Portuguese>Você foi tocado no ombro</Portuguese> - <Italian>Ti è stato dato un colpetto sulla spalla destra</Italian> + <Italian>Ti è stato dato un colpetto sulla spalla</Italian> </Key> <Key ID="STR_ACE_Interaction_YouWereTappedLeft"> <English>You were tapped on the LEFT shoulder.</English> @@ -455,7 +455,7 @@ <Czech>Někdo tě poklepal na LEVÉ rameno</Czech> <Russian>Вас похлопали по ЛЕВОМУ плечу</Russian> <Portuguese>Você foi tocado no ombro.</Portuguese> - <Italian>Ti è stato dato un colpetto sulla spalla sinistra</Italian> + <Italian>Ti è stato dato un colpetto sulla spalla</Italian> </Key> <Key ID="STR_ACE_Interaction_CancelSelection"> <English>Cancel</English> @@ -503,7 +503,7 @@ <Hungarian>A földre!</Hungarian> <Russian>Ложись!</Russian> <Portuguese>Abaixe-se!</Portuguese> - <Italian>A terra!</Italian> + <Italian>A Terra!</Italian> </Key> <Key ID="STR_ACE_Interaction_TeamManagement"> <English>Team Management</English> @@ -575,7 +575,6 @@ <Czech>Přiřadit k červeným</Czech> <Russian>Назначить в Красную группу</Russian> <French>Assigner à rouge</French> - <Italian>Assegna al team rosso</Italian> </Key> <Key ID="STR_ACE_Interaction_AssignTeamGreen"> <English>Assign Green</English> @@ -587,7 +586,6 @@ <Czech>Přiřadit k zeleným</Czech> <Russian>Назначить в Зеленую группу</Russian> <French>Assigner à vert</French> - <Italian>Assegna al team verde</Italian> </Key> <Key ID="STR_ACE_Interaction_AssignTeamBlue"> <English>Assign Blue</English> @@ -599,7 +597,6 @@ <Czech>Přiřadit k modrým</Czech> <Russian>Назначить в Синюю группу</Russian> <French>Assigner à bleu</French> - <Italian>Assegna al team blu</Italian> </Key> <Key ID="STR_ACE_Interaction_AssignTeamYellow"> <English>Assign Yellow</English> @@ -611,7 +608,6 @@ <Czech>Přiřadit ke žlutým</Czech> <Russian>Назначить в Желтую группу</Russian> <French>Assigner à jaune</French> - <Italian>Assegna al team giallo</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamRed"> <English>Join Red</English> @@ -623,7 +619,6 @@ <Czech>Připojit k červeným</Czech> <Russian>Присоединиться к Красной группе</Russian> <French>Rejoindre rouge</French> - <Italian>Unirsi al team rosso</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamGreen"> <English>Join Green</English> @@ -635,7 +630,6 @@ <Czech> Připojit k zeleným</Czech> <Russian>Присоединиться к Зеленой группе</Russian> <French>Rejoindre vert</French> - <Italian>Unirsi al team verde</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamBlue"> <English>Join Blue</English> @@ -647,7 +641,6 @@ <Czech>Připojit k modrým</Czech> <Russian>Присоединиться к Синей группе</Russian> <French>Rejoindre bleu</French> - <Italian>Unirsi al team blu</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamYellow"> <English>Join Yellow</English> @@ -659,7 +652,6 @@ <Czech>Připojit ke žlutým</Czech> <Russian>Присоединиться к Жёлтой группе</Russian> <French>Rejoindre jaune</French> - <Italian>Unirsi al team giallo</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinedTeam"> <English>You joined Team %1</English> @@ -729,7 +721,7 @@ <Spanish>Tecla modificadora</Spanish> <Russian>Клавиша-модификатор</Russian> <Portuguese>Tecla Modificadora</Portuguese> - <Italian>Tasto modifica</Italian> + <Italian>Modifica tasto</Italian> <Hungarian>Módosító billentyű</Hungarian> <Czech>Modifikátor</Czech> </Key> @@ -743,7 +735,7 @@ <Hungarian>Hatótávolságon kívül</Hungarian> <Polish>Poza zasięgiem</Polish> <Czech>Mimo dosah</Czech> - <Italian>Fuori limite</Italian> + <Italian>Non in raggio</Italian> </Key> <Key ID="STR_ACE_Interaction_Equipment"> <English>Equipment</English> @@ -766,8 +758,8 @@ <Czech>Odstrčit</Czech> <Hungarian>Tolás</Hungarian> <Russian>Толкать</Russian> + <Italian>Spingi</Italian> <Portuguese>Empurrar</Portuguese> - <Italian>Spingere</Italian> </Key> <Key ID="STR_ACE_Interaction_Interact"> <English>Interact</English> @@ -778,7 +770,7 @@ <Polish>Interakcja</Polish> <Spanish>Interactuar</Spanish> <Hungarian>Cselekvés</Hungarian> - <Italian>Interagire</Italian> + <Italian>Interagisci</Italian> <Portuguese>Interagir</Portuguese> </Key> <Key ID="STR_ACE_Interaction_Passengers"> @@ -805,17 +797,9 @@ <English>Should players be allowed to use the Team Management Menu? Default: Yes</English> <Polish>Czy gracze mogą korzystać z menu zarządzania drużyną? Domyślnie: Tak</Polish> </Key> - <Key ID="STR_ACE_InteractionSystem_EnableTeamManagement_Yes"> - <English>Yes</English> - <Polish>Tak</Polish> - </Key> - <Key ID="STR_ACE_InteractionSystem_EnableTeamManagement_No"> - <English>No</English> - <Polish>Nie</Polish> - </Key> <Key ID="STR_ACE_InteractionSystem_Module_Description"> <English></English> <Polish>Na zarządzanie drużyną składa się: przydział kolorów dla członków drużyny, przejmowanie dowodzenia, dołączanie/opuszczanie drużyn.</Polish> </Key> </Package> -</Project> +</Project> \ No newline at end of file diff --git a/addons/map/CfgVehicles.hpp b/addons/map/CfgVehicles.hpp index 150ac23930..849549e3d1 100644 --- a/addons/map/CfgVehicles.hpp +++ b/addons/map/CfgVehicles.hpp @@ -13,37 +13,25 @@ class CfgVehicles { displayName = "$STR_ACE_Map_MapIllumination_DisplayName"; description = "$STR_ACE_Map_MapIllumination_Description"; typeName = "BOOL"; - class values { - class Yes { name = "$STR_ACE_Map_Yes"; value = 1; default = 1; }; - class No { name = "$STR_ACE_Map_No"; value = 0; }; - }; + defaultValue = 1; }; class MapShake { displayName = "$STR_ACE_Map_MapShake_DisplayName"; description = "$STR_ACE_Map_MapShake_Description"; typeName = "BOOL"; - class values { - class Yes { name = "$STR_ACE_Map_Yes"; value = 1; default = 1;}; - class No { name = "$STR_ACE_Map_No"; value = 0; }; - }; + defaultValue = 1; }; class MapLimitZoom { displayName = "$STR_ACE_Map_MapLimitZoom_DisplayName"; description = "$STR_ACE_Map_MapLimitZoom_Description"; typeName = "BOOL"; - class values { - class Yes { name = "$STR_ACE_Map_Yes"; value = 1; }; - class No { name = "$STR_ACE_Map_No"; value = 0; default = 1;}; - }; + defaultValue = 0; }; class MapShowCursorCoordinates { displayName = "$STR_ACE_Map_MapShowCursorCoordinates_DisplayName"; description = "$STR_ACE_Map_MapShowCursorCoordinates_Description"; typeName = "BOOL"; - class values { - class Yes { name = "$STR_ACE_Map_Yes"; value = 1; }; - class No { name = "$STR_ACE_Map_No"; value = 0; default = 1;}; - }; + defaultValue = 0; }; }; class ModuleDescription { @@ -63,16 +51,14 @@ class CfgVehicles { class Interval { displayName = "$STR_ACE_Map_BFT_Interval_DisplayName"; description = "$STR_ACE_Map_BFT_Interval_Description"; + typeName = "NUMBER"; defaultValue = 1; }; class HideAiGroups { displayName = "$STR_ACE_Map_BFT_HideAiGroups_DisplayName"; description = "$STR_ACE_Map_BFT_HideAiGroups_Description"; typeName = "BOOL"; - class values { - class Yes { name = "$STR_ACE_Map_Yes"; value = 1; }; - class No { name = "$STR_ACE_Map_No"; value = 0; default = 1; }; - }; + defaultValue = 0; }; }; class ModuleDescription { diff --git a/addons/map/stringtable.xml b/addons/map/stringtable.xml index 0c25016653..c93ff4c286 100644 --- a/addons/map/stringtable.xml +++ b/addons/map/stringtable.xml @@ -13,14 +13,6 @@ <English>Calculate dynamic map illumination based on light conditions?</English> <Polish>Oblicza dynamiczne oświetlenie mapy bazujące na warunkach oświetleniowych</Polish> </Key> - <Key ID="STR_ACE_Map_Yes"> - <English>Yes</English> - <Polish>Tak</Polish> - </Key> - <Key ID="STR_ACE_Map_No"> - <English>No</English> - <Polish>Nie</Polish> - </Key> <Key ID="STR_ACE_Map_MapShake_DisplayName"> <English>Map shake?</English> <Polish>Drżenie mapy</Polish> diff --git a/addons/medical/CfgVehicles.hpp b/addons/medical/CfgVehicles.hpp index aac43de0ed..6c37c5cfd9 100644 --- a/addons/medical/CfgVehicles.hpp +++ b/addons/medical/CfgVehicles.hpp @@ -191,11 +191,8 @@ class CfgVehicles { class consumeItem_PAK { displayName = "$STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_DisplayName"; description = "$STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_Description"; - typeName = "NUMBER"; - class values { - class keep { name = "$STR_ACE_Medical_No"; value = 0; }; - class remove { name = "$STR_ACE_Medical_Yes"; value = 1; default = 1; }; - }; + typeName = "BOOL"; + defaultValue = 1; }; class useLocation_PAK { displayName = "$STR_ACE_AdvancedMedicalSettings_useLocation_PAK_DisplayName"; @@ -336,18 +333,8 @@ class CfgVehicles { class enabled { displayName = "$STR_ACE_AssignMedicVehicle_enabled_DisplayName"; description = "$STR_ACE_AssignMedicVehicle_enabled_Description"; - typeName = "NUMBER"; - class values { - class none { - name = "$STR_ACE_Medical_No"; - value = 0; - }; - class medic { - name = "$STR_ACE_Medical_Yes"; - value = 1; - default = 1; - }; - }; + typeName = "BOOL"; + defaultValue = 1; }; }; class ModuleDescription { @@ -1016,25 +1003,4 @@ class CfgVehicles { }; }; }; -}; - - - - - - - - - - - - - - - - - - - - - +}; \ No newline at end of file diff --git a/addons/medical/stringtable.xml b/addons/medical/stringtable.xml index 50f3d67110..0eb23d57d4 100644 --- a/addons/medical/stringtable.xml +++ b/addons/medical/stringtable.xml @@ -83,7 +83,7 @@ <French>Injecter de la morphine</French> <Hungarian>Morfium beadása</Hungarian> <Portuguese>Injetar Morfina</Portuguese> - <Italian>Inietta morfina</Italian> + <Italian>Inietta Morfina</Italian> </Key> <Key ID="STR_ACE_Medical_Transfuse_Blood"> <English>Transfuse Blood</English> @@ -95,7 +95,7 @@ <French>Transfusion</French> <Hungarian>Infúzió (vér)</Hungarian> <Portuguese>Transfundir Sangue</Portuguese> - <Italian>Trasfusione di sangue</Italian> + <Italian>Effettua trasfusione di sangue</Italian> </Key> <Key ID="STR_ACE_Medical_Transfuse_Plasma"> <English>Transfuse Plasma</English> @@ -106,7 +106,7 @@ <French>Transfuser du Plasma</French> <Russian>Перелить плазму</Russian> <Hungarian>Infúzió (vérplazma)</Hungarian> - <Italian>Trasfusione di Plasma</Italian> + <Italian>Effettua trasfusione di plasma</Italian> <Portuguese>Transfundir Plasma</Portuguese> </Key> <Key ID="STR_ACE_Medical_Transfuse_Saline"> @@ -118,7 +118,7 @@ <French>Transfuser de la solution saline</French> <Russian>Перелить физраствор</Russian> <Hungarian>Infúzió (sós víz)</Hungarian> - <Italian>Trasfusione di soluzione salina</Italian> + <Italian>Effettua trasfusione di soluzione salina</Italian> <Portuguese>Transfundir Soro</Portuguese> </Key> <Key ID="STR_ACE_Medical_Apply_Tourniquet"> @@ -274,7 +274,7 @@ <French>Transfusion de saline ...</French> <Russian>Переливание физраствора ...</Russian> <Hungarian>Infúzió sós vizzel ...</Hungarian> - <Italian>Effettuo la rasfusione di soluzione salina</Italian> + <Italian>Effettuo la rasfusione di salina</Italian> <Portuguese>Transfundindo Soro...</Portuguese> </Key> <Key ID="STR_ACE_Medical_Transfusing_Plasma"> @@ -370,7 +370,7 @@ <Czech>QuikClot</Czech> <French>Hémostatique</French> <Hungarian>QuikClot</Hungarian> - <Italian>QuikClot (polvere emostatica)</Italian> + <Italian>QuikClot(polvere emostatica)</Italian> <Portuguese>QuikClot</Portuguese> </Key> <Key ID="STR_ACE_Medical_Actions_CheckPulse"> @@ -632,7 +632,7 @@ <Polish>Natychmiastowy</Polish> <French>Urgence Immédiate</French> <German>Sofort</German> - <Czech>Okamžitý</Czech> + <Czech>Okamžiý</Czech> <Hungarian>Azonnali</Hungarian> <Italian>Immediata</Italian> <Portuguese>Imediato</Portuguese> @@ -801,7 +801,7 @@ <French>Bandage fait d'un matériel spécial utilisé pour couvrir une blessure, qui peut etre appliqué dès que le saignement a été stoppé.</French> <Polish>Opatrunek materiałowy, używany do przykrywania ran, zakładany na ranę po zatamowaniu krwawienia.</Polish> <Hungarian>Egy különleges anyagú kötszer sebek betakarására, amelyet a vérzés elállítása után helyeznek fel.</Hungarian> - <Italian>Una benda apposita, utilizzata per coprire una ferita, la quale viene applicata su di essa una volta fermata l'emorragia.</Italian> + <Italian>Una benda apposita, utilizzata per coprire una ferita, la quale è applicata sopra di essa una volta fermata l'emorragia.</Italian> <Portuguese>Uma curativo, material específico para cobrir um ferimento que é aplicado assim que o sangramento é estancando.</Portuguese> <Czech>Obvaz je vhodným způsobem upravený sterilní materiál, určený k překrytí rány, případně k fixaci poranění.</Czech> </Key> @@ -825,7 +825,7 @@ <French>Utilisé pour couvrir des blessures de taille moyenne à grande. Arrête l'hémorragies</French> <Polish>Używany w celu opatrywania średnich i dużych ran oraz tamowania krwawienia.</Polish> <Hungarian>Közepestől nagyig terjedő sebek betakarására és vérzés elállítására használt kötszer</Hungarian> - <Italian>Usato su ferite medie o larghe per fermare emorragie.</Italian> + <Italian>Usato su medie o larghe ferite per fermare emorragie.</Italian> <Portuguese>Usado para o preenchimento de cavidades geradas por ferimentos médios e grandes e estancar o sangramento.</Portuguese> <Czech>Používá se k zastavení středních až silnějších krvácení</Czech> </Key> @@ -850,7 +850,7 @@ <Polish>Bandaż (elastyczny)</Polish> <Czech>Obvaz (elastický)</Czech> <Hungarian>Rögzító kötszer</Hungarian> - <Italian>Benda (elastica)</Italian> + <Italian>Benda (Elastica)</Italian> <Portuguese>Bandagem (Elástica)</Portuguese> </Key> <Key ID="STR_ACE_Medical_Bandage_Elastic_Desc_Short"> @@ -861,7 +861,7 @@ <French>Bandage compressif élastique</French> <Polish>Zestaw bandaży elastycznych.</Polish> <Hungarian>Rugalmas kötszercsomag, "rögzítő"</Hungarian> - <Italian>Kit di bendaggio, elastico</Italian> + <Italian>Kit bendaggio, elastico</Italian> <Portuguese>Kit de Bandagem, Elástica</Portuguese> <Czech>Sada obvazů, Elastická</Czech> </Key> @@ -873,7 +873,7 @@ <Polish>Elastyczna opaska podtrzymująca opatrunek oraz usztywniająca okolice stawów.</Polish> <Spanish>Brinda una compresión uniforme y ofrece soporte extra a una zona lesionada</Spanish> <Hungarian>Egyenletes nyomást és támogatást biztosít a sebesült felületnek.</Hungarian> - <Italian>Permette di comprimere e aiutare la zone ferita.</Italian> + <Italian>Permette di comprimevere e aiutare la zone ferita.</Italian> <Portuguese>Esta bandagem pode ser utilizada para comprimir o ferimento e diminuir o sangramento e garantir que o ferimento não abra em movimento.</Portuguese> <Czech>Hodí se k fixačním účelům a to i v oblastech kloubů.</Czech> </Key> @@ -958,7 +958,7 @@ <German>Atropin Autoinjektor</German> <Czech>Autoinjektor atropin</Czech> <Hungarian>Atropin autoinjektor</Hungarian> - <Italian>Autoiniettore di atropina</Italian> + <Italian>Autoiniettore di Atropina</Italian> <Portuguese>Auto-injetor de Atropina</Portuguese> </Key> <Key ID="STR_ACE_Medical_Atropine_Desc_Short"> @@ -994,7 +994,7 @@ <German>Epiniphrin Autoinjektor</German> <Czech>Autoinjektor adrenalin</Czech> <Hungarian>Epinefrin autoinjektor</Hungarian> - <Italian>Autoiniettore di epinefrina</Italian> + <Italian>Autoiniettore di Epinefrina</Italian> <Portuguese>Auto-injetor de epinefrina</Portuguese> </Key> <Key ID="STR_ACE_Medical_Epinephrine_Desc_Short"> @@ -1271,7 +1271,6 @@ <Hungarian>Elsősegélycsomag, terepen való sebvarráshoz és haladó ellátáshoz</Hungarian> <Portuguese>Kit de primeiros socorros para sutura ou tratamentos avançados</Portuguese> <Czech>Osobní lékárnička obsahuje zdravotnický materiál umožňující šití a pokročilejší ošetřování raněných v poli </Czech> - <Italian>Pronto soccorso personale da campo per mettersi i punti o per trattamenti avanzati.</Italian> </Key> <Key ID="STR_ACE_Medical_Use_Aid_Kit"> <English>Use Personal Aid Kit</English> @@ -1283,7 +1282,6 @@ <Hungarian>Elsősegélycsomag használata</Hungarian> <Portuguese>Usar o kit de primeiros socorros</Portuguese> <Czech>Použít osobní lékárničku</Czech> - <Italian>Usa il pronto soccorso personale</Italian> </Key> <Key ID="STR_ACE_Medical_SurgicalKit_Display"> <English>Surgical Kit</English> @@ -1783,7 +1781,7 @@ </Key> <Key ID="STR_ACE_Medical_lostBlood"> <English>He's lost some blood</English> - <Italian>Ha perso sangue</Italian> + <Italian>Ha perso molto sangue</Italian> <Spanish>Ha perdido un poco de sangre</Spanish> <Russian>Есть кровопотеря</Russian> <German>Er hat etwas Blut verloren</German> @@ -1803,7 +1801,6 @@ <French>Il a perdu beaucoup de sang</French> <Czech>Ztratil hodně krve</Czech> <Portuguese>Ele perdeu muito sangue</Portuguese> - <Italian>Ha perso molto sangue</Italian> </Key> <Key ID="STR_ACE_Medical_noBloodloss"> <English>He hasn't lost blood</English> @@ -2247,7 +2244,6 @@ <Czech>Styl menu (Zdravotní)</Czech> <Portuguese>Estilo do menu (Médico)</Portuguese> <Hungarian>Menü stílusa (Orvosi)</Hungarian> - <Italian>Stile del menù (medico)</Italian> </Key> <Key ID="STR_ACE_Medical_menuTypeDescription"> <English>Select the type of menu you prefer; default 3d selections or radial.</English> @@ -2259,7 +2255,6 @@ <Portuguese>Selecione o tipo de menu que você prefere; padrão seleções 3d ou radial.</Portuguese> <Hungarian>Válaszd ki a neked megfelelő menüt: Alapértelmezett 3D válogatás, vagy kerek.</Hungarian> <Czech>Zvolte typ menu: základní 3D výběr nebo kruhový</Czech> - <Italian>Seleziona il tipo di menù che preferisci: selezione 3d predefinita o radiale.</Italian> </Key> <Key ID="STR_ACE_Medical_useSelection"> <English>Selections (3d)</English> @@ -2271,7 +2266,6 @@ <Portuguese>Seleção (3d)</Portuguese> <Hungarian>Választékok (3D)</Hungarian> <Czech>3D výběr</Czech> - <Italian>Selezione (3D)</Italian> </Key> <Key ID="STR_ACE_Medical_useRadial"> <English>Radial</English> @@ -2283,7 +2277,6 @@ <Portuguese>Radial</Portuguese> <Hungarian>Kerek</Hungarian> <Czech>Kruhový</Czech> - <Italian>Radiale</Italian> </Key> <Key ID="STR_ACE_Medical_Wounds_Abrasion"> <English>Scrape</English> @@ -2691,7 +2684,6 @@ <Spanish>Tratando ...</Spanish> <Portuguese>Tratando...</Portuguese> <Czech>Ošetřuji ...</Czech> - <Italian>Curando ...</Italian> </Key> <Key ID="STR_ACE_Medical_RemovingTourniquet"> <English>Removing Tourniquet ...</English> @@ -2703,7 +2695,6 @@ <Hungarian>Érszorító eltávolítása ...</Hungarian> <Czech>Sundavám škrtidlo ...</Czech> <Russian>Снятие жгута ...</Russian> - <Italian>Togliendo il laccio emostatico ...</Italian> </Key> <Key ID="STR_ACE_Medical_Category_DisplayName"> <English>ACE Medical</English> @@ -2897,14 +2888,6 @@ <English>Should PAK be removed on usage?</English> <Polish>Czy apteczka osobista powinna zniknąć z ekwipunku po jej użyciu?</Polish> </Key> - <Key ID="STR_ACE_Medical_No"> - <English>No</English> - <Polish>Nie</Polish> - </Key> - <Key ID="STR_ACE_Medical_Yes"> - <English>Yes</English> - <Polish>Tak</Polish> - </Key> <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_PAK_DisplayName"> <English>Locations PAK</English> <Polish>Ogr. apteczek osobistych</Polish> @@ -3079,3 +3062,4 @@ </Key> </Package> </Project> + \ No newline at end of file diff --git a/addons/nametags/CfgVehicles.hpp b/addons/nametags/CfgVehicles.hpp index 3619df195f..a4ef577ecf 100644 --- a/addons/nametags/CfgVehicles.hpp +++ b/addons/nametags/CfgVehicles.hpp @@ -62,10 +62,7 @@ class CfgVehicles { displayName = "$STR_ACE_NameTags_showCursorTagForVehicles_DisplayName"; description = "$STR_ACE_NameTags_showCursorTagForVehicles_Description"; typeName = "BOOL"; - class values { - class Yes {name = "$STR_ACE_NameTags_Yes"; value = 1;}; - class No {default = 1; name = "$STR_ACE_NameTags_No"; value = 0;}; - }; + defaultValue = 0; }; }; class ModuleDescription: ModuleDescription { diff --git a/addons/nametags/stringtable.xml b/addons/nametags/stringtable.xml index 251e8eba9a..070257e807 100644 --- a/addons/nametags/stringtable.xml +++ b/addons/nametags/stringtable.xml @@ -70,8 +70,8 @@ <Czech>Zobrazit info o posádce vozidla</Czech> <Russian>Показывать информацию об экипаже</Russian> <Hungarian>Jármű-legénység adatainak mutatása</Hungarian> + <Italian>Mostra le informazioni sull'equipaggio del veicolo</Italian> <Portuguese>Mostrar tripulantes</Portuguese> - <Italian>Mostra l'elenco del personale a bordo</Italian> </Key> <Key ID="STR_ACE_NameTags_ShowNamesForAI"> <English>Show name tags for AI units</English> @@ -82,7 +82,7 @@ <Polish>Wyświetl imiona jednostek AI</Polish> <French>Afficher les noms des IA</French> <Hungarian>Névcímkék mutatása MI-egységeknél</Hungarian> - <Italian>Mostra i nomi delle le unità AI</Italian> + <Italian>Mostra le tag nomi per le unità AI</Italian> <Portuguese>Mostrar nomes para unidades de IA</Portuguese> </Key> <Key ID="STR_ACE_NameTags_ShowSoundWaves"> @@ -94,7 +94,7 @@ <Polish>Pokaż fale dźwiękowe (wymagana opcja Pokaż imiona graczy)</Polish> <French>Afficher "qui parle" (si noms affichés)</French> <Hungarian>"Hanghullámok" mutatása (a nevek mutatása szükséges)</Hungarian> - <Italian>Mostra movimento audio (richiede mostra nomi abilitato)</Italian> + <Italian>Mostra barra movimento audio (richiede mostra nomi abilitato)</Italian> <Portuguese>Mostrar onda sonora (requer nome de jogadores)</Portuguese> </Key> <Key ID="STR_ACE_NameTags_DefaultNametagColor"> @@ -106,7 +106,7 @@ <French>Couleur d'affichage par défaut (si dans aucun groupe)</French> <Czech>Standardní barva jmenovek (pro nečleny jednotky)</Czech> <Hungarian>Alap névcímke-szín (csoporton kívüli személyek)</Hungarian> - <Italian>Colore dei nomi non appartenenti al gruppo</Italian> + <Italian>Colore nametag di default (membri non del gruppo)</Italian> <Portuguese>Cor padrão do nome (unidades fora do grupo)</Portuguese> </Key> <Key ID="STR_ACE_NameTags_Module_DisplayName"> @@ -157,51 +157,43 @@ <English>Show cursor NameTag for vehicle commander (only if client has name tags enabled)Default: No</English> <Polish>Pokazuj imię dowódcy pojazdu nad pojazdem (tylko jeżeli klient ma włączone imiona graczy). Domyślnie: Nie</Polish> </Key> - <Key ID="STR_ACE_NameTags_Yes"> - <English>Yes</English> - <Polish>Tak</Polish> - </Key> - <Key ID="STR_ACE_NameTags_No"> - <English>No</English> - <Polish>Nie</Polish> - </Key> <Key ID="STR_ACE_NameTags_Module_Description"> <English></English> <Polish>Moduł ten pozwala dostosować ustawienia i zasięg wyświetlania imion.</Polish> </Key> - <Key ID="STR_ACE_Common_Disabled"> + <Key ID="STR_ACE_Common_Disabled"> <English>Disabled</English> <Polish>Wyłączone</Polish> </Key> - <Key ID="STR_ACE_Common_Enabled"> + <Key ID="STR_ACE_Common_Enabled"> <English>Enabled</English> <Polish>Włączone</Polish> </Key> - <Key ID="STR_ACE_Common_OnlyCursor"> + <Key ID="STR_ACE_Common_OnlyCursor"> <English>Only Cursor</English> <Polish>Tylko pod kursorem</Polish> </Key> - <Key ID="STR_ACE_Common_OnlyOnKeypress"> + <Key ID="STR_ACE_Common_OnlyOnKeypress"> <English>Only On Keypress</English> <Polish>Tylko po wciśnięciu klawisza</Polish> </Key> - <Key ID="STR_ACE_Common_OnlyCursorAndKeyPress"> + <Key ID="STR_ACE_Common_OnlyCursorAndKeyPress"> <English>Only Cursor and KeyPress</English> <Polish>Tylko pod kursorem i po wciśnięciu klawisza</Polish> </Key> - <Key ID="STR_ACE_Common_NameTagSettings"> + <Key ID="STR_ACE_Common_NameTagSettings"> <English>Use Nametag settings</English> <Polish>Użyj ustawień imion</Polish> </Key> - <Key ID="STR_ACE_Common_AlwaysShowAll"> + <Key ID="STR_ACE_Common_AlwaysShowAll"> <English>Always Show All</English> <Polish>Zawsze pokazuj wszystkie</Polish> </Key> - <Key ID="STR_ACE_NameTags_ShowPlayerNames_Desc"> + <Key ID="STR_ACE_NameTags_ShowPlayerNames_Desc"> <English></English> <Polish>Opcja ta pozwala dostosować sposób wyświetlania imion nad głowami graczy. Opcja "Tylko po wciśnięciu klawisza" wyświetla imiona tylko przytrzymania klawisza "Modyfikator" dostępnego w menu ustawień addonów -> ACE3.</Polish> </Key> - <Key ID="STR_ACE_NameTags_ShowSoundWaves_Desc"> + <Key ID="STR_ACE_NameTags_ShowSoundWaves_Desc"> <English></English> <Polish>Opcja ta pozwala dostosować sposób wyświetlania efektu fal dźwiękowych nad głowami mówiących graczy, wyświetlanych po przytrzymaniu klawisza PTT. Opcja ta współpracuje z TFAR oraz ACRE2.</Polish> </Key> diff --git a/addons/respawn/CfgVehicles.hpp b/addons/respawn/CfgVehicles.hpp index 07ef054b0d..00f0bd4493 100644 --- a/addons/respawn/CfgVehicles.hpp +++ b/addons/respawn/CfgVehicles.hpp @@ -17,22 +17,14 @@ class CfgVehicles { displayName = "$STR_ACE_Respawn_SavePreDeathGear_DisplayName"; description = "$STR_ACE_Respawn_SavePreDeathGear_Description"; typeName = "BOOL"; - - class values { - class Yes { name = "$STR_ACE_Respawn_Yes"; value = 1; }; - class No { default = 1; name = "$STR_ACE_Respawn_No"; value = 0; }; - }; + defaultValue = 0; }; class RemoveDeadBodiesDisconnected { displayName = "$STR_ACE_Respawn_RemoveDeadBodiesDisconnected_DisplayName"; description = "$STR_ACE_Respawn_RemoveDeadBodiesDisconnected_Description"; typeName = "BOOL"; - - class values { - class Yes { default = 1; name = "$STR_ACE_Respawn_Yes"; value = 1; }; - class No { name = "$STR_ACE_Respawn_No"; value = 0; }; - }; + defaultValue = 1; }; }; class ModuleDescription: ModuleDescription { diff --git a/addons/respawn/stringtable.xml b/addons/respawn/stringtable.xml index a9965dd2a4..5351d0f3bc 100644 --- a/addons/respawn/stringtable.xml +++ b/addons/respawn/stringtable.xml @@ -35,7 +35,6 @@ <French>Téléportation à la base</French> <Portuguese>Teletransportar para a Base</Portuguese> <Hungarian>Bázisra teleportálás</Hungarian> - <Italian>Teleporta alla base</Italian> </Key> <Key ID="STR_ACE_Respawn_TeleportToRallypoint"> <English>Teleport to Rallypoint</English> @@ -47,7 +46,6 @@ <French>Téléporation au point de ralliement</French> <Portuguese>Teletransportar para o ponto de encontro</Portuguese> <Hungarian>Gyülekezőpontra teleportálás</Hungarian> - <Italian>Teleporta al rallypoint</Italian> </Key> <Key ID="STR_ACE_Respawn_TeleportedToBase"> <English>Teleported to Base</English> @@ -157,14 +155,6 @@ <English>Respawn with the gear a soldier had just before his death?</English> <Polish>Odradzaj z ekwipunkiem jaki żołnierz miał tuż przed swoją śmiercią?</Polish> </Key> - <Key ID="STR_ACE_Respawn_Yes"> - <English>Yes</English> - <Polish>Tak</Polish> - </Key> - <Key ID="STR_ACE_Respawn_No"> - <English>No</English> - <Polish>Nie</Polish> - </Key> <Key ID="STR_ACE_Respawn_RemoveDeadBodiesDisconnected_DisplayName"> <English>Remove bodies?</English> <Polish>Usuwać ciała?</Polish> diff --git a/addons/switchunits/CfgVehicles.hpp b/addons/switchunits/CfgVehicles.hpp index 1e041a3f4f..48271c6428 100644 --- a/addons/switchunits/CfgVehicles.hpp +++ b/addons/switchunits/CfgVehicles.hpp @@ -13,46 +13,31 @@ class CfgVehicles { displayName = "$STR_ACE_SwitchUnits_SwitchToWest_DisplayName"; description = "$STR_ACE_SwitchUnits_SwitchToWest_Description"; typeName = "BOOL"; - class values { - class Yes {name = "$STR_ACE_SwitchUnits_Yes"; value = 1;}; - class No {default = 1; name = "$STR_ACE_SwitchUnits_Yes"; value = 0;}; - }; + defaultValue = 0; }; class SwitchToEast { displayName = "$STR_ACE_SwitchUnits_SwitchToEast_DisplayName"; description = "$STR_ACE_SwitchUnits_SwitchToEast_Description"; typeName = "BOOL"; - class values { - class Yes {name = "$STR_ACE_SwitchUnits_Yes"; value = 1;}; - class No {default = 1; name = "$STR_ACE_SwitchUnits_No"; value = 0;}; - }; + defaultValue = 0; }; class SwitchToIndependent { displayName = "$STR_ACE_SwitchUnits_SwitchToIndependent_DisplayName"; description = "$STR_ACE_SwitchUnits_SwitchToIndependent_Description"; typeName = "BOOL"; - class values { - class Yes {name = "$STR_ACE_SwitchUnits_Yes"; value = 1;}; - class No {default = 1; name = "$STR_ACE_SwitchUnits_No"; value = 0;}; - }; + defaultValue = 0; }; class SwitchToCivilian { displayName = "$STR_ACE_SwitchUnits_SwitchToCivilian_DisplayName"; description = "$STR_ACE_SwitchUnits_SwitchToCivilian_Description"; typeName = "BOOL"; - class values { - class Yes {name = "$STR_ACE_SwitchUnits_Yes"; value = 1;}; - class No {default = 1; name = "$STR_ACE_SwitchUnits_No"; value = 0;}; - }; + defaultValue = 0; }; class EnableSafeZone { displayName = "$STR_ACE_SwitchUnits_EnableSafeZone_DisplayName"; description = "$STR_ACE_SwitchUnits_EnableSafeZone_Description"; typeName = "BOOL"; - class values { - class Yes {default = 1; name = "$STR_ACE_SwitchUnits_Yes"; value = 1;}; - class No {name = "$STR_ACE_SwitchUnits_No"; value = 0;}; - }; + defaultValue = 1; }; class SafeZoneRadius { displayName = "$STR_ACE_SwitchUnits_SafeZoneRadius_DisplayName"; diff --git a/addons/switchunits/stringtable.xml b/addons/switchunits/stringtable.xml index c1e7fc2d57..cdde0f8ff1 100644 --- a/addons/switchunits/stringtable.xml +++ b/addons/switchunits/stringtable.xml @@ -25,14 +25,6 @@ <Italian>Questa unità è troppo vicina al nemico.</Italian> <Portuguese>Essa unidade está muito perta do inimigo.</Portuguese> </Key> - <Key ID="STR_ACE_SwitchUnits_Yes"> - <English>Yes</English> - <Polish>Tak</Polish> - </Key> - <Key ID="STR_ACE_SwitchUnits_No"> - <English>No</English> - <Polish>Nie</Polish> - </Key> <Key ID="STR_ACE_SwitchUnits_Module_DisplayName"> <English>SwitchUnits System</English> <Polish>System zmiany stron</Polish> From 63c5308cd95a5396626f0986c71c6b9e060ed131 Mon Sep 17 00:00:00 2001 From: Grzegorz Sikora <gienkov.grzegorz@gmail.com> Date: Sat, 9 May 2015 20:43:55 +0200 Subject: [PATCH 27/51] Missed one Yes/no to BOOL --- addons/vehiclelock/CfgVehicles.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/addons/vehiclelock/CfgVehicles.hpp b/addons/vehiclelock/CfgVehicles.hpp index 8436657676..60cb67d4c4 100644 --- a/addons/vehiclelock/CfgVehicles.hpp +++ b/addons/vehiclelock/CfgVehicles.hpp @@ -83,9 +83,9 @@ class CfgVehicles { defaultValue = 0; }; class VehicleStartingLockState { - displayName = "$STR_ACE_VehicleLock_VehicleStartingLockState_DisplayName"; // Argument label - description = "$STR_ACE_VehicleLock_VehicleStartingLockState_Description"; // Tooltip description - typeName = "NUMBER"; // Value type, can be "NUMBER", "STRING" or "BOOL" + displayName = "$STR_ACE_VehicleLock_VehicleStartingLockState_DisplayName"; + description = "$STR_ACE_VehicleLock_VehicleStartingLockState_Description"; + typeName = "NUMBER"; class values { class None {name = "$STR_ACE_VehicleLock_VehicleStartingLockState_AsIs"; value = 0; default = 1;}; class Side {name = "$STR_ACE_VehicleLock_VehicleStartingLockState_Locked"; value = 1;}; @@ -95,8 +95,8 @@ class CfgVehicles { class DefaultLockpickStrength { displayName = "$STR_ACE_VehicleLock_DefaultLockpickStrength_DisplayName"; description = "$STR_ACE_VehicleLock_DefaultLockpickStrength_Description"; - typeName = "NUMBER"; // Value type, can be "NUMBER", "STRING" or "BOOL" - defaultValue = "10"; // Default text filled in the input box + typeName = "NUMBER"; + defaultValue = "10"; }; }; class ModuleDescription: ModuleDescription { From 5bbf875ef28a6afa912936f14e17eac51efc9f5f Mon Sep 17 00:00:00 2001 From: GieNkoV <gienkov.grzegorz@gmail.com> Date: Tue, 12 May 2015 04:54:23 +0200 Subject: [PATCH 28/51] Tabs removed Conflicts: addons/missileguidance/stringtable.xml addons/optionsmenu/stringtable.xml --- addons/missileguidance/stringtable.xml | 226 +++++----- addons/optionsmenu/stringtable.xml | 577 ++++++++++++------------- 2 files changed, 401 insertions(+), 402 deletions(-) diff --git a/addons/missileguidance/stringtable.xml b/addons/missileguidance/stringtable.xml index 3c551493a5..ef9bdeea26 100644 --- a/addons/missileguidance/stringtable.xml +++ b/addons/missileguidance/stringtable.xml @@ -1,113 +1,113 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project name="ACE"> - <Package name="missileguidance"> - <Key ID="STR_ACE_MissileGuidance"> - <English>Advanced Missile Guidance</English> - <Spanish>Guiado Avanzado de Misiles</Spanish> - <French>Guidage avancé de missile</French> - <Polish>Zaawansowane naprowadzanie rakiet</Polish> - <German>Erweitertes Raketenlenksystem</German> - <Czech>Pokročilé řízení střel</Czech> - <Italian>Guida missili avanzata</Italian> - <Portuguese>Avançado Missile Guidance</Portuguese> - <Hungarian>Fejlett rakétairányító</Hungarian> - <Russian>Продвинутое наведение ракет</Russian> - </Key> - <Key ID="STR_ACE_MissileGuidance_Desc"> - <English>Advanced missile guidance, or AMG, provides multiple enhancements to missile locking and firing. It is also a framework required for missile weapon types.</English> - <Polish>Zaawansowane namierzanie rakiet, lub ZNR, dostarcza wiele poprawek do systemu namierzania rakiet oraz dodaje nowe tryby strzału. Jest to wymagana opcja dla broni rakietowych.</Polish> - <Italian>Guida dei missili avanzata, o AMG, offre diversi miglioramenti alla teleguida di missili. E' anche un sistema necessario per i tipi di armi missile.</Italian> - <Russian>Продвинутое наведение ракет, или ПНР, обеспечивает множество усовершествований для наведения и стрельбы ракет. Также, это система, необходимая для всех ракетных типов оружия.</Russian> - <Spanish>Guiado Avanzado de Misiles, o AMG en sus siglas en inglés, ofrece múltiples mejoras en el fijado y disparo de misiles. Es también un sistema requerido para armas de tipo misil.</Spanish> - <German>Das Erweiterte Raketenlenksystem, auch ERls genannt, bietet viele Verbesserungen zum Aufschalten und Feuern mittels gelenkten Raketen. </German> - <French>Le guidage avancé de missile, ou AMG en anglais, apporte de multiple améliorations au verouillage et au tir de missiles. C'est aussi un framework requis pour tout arme de type missile.</French> - <Hungarian>A fejlett rakétairányító (vagy AMG) többféle módosítást tartalmaz a rakéták célkövetéséhez és tüzeléséhez. Ez egy szükséges keresztrendszer a rakéta-alapú fegyverekhez.</Hungarian> - <Portuguese>Orientação avançada de mísseis ou OAM, fornece vários aprimoramentos para travamento de mísseis e disparos. Também é um sistema requerido para disparar armas que utilizem mísseis.</Portuguese> - <Czech>Pokočilé navádění raket (AMG) poskytuje několik vylepšení pro lepší zaměření a následnou střelbu. Je to prvek vyžadovaný u typu zbraní jako jsou rakety.</Czech> - </Key> - <Key ID="STR_ACE_Hydra70_DAGR"> - <English>Hydra-70 DAGR Missile</English> - <Spanish>Misil Hydra-70 DAGR</Spanish> - <French>Hydra-70 DAGR</French> - <Polish>Hydra-70 DAGR</Polish> - <German>Hydra-70 DAGR Rackete</German> - <Czech>Hydra-70 DAGR</Czech> - <Italian>Missile Hydra-70 DAGR</Italian> - <Portuguese>Míssil Hydra-70 DAGR </Portuguese> - <Hungarian>Hydra-70 DAGR rakéta</Hungarian> - <Russian>Hydra-70 DAGR</Russian> - </Key> - <Key ID="STR_ACE_Hydra70_DAGR_Short"> - <English>DAGR</English> - <Spanish>DAGR</Spanish> - <French>DAGR</French> - <Polish>DAGR</Polish> - <German>DAGR</German> - <Czech>DAGR</Czech> - <Italian>DAGR</Italian> - <Portuguese>DAGR</Portuguese> - <Hungarian>DAGR</Hungarian> - <Russian>DAGR</Russian> - </Key> - <Key ID="STR_ACE_Hydra70_DAGR_Desc"> - <English>Hydra-70 DAGR Laser Guided Missile</English> - <Spanish>Misil guiado por láser Hydra-70 DAGR</Spanish> - <French>Missile à guidage laser Hydra-70 DAGR</French> - <Polish>Laserowo naprowadzana rakieta Hydra-70 DAGR</Polish> - <German>Hydra-70 DAGR lasergelenkte Rakete</German> - <Czech>Hydra-70 DAGR laserem naváděná střela</Czech> - <Italian>Hydra-70 DAGR missile guida laser</Italian> - <Portuguese>Míssil guiado a laser Hydra-70 DAGR </Portuguese> - <Hungarian>Hydra-70 DAGR lézer-irányított rakéta</Hungarian> - <Russian>Управляемая ракета лазерного наведения Hydra-70 DAGR</Russian> - </Key> - <Key ID="STR_ACE_Hellfire_AGM114K"> - <English>Hellfire II AGM-114K Missile</English> - <Spanish>Misil Hellfire II AGM-114K</Spanish> - <French>Hellfire II AGM-114K</French> - <Polish>Hellfire II AGM-114K</Polish> - <German>Hellfire II AGM-114K</German> - <Czech>Hellfire II AGM-114K</Czech> - <Italian>Missile Hellfire II AGM-114K</Italian> - <Portuguese>Míssil Hellfire II AGM-114K</Portuguese> - <Hungarian>Hellfire II AGM-114K rakéta</Hungarian> - <Russian>Hellfire II AGM-114K</Russian> - </Key> - <Key ID="STR_ACE_Hellfire_AGM114K_Short"> - <English>AGM-114K</English> - <Spanish>AGM-114K</Spanish> - <French>AGM-114K</French> - <Polish>AGM-114K</Polish> - <German>AGM-114K</German> - <Czech>AGM-114K</Czech> - <Italian>AGM-114K</Italian> - <Portuguese>AGM-114K</Portuguese> - <Hungarian>AGM-114K</Hungarian> - <Russian>AGM-114K</Russian> - </Key> - <Key ID="STR_ACE_Hellfire_AGM114K_desc"> - <English>Hellfire II AGM-114K Laser Guided Missile</English> - <Spanish>Misil guiado por láser Hellfire II AGM-114K</Spanish> - <French>Missile à guidage laser Hellfire II AGM-114K</French> - <Polish>Laserowo naprowadzana rakieta Hellfire II AGM-114K</Polish> - <German>Hellfire II AGM-114K Lasergelenkte Rakete</German> - <Czech>Hellfire II AGM-114K laserem naváděná střela</Czech> - <Italian>Missile guida laser Hellfire II AGM-114K</Italian> - <Portuguese>Míssil guiado a laser Hellfire II AGM-114K</Portuguese> - <Hungarian>Hellfire II AGM-114K lézer-irányított rakéta</Hungarian> - <Russian>Управляемая ракета лазерного наведения Hellfire II AGM-114K</Russian> - </Key> - <Key ID="STR_ACE_MissileGuidance_Off"> - <English>Off</English> - <Polish>Wyłącz</Polish> - </Key> - <Key ID="STR_ACE_MissileGuidance_PlayerOnly"> - <English>Player Only</English> - <Polish>Tylko gracz</Polish> - </Key> - <Key ID="STR_ACE_MissileGuidance_PlayerAndAi"> - <English>Player and AI</English> - <Polish>Gracz oraz AI</Polish> - </Key> - </Package> -</Project> +<?xml version="1.0" encoding="utf-8"?> +<Project name="ACE"> + <Package name="missileguidance"> + <Key ID="STR_ACE_MissileGuidance"> + <English>Advanced Missile Guidance</English> + <Spanish>Guiado Avanzado de Misiles</Spanish> + <French>Guidage avancé de missile</French> + <Polish>Zaawansowane naprowadzanie rakiet</Polish> + <German>Erweitertes Raketenlenksystem</German> + <Czech>Pokročilé řízení střel</Czech> + <Italian>Guida missili avanzata</Italian> + <Portuguese>Avançado Missile Guidance</Portuguese> + <Hungarian>Fejlett rakétairányító</Hungarian> + <Russian>Продвинутое наведение ракет</Russian> + </Key> + <Key ID="STR_ACE_MissileGuidance_Desc"> + <English>Advanced missile guidance, or AMG, provides multiple enhancements to missile locking and firing. It is also a framework required for missile weapon types.</English> + <Polish>Zaawansowane namierzanie rakiet, lub ZNR, dostarcza wiele poprawek do systemu namierzania rakiet oraz dodaje nowe tryby strzału. Jest to wymagana opcja dla broni rakietowych.</Polish> + <Italian>Guida dei missili avanzata, o AMG, offre diversi miglioramenti alla teleguida di missili. E' anche un sistema necessario per i tipi di armi missile.</Italian> + <Russian>Продвинутое наведение ракет, или ПНР, обеспечивает множество усовершествований для наведения и стрельбы ракет. Также, это система, необходимая для всех ракетных типов оружия.</Russian> + <Spanish>Guiado Avanzado de Misiles, o AMG en sus siglas en inglés, ofrece múltiples mejoras en el fijado y disparo de misiles. Es también un sistema requerido para armas de tipo misil.</Spanish> + <German>Das Erweiterte Raketenlenksystem, auch ERls genannt, bietet viele Verbesserungen zum Aufschalten und Feuern mittels gelenkten Raketen. </German> + <French>Le guidage avancé de missile, ou AMG en anglais, apporte de multiple améliorations au verouillage et au tir de missiles. C'est aussi un framework requis pour tout arme de type missile.</French> + <Hungarian>A fejlett rakétairányító (vagy AMG) többféle módosítást tartalmaz a rakéták célkövetéséhez és tüzeléséhez. Ez egy szükséges keresztrendszer a rakéta-alapú fegyverekhez.</Hungarian> + <Portuguese>Orientação avançada de mísseis ou OAM, fornece vários aprimoramentos para travamento de mísseis e disparos. Também é um sistema requerido para disparar armas que utilizem mísseis.</Portuguese> + <Czech>Pokočilé navádění raket (AMG) poskytuje několik vylepšení pro lepší zaměření a následnou střelbu. Je to prvek vyžadovaný u typu zbraní jako jsou rakety.</Czech> + </Key> + <Key ID="STR_ACE_Hydra70_DAGR"> + <English>Hydra-70 DAGR Missile</English> + <Spanish>Misil Hydra-70 DAGR</Spanish> + <French>Hydra-70 DAGR</French> + <Polish>Hydra-70 DAGR</Polish> + <German>Hydra-70 DAGR Rackete</German> + <Czech>Hydra-70 DAGR</Czech> + <Italian>Missile Hydra-70 DAGR</Italian> + <Portuguese>Míssil Hydra-70 DAGR </Portuguese> + <Hungarian>Hydra-70 DAGR rakéta</Hungarian> + <Russian>Hydra-70 DAGR</Russian> + </Key> + <Key ID="STR_ACE_Hydra70_DAGR_Short"> + <English>DAGR</English> + <Spanish>DAGR</Spanish> + <French>DAGR</French> + <Polish>DAGR</Polish> + <German>DAGR</German> + <Czech>DAGR</Czech> + <Italian>DAGR</Italian> + <Portuguese>DAGR</Portuguese> + <Hungarian>DAGR</Hungarian> + <Russian>DAGR</Russian> + </Key> + <Key ID="STR_ACE_Hydra70_DAGR_Desc"> + <English>Hydra-70 DAGR Laser Guided Missile</English> + <Spanish>Misil guiado por láser Hydra-70 DAGR</Spanish> + <French>Missile à guidage laser Hydra-70 DAGR</French> + <Polish>Laserowo naprowadzana rakieta Hydra-70 DAGR</Polish> + <German>Hydra-70 DAGR lasergelenkte Rakete</German> + <Czech>Hydra-70 DAGR laserem naváděná střela</Czech> + <Italian>Hydra-70 DAGR missile guida laser</Italian> + <Portuguese>Míssil guiado a laser Hydra-70 DAGR </Portuguese> + <Hungarian>Hydra-70 DAGR lézer-irányított rakéta</Hungarian> + <Russian>Управляемая ракета лазерного наведения Hydra-70 DAGR</Russian> + </Key> + <Key ID="STR_ACE_Hellfire_AGM114K"> + <English>Hellfire II AGM-114K Missile</English> + <Spanish>Misil Hellfire II AGM-114K</Spanish> + <French>Hellfire II AGM-114K</French> + <Polish>Hellfire II AGM-114K</Polish> + <German>Hellfire II AGM-114K</German> + <Czech>Hellfire II AGM-114K</Czech> + <Italian>Missile Hellfire II AGM-114K</Italian> + <Portuguese>Míssil Hellfire II AGM-114K</Portuguese> + <Hungarian>Hellfire II AGM-114K rakéta</Hungarian> + <Russian>Hellfire II AGM-114K</Russian> + </Key> + <Key ID="STR_ACE_Hellfire_AGM114K_Short"> + <English>AGM-114K</English> + <Spanish>AGM-114K</Spanish> + <French>AGM-114K</French> + <Polish>AGM-114K</Polish> + <German>AGM-114K</German> + <Czech>AGM-114K</Czech> + <Italian>AGM-114K</Italian> + <Portuguese>AGM-114K</Portuguese> + <Hungarian>AGM-114K</Hungarian> + <Russian>AGM-114K</Russian> + </Key> + <Key ID="STR_ACE_Hellfire_AGM114K_desc"> + <English>Hellfire II AGM-114K Laser Guided Missile</English> + <Spanish>Misil guiado por láser Hellfire II AGM-114K</Spanish> + <French>Missile à guidage laser Hellfire II AGM-114K</French> + <Polish>Laserowo naprowadzana rakieta Hellfire II AGM-114K</Polish> + <German>Hellfire II AGM-114K Lasergelenkte Rakete</German> + <Czech>Hellfire II AGM-114K laserem naváděná střela</Czech> + <Italian>Missile guida laser Hellfire II AGM-114K</Italian> + <Portuguese>Míssil guiado a laser Hellfire II AGM-114K</Portuguese> + <Hungarian>Hellfire II AGM-114K lézer-irányított rakéta</Hungarian> + <Russian>Управляемая ракета лазерного наведения Hellfire II AGM-114K</Russian> + </Key> + <Key ID="STR_ACE_MissileGuidance_Off"> + <English>Off</English> + <Polish>Wyłącz</Polish> + </Key> + <Key ID="STR_ACE_MissileGuidance_PlayerOnly"> + <English>Player Only</English> + <Polish>Tylko gracz</Polish> + </Key> + <Key ID="STR_ACE_MissileGuidance_PlayerAndAi"> + <English>Player and AI</English> + <Polish>Gracz oraz AI</Polish> + </Key> + </Package> +</Project> diff --git a/addons/optionsmenu/stringtable.xml b/addons/optionsmenu/stringtable.xml index 3b649aa6c7..f14a97b460 100644 --- a/addons/optionsmenu/stringtable.xml +++ b/addons/optionsmenu/stringtable.xml @@ -1,289 +1,288 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project name="ACE"> - <Package name="OptionsMenu"> - <Key ID="STR_ACE_OptionsMenu_OpenConfigMenu"> - <English>ACE Options</English> - <German>ACE Optionen</German> - <Spanish>Opciones ACE</Spanish> - <Polish>Ustawienia ACE</Polish> - <Czech>ACE Nastavení</Czech> - <French>Options ACE</French> - <Russian>ACE Настройки</Russian> - <Portuguese>Opções do ACE</Portuguese> - <Hungarian>ACE Beállítások</Hungarian> - <Italian>Opzioni ACE</Italian> - </Key> - <Key ID="STR_ACE_OptionsMenu_FixAnimation"> - <English>Fix Animation</English> - <German>Behebe Animation</German> - <Spanish>Arreglar animación</Spanish> - <Russian>Фикс анимации</Russian> - <Czech>Opravit animace</Czech> - <Polish>Napraw animację</Polish> - <French>Corriger animation</French> - <Hungarian>Animációk kijavítása</Hungarian> - <Italian>Fixa l'animazione</Italian> - <Portuguese>Arrumar Animação</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_ResetAll"> - <English>Reset All</English> - <German>Alles zurücksetzen</German> - <Spanish>Reiniciar todo</Spanish> - <Russian>Полный сброс</Russian> - <Czech>Vyresetovat vše</Czech> - <Polish>Resetuj wszystko</Polish> - <French>Défaut</French> - <Hungarian>Minden visszaállítása</Hungarian> - <Italian>Resetta tutto</Italian> - <Portuguese>Resetar Tudo</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_TabColors"> - <English>Colors</English> - <French>Couleurs</French> - <German>Farben</German> - <Spanish>Colores</Spanish> - <Russian>Цвета</Russian> - <Czech>Barvy</Czech> - <Polish>Kolory</Polish> - <Hungarian>Színek</Hungarian> - <Italian>Colori</Italian> - <Portuguese>Cores</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_TabOptions"> - <English>Options</English> - <German>Optionen</German> - <Spanish>Opciones</Spanish> - <Polish>Opcje</Polish> - <Czech>Nastavení</Czech> - <French>Options</French> - <Russian>Настройки</Russian> - <Portuguese>Opções</Portuguese> - <Hungarian>Beállítások</Hungarian> - <Italian>Opzioni</Italian> - </Key> - <Key ID="STR_ACE_OptionsMenu_TabValues"> - <English>Values</English> - <Spanish>Valores</Spanish> - <Russian>Значения</Russian> - <Czech>Hodnoty</Czech> - <Polish>Wartości</Polish> - <French>Valeurs</French> - <German>Werte</German> - <Hungarian>Értékek</Hungarian> - <Italian>Valori</Italian> - <Portuguese>Valores</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_Enabled"> - <English>Yes</English> - <German>Ja</German> - <Spanish>Si</Spanish> - <Polish>Tak</Polish> - <Czech>Ano</Czech> - <French>Oui</French> - <Russian>Да</Russian> - <Hungarian>Igen</Hungarian> - <Portuguese>Sim</Portuguese> - <Italian>Si</Italian> - </Key> - <Key ID="STR_ACE_OptionsMenu_Disabled"> - <English>No</English> - <German>Nein</German> - <Spanish>No</Spanish> - <Polish>Nie</Polish> - <Czech>Ne</Czech> - <French>Non</French> - <Russian>Нет</Russian> - <Hungarian>Nem</Hungarian> - <Portuguese>Não</Portuguese> - <Italian>No</Italian> - </Key> - <Key ID="STR_ACE_OptionsMenu_Setting"> - <English>Setting:</English> - <Czech>Nastavení:</Czech> - <German>Einstellung:</German> - <Russian>Установки:</Russian> - <Spanish>Ajuste:</Spanish> - <Polish>Ustaw:</Polish> - <French>Paramètres</French> - <Hungarian>Opció:</Hungarian> - <Italian>Parametri:</Italian> - <Portuguese>Opção:</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_Export"> - <English>Export</English> - <German>Exportieren</German> - <Spanish>Exportar</Spanish> - <Russian>Экспорт</Russian> - <Czech>Exportovat</Czech> - <Polish>Eksport</Polish> - <French>Exporter</French> - <Hungarian>Exportálás</Hungarian> - <Italian>Esporta</Italian> - <Portuguese>Exportar</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_OpenExport"> - <English>Open Export Menu</English> - <German>Öffne Exportmenü</German> - <Spanish>Abrir menú de exportación</Spanish> - <Russian>Открыть меню экспорта</Russian> - <Czech>Otevřít exportovací menu</Czech> - <Polish>Otwórz menu eksportowania</Polish> - <French>Ouvrir le menu d'exportation</French> - <Hungarian>Exportálási menü megnyitása</Hungarian> - <Italian>Apri menù esportazione</Italian> - <Portuguese>Abrir menu de exportação</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_stringType"> - <English>String input.</English> - <German>Zeichenketteneingabe</German> - <Spanish>Introducir cadena de texto.</Spanish> - <Russian>Строчный ввод.</Russian> - <Polish>Wpisywanie tekstu.</Polish> - <Czech>Vkládání textu.</Czech> - <French>Entrée</French> - <Hungarian>String bevitel.</Hungarian> - <Italian>Stringa di unput.</Italian> - <Portuguese>Input de String</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_arrayType"> - <English>Array. Seperate elements by using ,.</English> - <German>Array. Teile unterschiedliche Elemente mit ,.</German> - <Spanish>Matriz. Separa elementos usando ,.</Spanish> - <Russian>Массив. Разделяйте элемены, используя запятую.</Russian> - <Polish>Tablica. Oddziel elementy używając ,.</Polish> - <French>Tableau. Séparation par ,.</French> - <Czech>Tabulka. Odděl elementy použitím ,.</Czech> - <Hungarian>Array. Válasszad el az elemeket vesszővel.</Hungarian> - <Italian>Array. Separa gli elementi usando ,.</Italian> - <Portuguese>Vetor. Separe elementos usando *,*.</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_scalarType"> - <English>Number</English> - <German>Zahl</German> - <Spanish>Número</Spanish> - <Russian>Число</Russian> - <Czech>Číslo</Czech> - <Polish>Cyfra</Polish> - <French>Nombre</French> - <Hungarian>Szám</Hungarian> - <Italian>Numero</Italian> - <Portuguese>Número</Portuguese> - </Key> - <Key ID="STR_ACE_optionsMenu_unknownType"> - <English>Uknown input type</English> - <German>Unbekannter Eingabetyp</German> - <Spanish>Tipo de entrada desconocida</Spanish> - <Russian>Неизвестный тип ввода</Russian> - <Czech>Neznámý vstup</Czech> - <Polish>Nieznany rodzaj danych</Polish> - <French>Type d'entrée inconnue</French> - <Hungarian>Ismeretlen beviteli típus</Hungarian> - <Italian>Input inserito sconosciuto</Italian> - <Portuguese>Tipo desonhecido de input</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_SaveInput"> - <English>Save input</English> - <German>Speichere Eingabe</German> - <Spanish>Guardar entrada</Spanish> - <Russian>Сохранить ввод</Russian> - <Czech>Uložit vstup</Czech> - <Polish>Zapisz dane</Polish> - <French>Sauvegarder</French> - <Hungarian>Bevitel elmentése</Hungarian> - <Italian>Salva input</Italian> - <Portuguese>Salvar input</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_inClientSettings"> - <English>Include Client Settings</English> - <German>Schließe Client-Einstellungen ein</German> - <Spanish>Incluir configuración de cliente</Spanish> - <Russian>Включить настройки клиента</Russian> - <Czech>Zahrnout nastavení klienta</Czech> - <Polish>Zawrzyj ustawienia klienta</Polish> - <French>Inclure paramètres client</French> - <Hungarian>Kliens-beállítások melléklése</Hungarian> - <Italian>Includi i parametri del client</Italian> - <Portuguese>Incluir opções do cliente</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_exClientSettings"> - <English>Exclude Client Settings</English> - <German>Schließe Client-Einstellungen aus</German> - <Spanish>Excluir configuración de cliente</Spanish> - <Russian>Исключить настройки клиента</Russian> - <Czech>Nezahrnout nastavení klienta</Czech> - <Polish>Wyklucz ustawienia klienta</Polish> - <French>Exclure paramètres client</French> - <Hungarian>Kliens-beállítások elhagyása</Hungarian> - <Italian>Escludi i parametri del client</Italian> - <Portuguese>Excluir opções do cliente</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_settingsExported"> - <English>Settings exported to clipboard</English> - <German>Einstellungen in die Zwischenablage exportiert</German> - <Spanish>Configuración exportada al portapapeles</Spanish> - <Russian>Настройки экспортированы в буфер обмена</Russian> - <Czech>Nastevení exportována do schránky</Czech> - <Polish>Ustawienia wyeksportowano do schowka</Polish> - <French>Paramètres exportés dans le presse papier</French> - <Hungarian>Beállítások exportálva a vágólapba</Hungarian> - <Italian>Parametri esportati alla clipboard</Italian> - <Portuguese>Opções exportadas para o clipboard.</Portuguese> - </Key> - <Key ID="STR_ACE_optionsMenu_uiScaing"> - <English>Option Menu UI Scaling</English> - <French>Menu option: taille de l'UI</French> - <Polish>Skalowanie UI menu ustawień</Polish> - <Czech>Měřítko UI v menu nastavení</Czech> - <Russian>Размер интерфейса меню настройки</Russian> - <Spanish>Opción de escalado del menú IU</Spanish> - <German>UI Skalierung</German> - <Hungarian>Beállításmenü kezelőfelületének skálázása</Hungarian> - <Portuguese>Escalar o menu de opções</Portuguese> - <Italian>Proporzioni della interfaccia utente</Italian> - </Key> - <Key ID="STR_AllowConfigExport_Module_DisplayName"> - <English>Allow Config Export [ACE]</English> - <Polish>Pozwól na eksport ustawień [ACE]</Polish> - </Key> - <Key ID="STR_AllowConfigExport_allowconfigurationExport_DisplayName"> - <English>Allow</English> - <Polish>Zezwól</Polish> - </Key> - <Key ID="STR_AllowConfigExport_allowconfigurationExport_Description"> - <English>Allow export of all settings to a server config formatted.</English> - <Polish>Zezwól na eksport wszystkich ustawień do formatu konfiguracji serwera.</Polish> - </Key> - <Key ID="STR_AllowConfigExport_Module_Description"> - <English>When allowed, you have access to the settings modification and export in SP. Clicking export will place the formated config on your clipboard.</English> - <Polish>Jeżeli ustawione na zezwól, wtedy będziesz mieć dostęp do ekranu modyfikacji wszystich ustawień i zmiennych ACE, a także będziesz mieć możliwość eksportu tychże ustawień do formatu rozpoznawalnego przez userconfig serwera. Kliknięcie opcji Eksportuj skopiuje wszystkie ustawienia do schowka. Działa tylko w trybie SP.</Polish> - </Key> - <Key ID="STR_ACE_Common_Hide"> - <English>Hide</English> - <Polish>Ukryj</Polish> - </Key> - <Key ID="STR_ACE_Common_TopRightDown"> - <English>Top right, downwards</English> - <Polish>Po prawej u góry, w dół</Polish> - </Key> - <Key ID="STR_ACE_Common_TopRightLeft"> - <English>Top right, to the left</English> - <Polish>Po prawej u góry, do lewej</Polish> - </Key> - <Key ID="STR_ACE_Common_TopLeftDown"> - <English>Top left, downwards</English> - <Polish>Po lewej u góry, w dół</Polish> - </Key> - <Key ID="STR_ACE_Common_TopLeftRight"> - <English>Top left, to the right</English> - <Polish>Po lewej u góry, do prawej</Polish> - </Key> - <Key ID="STR_ACE_Common_Top"> - <English>Top</English> - <Polish>Góra</Polish> - </Key> - <Key ID="STR_ACE_Common_Bottom"> - <English>Bottom</English> - <Polish>Dół</Polish> - </Key> - </Package> -</Project> +<?xml version="1.0" encoding="utf-8"?> +<Project name="ACE"> + <Package name="OptionsMenu"> + <Key ID="STR_ACE_OptionsMenu_OpenConfigMenu"> + <English>ACE Options</English> + <German>ACE Optionen</German> + <Spanish>Opciones ACE</Spanish> + <Polish>Ustawienia ACE</Polish> + <Czech>ACE Nastavení</Czech> + <French>Options ACE</French> + <Russian>ACE Настройки</Russian> + <Portuguese>Opções do ACE</Portuguese> + <Hungarian>ACE Beállítások</Hungarian> + <Italian>Opzioni ACE</Italian> + </Key> + <Key ID="STR_ACE_OptionsMenu_FixAnimation"> + <English>Fix Animation</English> + <German>Behebe Animation</German> + <Spanish>Arreglar animación</Spanish> + <Russian>Фикс анимации</Russian> + <Czech>Opravit animace</Czech> + <Polish>Napraw animację</Polish> + <French>Corriger animation</French> + <Hungarian>Animációk kijavítása</Hungarian> + <Italian>Fixa l'animazione</Italian> + <Portuguese>Arrumar Animação</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_ResetAll"> + <English>Reset All</English> + <German>Alles zurücksetzen</German> + <Spanish>Reiniciar todo</Spanish> + <Russian>Полный сброс</Russian> + <Czech>Vyresetovat vše</Czech> + <Polish>Resetuj wszystko</Polish> + <French>Défaut</French> + <Hungarian>Minden visszaállítása</Hungarian> + <Italian>Resetta tutto</Italian> + <Portuguese>Resetar Tudo</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_TabColors"> + <English>Colors</English> + <French>Couleurs</French> + <German>Farben</German> + <Spanish>Colores</Spanish> + <Russian>Цвета</Russian> + <Czech>Barvy</Czech> + <Polish>Kolory</Polish> + <Hungarian>Színek</Hungarian> + <Italian>Colori</Italian> + <Portuguese>Cores</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_TabOptions"> + <English>Options</English> + <German>Optionen</German> + <Spanish>Opciones</Spanish> + <Polish>Opcje</Polish> + <Czech>Nastavení</Czech> + <French>Options</French> + <Russian>Настройки</Russian> + <Portuguese>Opções</Portuguese> + <Hungarian>Beállítások</Hungarian> + <Italian>Opzioni</Italian> + </Key> + <Key ID="STR_ACE_OptionsMenu_TabValues"> + <English>Values</English> + <Spanish>Valores</Spanish> + <Russian>Значения</Russian> + <Czech>Hodnoty</Czech> + <Polish>Wartości</Polish> + <French>Valeurs</French> + <German>Werte</German> + <Hungarian>Értékek</Hungarian> + <Italian>Valori</Italian> + <Portuguese>Valores</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_Enabled"> + <English>Yes</English> + <German>Ja</German> + <Spanish>Si</Spanish> + <Polish>Tak</Polish> + <Czech>Ano</Czech> + <French>Oui</French> + <Russian>Да</Russian> + <Hungarian>Igen</Hungarian> + <Portuguese>Sim</Portuguese> + <Italian>Si</Italian> + </Key> + <Key ID="STR_ACE_OptionsMenu_Disabled"> + <English>No</English> + <German>Nein</German> + <Spanish>No</Spanish> + <Polish>Nie</Polish> + <Czech>Ne</Czech> + <French>Non</French> + <Russian>Нет</Russian> + <Hungarian>Nem</Hungarian> + <Portuguese>Não</Portuguese> + <Italian>No</Italian> + </Key> + <Key ID="STR_ACE_OptionsMenu_Setting"> + <English>Setting:</English> + <Czech>Nastavení:</Czech> + <German>Einstellung:</German> + <Russian>Установки:</Russian> + <Spanish>Ajuste:</Spanish> + <Polish>Ustaw:</Polish> + <French>Paramètres</French> + <Hungarian>Opció:</Hungarian> + <Italian>Parametri:</Italian> + <Portuguese>Opção:</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_Export"> + <English>Export</English> + <German>Exportieren</German> + <Spanish>Exportar</Spanish> + <Russian>Экспорт</Russian> + <Czech>Exportovat</Czech> + <Polish>Eksport</Polish> + <French>Exporter</French> + <Hungarian>Exportálás</Hungarian> + <Italian>Esporta</Italian> + <Portuguese>Exportar</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_OpenExport"> + <English>Open Export Menu</English> + <German>Öffne Exportmenü</German> + <Spanish>Abrir menú de exportación</Spanish> + <Russian>Открыть меню экспорта</Russian> + <Czech>Otevřít exportovací menu</Czech> + <Polish>Otwórz menu eksportowania</Polish> + <French>Ouvrir le menu d'exportation</French> + <Hungarian>Exportálási menü megnyitása</Hungarian> + <Italian>Apri menù esportazione</Italian> + <Portuguese>Abrir menu de exportação</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_stringType"> + <English>String input.</English> + <German>Zeichenketteneingabe</German> + <Spanish>Introducir cadena de texto.</Spanish> + <Russian>Строчный ввод.</Russian> + <Polish>Wpisywanie tekstu.</Polish> + <Czech>Vkládání textu.</Czech> + <French>Entrée</French> + <Hungarian>String bevitel.</Hungarian> + <Italian>Stringa di unput.</Italian> + <Portuguese>Input de String</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_arrayType"> + <English>Array. Seperate elements by using ,.</English> + <German>Array. Teile unterschiedliche Elemente mit ,.</German> + <Spanish>Matriz. Separa elementos usando ,.</Spanish> + <Russian>Массив. Разделяйте элемены, используя запятую.</Russian> + <Polish>Tablica. Oddziel elementy używając ,.</Polish> + <French>Tableau. Séparation par ,.</French> + <Czech>Tabulka. Odděl elementy použitím ,.</Czech> + <Hungarian>Array. Válasszad el az elemeket vesszővel.</Hungarian> + <Italian>Array. Separa gli elementi usando ,.</Italian> + <Portuguese>Vetor. Separe elementos usando *,*.</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_scalarType"> + <English>Number</English> + <German>Zahl</German> + <Spanish>Número</Spanish> + <Russian>Число</Russian> + <Czech>Číslo</Czech> + <Polish>Cyfra</Polish> + <French>Nombre</French> + <Hungarian>Szám</Hungarian> + <Italian>Numero</Italian> + <Portuguese>Número</Portuguese> + </Key> + <Key ID="STR_ACE_optionsMenu_unknownType"> + <English>Uknown input type</English> + <German>Unbekannter Eingabetyp</German> + <Spanish>Tipo de entrada desconocida</Spanish> + <Russian>Неизвестный тип ввода</Russian> + <Czech>Neznámý vstup</Czech> + <Polish>Nieznany rodzaj danych</Polish> + <French>Type d'entrée inconnue</French> + <Hungarian>Ismeretlen beviteli típus</Hungarian> + <Italian>Input inserito sconosciuto</Italian> + <Portuguese>Tipo desonhecido de input</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_SaveInput"> + <English>Save input</English> + <German>Speichere Eingabe</German> + <Spanish>Guardar entrada</Spanish> + <Russian>Сохранить ввод</Russian> + <Czech>Uložit vstup</Czech> + <Polish>Zapisz dane</Polish> + <French>Sauvegarder</French> + <Hungarian>Bevitel elmentése</Hungarian> + <Italian>Salva input</Italian> + <Portuguese>Salvar input</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_inClientSettings"> + <English>Include Client Settings</English> + <German>Schließe Client-Einstellungen ein</German> + <Spanish>Incluir configuración de cliente</Spanish> + <Russian>Включить настройки клиента</Russian> + <Czech>Zahrnout nastavení klienta</Czech> + <Polish>Zawrzyj ustawienia klienta</Polish> + <French>Inclure paramètres client</French> + <Hungarian>Kliens-beállítások melléklése</Hungarian> + <Italian>Includi i parametri del client</Italian> + <Portuguese>Incluir opções do cliente</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_exClientSettings"> + <English>Exclude Client Settings</English> + <German>Schließe Client-Einstellungen aus</German> + <Spanish>Excluir configuración de cliente</Spanish> + <Russian>Исключить настройки клиента</Russian> + <Czech>Nezahrnout nastavení klienta</Czech> + <Polish>Wyklucz ustawienia klienta</Polish> + <French>Exclure paramètres client</French> + <Hungarian>Kliens-beállítások elhagyása</Hungarian> + <Italian>Escludi i parametri del client</Italian> + <Portuguese>Excluir opções do cliente</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_settingsExported"> + <English>Settings exported to clipboard</English> + <German>Einstellungen in die Zwischenablage exportiert</German> + <Spanish>Configuración exportada al portapapeles</Spanish> + <Russian>Настройки экспортированы в буфер обмена</Russian> + <Czech>Nastevení exportována do schránky</Czech> + <Polish>Ustawienia wyeksportowano do schowka</Polish> + <French>Paramètres exportés dans le presse papier</French> + <Hungarian>Beállítások exportálva a vágólapba</Hungarian> + <Italian>Parametri esportati alla clipboard</Italian> + <Portuguese>Opções exportadas para o clipboard.</Portuguese> + </Key> + <Key ID="STR_ACE_optionsMenu_uiScaing"> + <English>Option Menu UI Scaling</English> + <French>Menu option: taille de l'UI</French> + <Polish>Skalowanie UI menu ustawień</Polish> + <Czech>Měřítko UI v menu nastavení</Czech> + <Russian>Размер интерфейса меню настройки</Russian> + <Spanish>Opción de escalado del menú IU</Spanish> + <German>UI Skalierung</German> + <Hungarian>Beállításmenü kezelőfelületének skálázása</Hungarian> + <Portuguese>Escalar o menu de opções</Portuguese> + </Key> + <Key ID="STR_AllowConfigExport_Module_DisplayName"> + <English>Allow Config Export [ACE]</English> + <Polish>Pozwól na eksport ustawień [ACE]</Polish> + </Key> + <Key ID="STR_AllowConfigExport_allowconfigurationExport_DisplayName"> + <English>Allow</English> + <Polish>Zezwól</Polish> + </Key> + <Key ID="STR_AllowConfigExport_allowconfigurationExport_Description"> + <English>Allow export of all settings to a server config formatted.</English> + <Polish>Zezwól na eksport wszystkich ustawień do formatu konfiguracji serwera.</Polish> + </Key> + <Key ID="STR_AllowConfigExport_Module_Description"> + <English>When allowed, you have access to the settings modification and export in SP. Clicking export will place the formated config on your clipboard.</English> + <Polish>Jeżeli ustawione na zezwól, wtedy będziesz mieć dostęp do ekranu modyfikacji wszystich ustawień i zmiennych ACE, a także będziesz mieć możliwość eksportu tychże ustawień do formatu rozpoznawalnego przez userconfig serwera. Kliknięcie opcji Eksportuj skopiuje wszystkie ustawienia do schowka. Działa tylko w trybie SP.</Polish> + </Key> + <Key ID="STR_ACE_Common_Hide"> + <English>Hide</English> + <Polish>Ukryj</Polish> + </Key> + <Key ID="STR_ACE_Common_TopRightDown"> + <English>Top right, downwards</English> + <Polish>Po prawej u góry, w dół</Polish> + </Key> + <Key ID="STR_ACE_Common_TopRightLeft"> + <English>Top right, to the left</English> + <Polish>Po prawej u góry, do lewej</Polish> + </Key> + <Key ID="STR_ACE_Common_TopLeftDown"> + <English>Top left, downwards</English> + <Polish>Po lewej u góry, w dół</Polish> + </Key> + <Key ID="STR_ACE_Common_TopLeftRight"> + <English>Top left, to the right</English> + <Polish>Po lewej u góry, do prawej</Polish> + </Key> + <Key ID="STR_ACE_Common_Top"> + <English>Top</English> + <Polish>Góra</Polish> + </Key> + <Key ID="STR_ACE_Common_Bottom"> + <English>Bottom</English> + <Polish>Dół</Polish> + </Key> + </Package> +</Project> From 44466e8be8c201ba880ee7f806ae9df9842a6122 Mon Sep 17 00:00:00 2001 From: Grzegorz Sikora <gienkov.grzegorz@gmail.com> Date: Tue, 12 May 2015 02:29:32 +0200 Subject: [PATCH 29/51] Remove tabs and repair errors @Glowbal found Conflicts: addons/map/CfgVehicles.hpp addons/medical/CfgVehicles.hpp Conflicts: addons/map/CfgVehicles.hpp addons/medical/CfgVehicles.hpp addons/optionsmenu/stringtable.xml --- addons/captives/stringtable.xml | 8 + addons/common/CfgVehicles.hpp | 8 +- addons/explosives/CfgModule.hpp | 4 +- addons/hearing/CfgVehicles.hpp | 2 +- addons/interaction/CfgVehicles.hpp | 2 +- addons/javelin/CfgVehicles.hpp | 10 +- addons/javelin/CfgWeapons.hpp | 6 +- addons/map/CfgVehicles.hpp | 6 +- addons/medical/CfgVehicles.hpp | 26 +- addons/medical/stringtable.xml | 374 +++++++++++++++- addons/missionmodules/stringtable.xml | 20 +- addons/mk6mortar/script_component.hpp | 4 +- addons/mk6mortar/stringtable.xml | 32 ++ addons/nametags/CfgVehicles.hpp | 2 +- addons/optionsmenu/stringtable.xml | 620 ++++++++++++++------------ addons/respawn/CfgVehicles.hpp | 6 +- addons/switchunits/CfgVehicles.hpp | 4 +- addons/winddeflection/CfgVehicles.hpp | 24 +- addons/winddeflection/stringtable.xml | 20 +- 19 files changed, 824 insertions(+), 354 deletions(-) diff --git a/addons/captives/stringtable.xml b/addons/captives/stringtable.xml index 07cf780e19..0d01cbafc6 100644 --- a/addons/captives/stringtable.xml +++ b/addons/captives/stringtable.xml @@ -201,5 +201,13 @@ <English>Sync a unit to make them surrender.<br />Source: ace_captives</English> <Polish>Zsynchronizuj z jednostką aby sprawić by się poddała<br />Źródło: ace_captives</Polish> </Key> + <Key ID="STR_ACE_Captives_ModuleSurrender_DisplayName"> + <English>Make Unit Surrender</English> + <Polish>Poddaj się!</Polish> + </Key> + <Key ID="STR_ACE_Captives_ModuleSurrender_Description"> + <English>Sync a unit to make them surrender.<br />Source: ace_captives</English> + <Polish>Zsynchronizuj z jednostką aby sprawić by się poddała<br />Źródło: ace_captives</Polish> + </Key> </Package> </Project> diff --git a/addons/common/CfgVehicles.hpp b/addons/common/CfgVehicles.hpp index 65bf2d7058..1adf622494 100644 --- a/addons/common/CfgVehicles.hpp +++ b/addons/common/CfgVehicles.hpp @@ -74,7 +74,7 @@ class CfgVehicles { }; class ModuleDescription: ModuleDescription { description = "$STR_ACE_Common_CheckPBO_Description"; - }; + }; }; class ACE_ModuleLSDVehicles: Module_F { @@ -89,8 +89,8 @@ class CfgVehicles { }; class ModuleDescription: ModuleDescription { description = "$STR_ACE_Common_LSDVehicles_Description"; - sync[] = {"AnyVehicle"}; - }; + sync[] = {"AnyVehicle"}; + }; }; class Box_NATO_Support_F; @@ -124,4 +124,4 @@ class CfgVehicles { }; }; }; -}; \ No newline at end of file +}; diff --git a/addons/explosives/CfgModule.hpp b/addons/explosives/CfgModule.hpp index 9159babc2d..52f70ea3af 100644 --- a/addons/explosives/CfgModule.hpp +++ b/addons/explosives/CfgModule.hpp @@ -24,7 +24,7 @@ class ACE_ModuleExplosive: Module_F { defaultValue = 1; }; }; - class ModuleDescription: ModuleDescription { - description = "$STR_ACE_Explosive_Module_Description"; + class ModuleDescription: ModuleDescription { + description = "$STR_ACE_Explosive_Module_Description"; }; }; \ No newline at end of file diff --git a/addons/hearing/CfgVehicles.hpp b/addons/hearing/CfgVehicles.hpp index 6cec04a242..16bb47014a 100644 --- a/addons/hearing/CfgVehicles.hpp +++ b/addons/hearing/CfgVehicles.hpp @@ -111,7 +111,7 @@ class CfgVehicles { defaultValue = 1; }; }; - class ModuleDescription { + class ModuleDescription { description = "$STR_ACE_Hearing_Module_Description"; }; }; diff --git a/addons/interaction/CfgVehicles.hpp b/addons/interaction/CfgVehicles.hpp index 03466c1986..deb8a4d800 100644 --- a/addons/interaction/CfgVehicles.hpp +++ b/addons/interaction/CfgVehicles.hpp @@ -17,7 +17,7 @@ class CfgVehicles { defaultValue = 1; }; }; - class ModuleDescription { + class ModuleDescription { description = "$STR_ACE_InteractionSystem_Module_Description"; }; }; diff --git a/addons/javelin/CfgVehicles.hpp b/addons/javelin/CfgVehicles.hpp index 48781036ad..1cd527089d 100644 --- a/addons/javelin/CfgVehicles.hpp +++ b/addons/javelin/CfgVehicles.hpp @@ -16,7 +16,7 @@ class CfgVehicles { class MainTurret : MainTurret { weapons[] = { QGVAR(Titan_Static) }; magazines[] = {"1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles"}; - + turretInfoType = "ACE_RscOptics_javelin"; gunnerOpticsModel = PATHTOF(data\reticle_titan.p3d); opticsZoomMin = 0.08333; @@ -29,12 +29,12 @@ class CfgVehicles { }; }; }; - class O_static_AT_F: AT_01_base_F { + class O_static_AT_F: AT_01_base_F { class Turrets : Turrets { class MainTurret : MainTurret { weapons[] = { QGVAR(Titan_Static) }; magazines[] = {"1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles"}; - + turretInfoType = "ACE_RscOptics_javelin"; gunnerOpticsModel = PATHTOF(data\reticle_titan.p3d); opticsZoomMin = 0.08333; @@ -47,12 +47,12 @@ class CfgVehicles { }; }; }; - class I_static_AT_F: AT_01_base_F { + class I_static_AT_F: AT_01_base_F { class Turrets : Turrets { class MainTurret : MainTurret { weapons[] = { QGVAR(Titan_Static) }; magazines[] = {"1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles","1Rnd_GAT_missiles"}; - + turretInfoType = "ACE_RscOptics_javelin"; gunnerOpticsModel = PATHTOF(data\reticle_titan.p3d); opticsZoomMin = 0.08333; diff --git a/addons/javelin/CfgWeapons.hpp b/addons/javelin/CfgWeapons.hpp index 1bbf713b3b..75aaf7c332 100644 --- a/addons/javelin/CfgWeapons.hpp +++ b/addons/javelin/CfgWeapons.hpp @@ -38,7 +38,7 @@ class CfgWeapons { lockingTargetSound[] = {"",0,1}; lockedTargetSound[] = {"",0,1}; }; - class launch_I_Titan_short_F: launch_Titan_short_base { + class launch_I_Titan_short_F: launch_Titan_short_base { GVAR(enabled) = 1; weaponInfoType = "ACE_RscOptics_javelin"; modelOptics = PATHTOF(data\reticle_titan.p3d); @@ -48,7 +48,7 @@ class CfgWeapons { lockingTargetSound[] = {"",0,1}; lockedTargetSound[] = {"",0,1}; }; - class launch_O_Titan_short_F: launch_Titan_short_base { + class launch_O_Titan_short_F: launch_Titan_short_base { GVAR(enabled) = 1; weaponInfoType = "ACE_RscOptics_javelin"; modelOptics = PATHTOF(data\reticle_titan.p3d); @@ -59,7 +59,7 @@ class CfgWeapons { lockingTargetSound[] = {"",0,1}; lockedTargetSound[] = {"",0,1}; }; - class launch_Titan_short_F: launch_Titan_short_base { + class launch_Titan_short_F: launch_Titan_short_base { GVAR(enabled) = 1; weaponInfoType = "ACE_RscOptics_javelin"; modelOptics = PATHTOF(data\reticle_titan.p3d); diff --git a/addons/map/CfgVehicles.hpp b/addons/map/CfgVehicles.hpp index 849549e3d1..a5194e015e 100644 --- a/addons/map/CfgVehicles.hpp +++ b/addons/map/CfgVehicles.hpp @@ -34,7 +34,7 @@ class CfgVehicles { defaultValue = 0; }; }; - class ModuleDescription { + class ModuleDescription { description = "$STR_ACE_Map_Module_Description"; }; }; @@ -51,7 +51,7 @@ class CfgVehicles { class Interval { displayName = "$STR_ACE_Map_BFT_Interval_DisplayName"; description = "$STR_ACE_Map_BFT_Interval_Description"; - typeName = "NUMBER"; + typeName = "NUMBER"; defaultValue = 1; }; class HideAiGroups { @@ -61,7 +61,7 @@ class CfgVehicles { defaultValue = 0; }; }; - class ModuleDescription { + class ModuleDescription { description = "$STR_ACE_Map_BFT_Module_Description"; }; }; diff --git a/addons/medical/CfgVehicles.hpp b/addons/medical/CfgVehicles.hpp index 6c37c5cfd9..e0a6fbcfa0 100644 --- a/addons/medical/CfgVehicles.hpp +++ b/addons/medical/CfgVehicles.hpp @@ -9,7 +9,6 @@ class CfgVehicles { }; }; class ACE_Module; - // TODO localization for all the modules class ACE_moduleMedicalSettings: ACE_Module { scope = 2; displayName = "$STR_ACE_MedicalSettings_Module_DisplayName"; @@ -191,8 +190,12 @@ class CfgVehicles { class consumeItem_PAK { displayName = "$STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_DisplayName"; description = "$STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_Description"; - typeName = "BOOL"; - defaultValue = 1; + + typeName = "NUMBER"; + class values { + class keep { name = "$STR_ACE_Medical_No"; value = 0; }; + class remove { name = "$STR_ACE_Medical_Yes"; value = 1; default = 1; }; + }; }; class useLocation_PAK { displayName = "$STR_ACE_AdvancedMedicalSettings_useLocation_PAK_DisplayName"; @@ -333,8 +336,19 @@ class CfgVehicles { class enabled { displayName = "$STR_ACE_AssignMedicVehicle_enabled_DisplayName"; description = "$STR_ACE_AssignMedicVehicle_enabled_Description"; - typeName = "BOOL"; - defaultValue = 1; + + typeName = "NUMBER"; + class values { + class none { + name = "$STR_ACE_Medical_No"; + value = 0; + }; + class medic { + name = "$STR_ACE_Medical_Yes"; + value = 1; + default = 1; + }; + }; }; }; class ModuleDescription { @@ -1003,4 +1017,4 @@ class CfgVehicles { }; }; }; -}; \ No newline at end of file +}; diff --git a/addons/medical/stringtable.xml b/addons/medical/stringtable.xml index 0eb23d57d4..e522e215ef 100644 --- a/addons/medical/stringtable.xml +++ b/addons/medical/stringtable.xml @@ -3060,6 +3060,378 @@ <English>[ACE] Medical Supply Crate (Advanced)</English> <Polish>[ACE] Skrzynka z zapasami medycznymi (zaawansowana)</Polish> </Key> + <Key ID="STR_ACE_Medical_Category_DisplayName"> + <English>ACE Medical</English> + <Polish>ACE Opcje medyczne</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_Module_DisplayName"> + <English>Medical Settings [ACE]</English> + <Polish>Ustawienia medyczne [ACE]</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_level_DisplayName"> + <English>Medical Level</English> + <Polish>Poziom medyczny</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_level_Description"> + <English>What is the medical simulation level?</English> + <Polish>Jaki jest poziom symulacji medycznej?</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_basic"> + <English>Basic</English> + <Polish>Podstawowy</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_advanced"> + <English>Advanced</English> + <Polish>Zaawansowany</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_medicSetting_DisplayName"> + <English>Medics setting</English> + <Polish>Poziom medyków</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_medicSetting_Description"> + <English>What is the level of detail prefered for medics?</English> + <Polish>Jaki jest poziom detali medycznych wyświetlanych dla medyków?</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_medicSetting_disable"> + <English>Disable medics</English> + <Polish>Wyłącz medyków</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_allowLitterCreation_DisplayName"> + <English>Enable Litter</English> + <Polish>Aktywuj odpadki</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_allowLitterCreation_Description"> + <English>Enable litter being created upon treatment</English> + <Polish>Twórz odpadki medyczne podczas leczenia</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_litterCleanUpDelay_DisplayName"> + <English>Life time of litter objects</English> + <Polish>Długość życia odpadków</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_litterCleanUpDelay_Description"> + <English>How long should litter objects stay? In seconds. -1 is forever.</English> + <Polish>Ile czasu musi upłynąć, aby odpadki zaczęły znikać? W sekundach. -1 dla nieskończoności.</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_enableScreams_DisplayName"> + <English>Enable Screams</English> + <Polish>Aktywuj wrzaski</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_enableScreams_Description"> + <English>Enable screaming by injuried units</English> + <Polish>Aktywuj wrzeszczenie z bólu przez ranne jednostki</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_playerDamageThreshold_DisplayName"> + <English>Player Damage</English> + <Polish>Próg obrażeń graczy</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_playerDamageThreshold_Description"> + <English>What is the damage a player can take before being killed?</English> + <Polish>Jaki jest próg obrażeń, jakie gracz może otrzymać zanim zostanie zabity?</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_AIDamageThreshold_DisplayName"> + <English>AI Damage</English> + <Polish>Próg obrażeń AI</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_AIDamageThreshold_Description"> + <English>What is the damage an AI can take before being killed?</English> + <Polish>Jaki jest próg obrażeń, jakie AI może otrzymać zanim zostanie zabite?</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_enableUnconsciousnessAI_DisplayName"> + <English>AI Unconsciousness</English> + <Polish>Nieprzytomność AI</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_enableUnconsciousnessAI_Description"> + <English>Allow AI to go unconscious</English> + <Polish>Czy AI może być nieprzytomne od odniesionych obrażeń?</Polish> + </Key> + <Key ID="STR_ACE_Medical_disabled"> + <English>Disabled</English> + <Polish>Wyłączone</Polish> + </Key> + <Key ID="STR_ACE_Medical_enabled"> + <English>Enabled</English> + <Polish>Włączone</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_preventInstaDeath_DisplayName"> + <English>Prevent instant death</English> + <Polish>Wył. natychmiast. śmierć</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_preventInstaDeath_Description"> + <English>Have a unit move to unconscious instead of death</English> + <Polish>Spraw, aby jednostka została przeniesiona do stanu nieprzytomności zamiast ginąć na miejscu od śmiertelnych obrażeń</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_bleedingCoefficient_DisplayName"> + <English>Bleeding coefficient</English> + <Polish>Mnożnik krwawienia</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_bleedingCoefficient_Description"> + <English>Coefficient to modify the bleeding speed</English> + <Polish>Mnożnik modyfikujący prędkość wykrwawiania się</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_painCoefficient_DisplayName"> + <English>Pain coefficient</English> + <Polish>Mnożnik bólu</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_painCoefficient_Description"> + <English>Coefficient to modify the pain intensity</English> + <Polish>Mnożnik modyfikujący intensywność bólu</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_keepLocalSettingsSynced_DisplayName"> + <English>Sync status</English> + <Polish>Synchronizuj status</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_keepLocalSettingsSynced_Description"> + <English>Keep unit status synced. Recommended on.</English> + <Polish>Utrzymuj synchronizację statusu jednostek. Zalecane zostawienie tej opcji włączonej.</Polish> + </Key> + <Key ID="STR_ACE_MedicalSettings_Module_Description"> + <English>Provides a medical system for both players and AI.</English> + <Polish>Moduł ten dostarcza system medyczny dla graczy oraz AI.</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_Module_DisplayName"> + <English>Advanced Medical Settings [ACE]</English> + <Polish>Zaawansowane ustawienia medyczne [ACE]</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableFor_DisplayName"> + <English>Enabled for</English> + <Polish>Aktywne dla</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableFor_Description"> + <English>Select what units the advanced medical system will be enabled for</English> + <Polish>Wybierz dla kogo zaawansowany system medyczny będzie aktywny</Polish> + </Key> + <Key ID="STR_ACE_Medical_playeronly"> + <English>Players only</English> + <Polish>Tylko dla graczy</Polish> + </Key> + <Key ID="STR_ACE_Medical_playersandai"> + <English>Players and AI</English> + <Polish>Gracze oraz AI</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableAdvancedWounds_DisplayName"> + <English>Enable Advanced wounds</English> + <Polish>Akt. zaawansowane rany</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableAdvancedWounds_Description"> + <English>Allow reopening of bandaged wounds?</English> + <Polish>Pozwól na otwieranie się zabandażowanych ran?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableVehicleCrashes_DisplayName"> + <English>Vehicle Crashes</English> + <Polish>Obrażenia od kolizji</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_enableVehicleCrashes_Description"> + <English>Do units take damage from a vehicle crash?</English> + <Polish>Czy jednostki otrzymują obrażenia w wyniku kolizji pojazdów?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_PAK_DisplayName"> + <English>Allow PAK</English> + <Polish>Ust. apteczek osobistych</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_PAK_Description"> + <English>Who can use the PAK for full heal?</English> + <Polish>Kto może skorzystać z apteczki osobistej w celu pełnego uleczenia?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_anyone"> + <English>Anyone</English> + <Polish>Wszyscy</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_Medic"> + <English>Medics only</English> + <Polish>Tylko medycy</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_Special"> + <English>Doctors only</English> + <Polish>Tylko doktorzy</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_DisplayName"> + <English>Remove PAK on use</English> + <Polish>Usuń apteczkę po użyciu</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_Description"> + <English>Should PAK be removed on usage?</English> + <Polish>Czy apteczka osobista powinna zniknąć z ekwipunku po jej użyciu?</Polish> + </Key> + <Key ID="STR_ACE_Medical_No"> + <English>No</English> + <Polish>Nie</Polish> + </Key> + <Key ID="STR_ACE_Medical_Yes"> + <English>Yes</English> + <Polish>Tak</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_PAK_DisplayName"> + <English>Locations PAK</English> + <Polish>Ogr. apteczek osobistych</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_PAK_Description"> + <English>Where can the personal aid kit be used?</English> + <Polish>Gdzie można korzystać z apteczek osobistych?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_anywhere"> + <English>Anywhere</English> + <Polish>Wszędzie</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_vehicle"> + <English>Medical vehicles</English> + <Polish>Pojazdy medyczne</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_facility"> + <English>Medical facility</English> + <Polish>Budynki medyczne</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_vehicleAndFacility"> + <English>Vehicles & facility</English> + <Polish>Pojazdy i budynki medyczne</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_disabled"> + <English>Disabled</English> + <Polish>Wyłączone</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_SurgicalKit_DisplayName"> + <English>Allow Surgical kit (Adv)</English> + <Polish>Ust. zestawu chirurg.</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_SurgicalKit_Description"> + <English>Who can use the surgical kit?</English> + <Polish>Kto może skorzystać z zestawu chirurgicznego w celu zszycia ran?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_SurgicalKit_DisplayName"> + <English>Remove Surgical kit (Adv)</English> + <Polish>Usuń zest. chir. po użyciu</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_SurgicalKit_Description"> + <English>Should Surgical kit be removed on usage?</English> + <Polish>Czy zestaw chirurgiczny powinien zniknąć z ekwipunku po jego użyciu?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_SurgicalKit_DisplayName"> + <English>Locations Surgical kit (Adv)</English> + <Polish>Ogr. zestawu chirurg.</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_SurgicalKit_Description"> + <English>Where can the Surgical kit be used?</English> + <Polish>Gdzie można korzystać z zestawu chirurgicznego?</Polish> + </Key> + <Key ID="STR_ACE_AdvancedMedicalSettings_Module_Description"> + <English>Configure the treatment settings from ACE Medical</English> + <Polish>Skonfiguruj zaawansowane ustawienia leczenia systemu medycznego ACE</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_Module_DisplayName"> + <English>Revive Settings [ACE]</English> + <Polish>Ustawienia wskrzeszania [ACE]</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_enableRevive_DisplayName"> + <English>Enable Revive</English> + <Polish>Aktywuj wskrzeszanie</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_enableRevive_Description"> + <English>Enable a basic revive system</English> + <Polish>Aktywuj podstawowy system wskrzeszania</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_maxReviveTime_DisplayName"> + <English>Max Revive time</English> + <Polish>Maks. czas agonii</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_maxReviveTime_Description"> + <English>Max amount of seconds a unit can spend in revive state</English> + <Polish>Maksymalna długość agonii w sekundach (czas na wskrzeszenie)</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_amountOfReviveLives_DisplayName"> + <English>Max Revive lives</English> + <Polish>Maks. ilość wskrzeszeń</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_amountOfReviveLives_Description"> + <English>Max amount of lives a unit. 0 or -1 is disabled.</English> + <Polish>Maksymalna ilość wskrzeszeń. Wpisz 0 lub -1 aby wyłączyć.</Polish> + </Key> + <Key ID="STR_ACE_ReviveSettings_Module_Description"> + <English>Provides a medical system for both players and AI.</English> + <Polish>Moduł ten aktywuje podstawowy system wskrzeszania. Jednostka po otrzymaniu śmiertelnych obrażeń przechodzi do stanu agonii, która trwa określoną długość czasu. W tym czasie aby wskrzesić i jednocześnie odratować jednostkę należy opatrzeć jej rany i wykonać RKO.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_Module_DisplayName"> + <English>Set Medic Class [ACE]</English> + <Polish>Ustaw klasę medyka [ACE]</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_EnableList_DisplayName"> + <English>List</English> + <Polish>Lista</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_EnableList_Description"> + <English>List of unit names that will be classified as medic, separated by commas.</English> + <Polish>Lista nazw jednostek, które są sklasyfikowane jako medycy, oddzielone przecinkami.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_role_DisplayName"> + <English>Is Medic</English> + <Polish>Klasa medyczna</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_role_Description"> + <English></English> + <Polish></Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_role_none"> + <English>None</English> + <Polish>Żadna</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_role_medic"> + <English>Regular medic</English> + <Polish>Zwykły medyk</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_role_doctor"> + <English>Doctor (Only Advanced Medics)</English> + <Polish>Doktor (tylko zaawansowani medycy)</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicRoles_Module_Description"> + <English>Assigns the ACE medic class to a unit</English> + <Polish>Moduł ten przypisuje klasę medyka ACE do jednostek.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_Module_DisplayName"> + <English>Set Medical Vehicle [ACE]</English> + <Polish>Ustaw pojazd medyczny [ACE]</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_EnableList_DisplayName"> + <English>List</English> + <Polish>Lista</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_EnableList_Description"> + <English>List of vehicles that will be classified as medical vehicle, separated by commas.</English> + <Polish>Lista nazw pojazdów, które są sklasyfikowane jako pojazdy medyczne, oddzielone przecinkami.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_enabled_DisplayName"> + <English>Is Medical Vehicle</English> + <Polish>Jest pojazdem med.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_enabled_Description"> + <English>Whatever or not the objects in the list will be a medical vehicle.</English> + <Polish>Czy pojazdy z tej listy są pojazdami medycznymi.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicVehicle_Module_Description"> + <English>Assigns the ACE medic class to a unit</English> + <Polish>Moduł ten pozwala na przypisanie danym pojazdom statusu pojazdów medycznych. Wewnątrz takiego pojazdu można wykonywać zaawansowane zabiegi medyczne.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicalFacility_Module_DisplayName"> + <English>Set Medical Facility [ACE]</English> + <Polish>Ustaw budynek medyczny [ACE]</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicalFacility_enabled_DisplayName"> + <English>Is Medical Facility</English> + <Polish>Jest budynkiem med.</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicalFacility_enabled_Description"> + <English>Registers an object as a medical facility</English> + <Polish>Przypisuje danemu obiektowi status budynku medycznego</Polish> + </Key> + <Key ID="STR_ACE_AssignMedicalFacility_Module_Description"> + <English>Defines an object as a medical facility. This allows for more advanced treatments. Can be used on buildings and vehicles.</English> + <Polish>Moduł ten pozwala przypisać status budynku medycznego danemu obiektowi. Budynek taki pozwala na wykonywanie zaawansowanych zabiegów medycznych. Może być użyte na pojazdach i budynkach.</Polish> + </Key> + <Key ID="STR_ACE_medicalSupplyCrate"> + <English>[ACE] Medical Supply Crate (Basic)</English> + <Polish>[ACE] Skrzynka z zapasami medycznymi (podstawowa)</Polish> + </Key> + <Key ID="STR_ACE_medicalSupplyCrate_advanced"> + <English>[ACE] Medical Supply Crate (Advanced)</English> + <Polish>[ACE] Skrzynka z zapasami medycznymi (zaawansowana)</Polish> + </Key> </Package> </Project> - \ No newline at end of file + diff --git a/addons/missionmodules/stringtable.xml b/addons/missionmodules/stringtable.xml index 12d70602c2..1532827378 100644 --- a/addons/missionmodules/stringtable.xml +++ b/addons/missionmodules/stringtable.xml @@ -14,39 +14,39 @@ <Polish>Dźwięki</Polish> </Key> <Key ID="STR_ACE_MissionModules_AmbianceSounds_soundFiles_Description"> - <English>Classnames of the ambiance sounds played. Seperated by ','. </English> - <Polish>Classname-y dźwięków do odtwarzania. Oddzielone przy użyciu ','.</Polish> + <English>Class names of the ambiance sounds to be played. Seperated by ','</English> + <Polish>Class name-y dźwięków do odtwarzania. Oddzielone przy użyciu ','</Polish> </Key> <Key ID="STR_ACE_MissionModules_AmbianceSounds_minimalDistance_DisplayName"> <English>Minimal Distance</English> <Polish>Minimalny dystans</Polish> </Key> <Key ID="STR_ACE_MissionModules_AmbianceSounds_minimalDistance_Description"> - <English>Minimal Distance</English> - <Polish>Minimalny dystans</Polish> + <English>Used for calculating a random position and sets the minimal distance between the players and the played sound file(s)</English> + <Polish>Używany do obliczania losowej pozycji a także ustawia minimalny dystans pomiędzy graczami a odtwarzanymi plikami dźwiękowymi</Polish> </Key> <Key ID="STR_ACE_MissionModules_AmbianceSounds_maximalDistance_DisplayName"> - <English>Maximal Distance</English> + <English>Maximum Distance</English> <Polish>Maksymalny dystans</Polish> </Key> <Key ID="STR_ACE_MissionModules_AmbianceSounds_maximalDistance_Description"> - <English>Maximal Distance</English> - <Polish>Maksymalny dystans</Polish> + <English>Used for calculating a random position and sets the maximum distance between the players and the played sound file(s)</English> + <Polish>Używany do obliczania losowej pozycji a także ustawia maksymalny dystans pomiędzy graczami a odtwarzanymi plikami dźwiękowymi</Polish> </Key> <Key ID="STR_ACE_MissionModules_AmbianceSounds_minimalDelay_DisplayName"> <English>Minimal Delay</English> <Polish>Minimalne opóźnienie</Polish> </Key> <Key ID="STR_ACE_MissionModules_AmbianceSounds_minimalDelay_Description"> - <English>Minimal Delay between sounds played</English> + <English>Minimal delay between sounds played</English> <Polish>Minimalne opóźnienie pomiędzy odtwarzanymi dźwiękami</Polish> </Key> <Key ID="STR_ACE_MissionModules_AmbianceSounds_maximalDelay_DisplayName"> - <English>Maximal Delay</English> + <English>Maximum Delay</English> <Polish>Maksymalne opóźnienie</Polish> </Key> <Key ID="STR_ACE_MissionModules_AmbianceSounds_maximalDelay_Description"> - <English>Maximal Delay between sounds played</English> + <English>Maximum delay between sounds played</English> <Polish>Maksymalne opóźnienie pomiędzy odtwarzanymi dźwiękami</Polish> </Key> <Key ID="STR_ACE_MissionModules_AmbianceSounds_followPlayers_DisplayName"> diff --git a/addons/mk6mortar/script_component.hpp b/addons/mk6mortar/script_component.hpp index cb74d552de..e1d56d087e 100644 --- a/addons/mk6mortar/script_component.hpp +++ b/addons/mk6mortar/script_component.hpp @@ -2,11 +2,11 @@ #include "\z\ace\Addons\main\script_mod.hpp" #ifdef DEBUG_ENABLED_MK6MORTAR - #define DEBUG_MODE_FULL + #define DEBUG_MODE_FULL #endif #ifdef DEBUG_SETTINGS_MK6MORTAR - #define DEBUG_SETTINGS DEBUG_SETTINGS_MK6MORTAR + #define DEBUG_SETTINGS DEBUG_SETTINGS_MK6MORTAR #endif #include "\z\ace\Addons\main\script_macros.hpp" diff --git a/addons/mk6mortar/stringtable.xml b/addons/mk6mortar/stringtable.xml index 37c7d322ad..cb4a7c5376 100644 --- a/addons/mk6mortar/stringtable.xml +++ b/addons/mk6mortar/stringtable.xml @@ -81,5 +81,37 @@ <English></English> <Polish>Moduł ten pozwala dostosować ustawienia moździerza MK6.</Polish> </Key> + <Key ID="STR_ACE_mk6mortar_Module_DisplayName"> + <English>MK6 Settings</English> + <Polish>Moździerz MK6 - Ustawienia</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_airResistanceEnabled_DisplayName"> + <English>Air Resistance</English> + <Polish>Opór powietrza</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_airResistanceEnabled_Description"> + <English>For Player Shots, Model Air Resistance and Wind Effects</English> + <Polish>Modeluj opór powietrza oraz wpływ wiatru na tor lotu pocisku dla strzałów z moździerza MK6 przez graczy</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_allowComputerRangefinder_DisplayName"> + <English>Allow MK6 Computer</English> + <Polish>Komputer MK6</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_allowComputerRangefinder_Description"> + <English>Show the Computer and Rangefinder (these NEED to be removed if you enable air resistance)</English> + <Polish>Zezwól na komputer i dalmierz (opcja ta MUSI zostać wyłączona jeżeli aktywowałeś opór powietrza)</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_allowCompass_DisplayName"> + <English>Allow MK6 Compass</English> + <Polish>Kompas MK6</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_allowCompass_Description"> + <English>Show the MK6 Digital Compass</English> + <Polish>Pokaż kompas MK6</Polish> + </Key> + <Key ID="STR_ACE_mk6mortar_Module_Description"> + <English></English> + <Polish>Moduł ten pozwala dostosować ustawienia moździerza MK6.</Polish> + </Key> </Package> </Project> diff --git a/addons/nametags/CfgVehicles.hpp b/addons/nametags/CfgVehicles.hpp index a4ef577ecf..fabd3b09cb 100644 --- a/addons/nametags/CfgVehicles.hpp +++ b/addons/nametags/CfgVehicles.hpp @@ -65,7 +65,7 @@ class CfgVehicles { defaultValue = 0; }; }; - class ModuleDescription: ModuleDescription { + class ModuleDescription: ModuleDescription { description = "$STR_ACE_NameTags_Module_Description"; }; }; diff --git a/addons/optionsmenu/stringtable.xml b/addons/optionsmenu/stringtable.xml index f14a97b460..495db21df7 100644 --- a/addons/optionsmenu/stringtable.xml +++ b/addons/optionsmenu/stringtable.xml @@ -1,288 +1,332 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project name="ACE"> - <Package name="OptionsMenu"> - <Key ID="STR_ACE_OptionsMenu_OpenConfigMenu"> - <English>ACE Options</English> - <German>ACE Optionen</German> - <Spanish>Opciones ACE</Spanish> - <Polish>Ustawienia ACE</Polish> - <Czech>ACE Nastavení</Czech> - <French>Options ACE</French> - <Russian>ACE Настройки</Russian> - <Portuguese>Opções do ACE</Portuguese> - <Hungarian>ACE Beállítások</Hungarian> - <Italian>Opzioni ACE</Italian> - </Key> - <Key ID="STR_ACE_OptionsMenu_FixAnimation"> - <English>Fix Animation</English> - <German>Behebe Animation</German> - <Spanish>Arreglar animación</Spanish> - <Russian>Фикс анимации</Russian> - <Czech>Opravit animace</Czech> - <Polish>Napraw animację</Polish> - <French>Corriger animation</French> - <Hungarian>Animációk kijavítása</Hungarian> - <Italian>Fixa l'animazione</Italian> - <Portuguese>Arrumar Animação</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_ResetAll"> - <English>Reset All</English> - <German>Alles zurücksetzen</German> - <Spanish>Reiniciar todo</Spanish> - <Russian>Полный сброс</Russian> - <Czech>Vyresetovat vše</Czech> - <Polish>Resetuj wszystko</Polish> - <French>Défaut</French> - <Hungarian>Minden visszaállítása</Hungarian> - <Italian>Resetta tutto</Italian> - <Portuguese>Resetar Tudo</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_TabColors"> - <English>Colors</English> - <French>Couleurs</French> - <German>Farben</German> - <Spanish>Colores</Spanish> - <Russian>Цвета</Russian> - <Czech>Barvy</Czech> - <Polish>Kolory</Polish> - <Hungarian>Színek</Hungarian> - <Italian>Colori</Italian> - <Portuguese>Cores</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_TabOptions"> - <English>Options</English> - <German>Optionen</German> - <Spanish>Opciones</Spanish> - <Polish>Opcje</Polish> - <Czech>Nastavení</Czech> - <French>Options</French> - <Russian>Настройки</Russian> - <Portuguese>Opções</Portuguese> - <Hungarian>Beállítások</Hungarian> - <Italian>Opzioni</Italian> - </Key> - <Key ID="STR_ACE_OptionsMenu_TabValues"> - <English>Values</English> - <Spanish>Valores</Spanish> - <Russian>Значения</Russian> - <Czech>Hodnoty</Czech> - <Polish>Wartości</Polish> - <French>Valeurs</French> - <German>Werte</German> - <Hungarian>Értékek</Hungarian> - <Italian>Valori</Italian> - <Portuguese>Valores</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_Enabled"> - <English>Yes</English> - <German>Ja</German> - <Spanish>Si</Spanish> - <Polish>Tak</Polish> - <Czech>Ano</Czech> - <French>Oui</French> - <Russian>Да</Russian> - <Hungarian>Igen</Hungarian> - <Portuguese>Sim</Portuguese> - <Italian>Si</Italian> - </Key> - <Key ID="STR_ACE_OptionsMenu_Disabled"> - <English>No</English> - <German>Nein</German> - <Spanish>No</Spanish> - <Polish>Nie</Polish> - <Czech>Ne</Czech> - <French>Non</French> - <Russian>Нет</Russian> - <Hungarian>Nem</Hungarian> - <Portuguese>Não</Portuguese> - <Italian>No</Italian> - </Key> - <Key ID="STR_ACE_OptionsMenu_Setting"> - <English>Setting:</English> - <Czech>Nastavení:</Czech> - <German>Einstellung:</German> - <Russian>Установки:</Russian> - <Spanish>Ajuste:</Spanish> - <Polish>Ustaw:</Polish> - <French>Paramètres</French> - <Hungarian>Opció:</Hungarian> - <Italian>Parametri:</Italian> - <Portuguese>Opção:</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_Export"> - <English>Export</English> - <German>Exportieren</German> - <Spanish>Exportar</Spanish> - <Russian>Экспорт</Russian> - <Czech>Exportovat</Czech> - <Polish>Eksport</Polish> - <French>Exporter</French> - <Hungarian>Exportálás</Hungarian> - <Italian>Esporta</Italian> - <Portuguese>Exportar</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_OpenExport"> - <English>Open Export Menu</English> - <German>Öffne Exportmenü</German> - <Spanish>Abrir menú de exportación</Spanish> - <Russian>Открыть меню экспорта</Russian> - <Czech>Otevřít exportovací menu</Czech> - <Polish>Otwórz menu eksportowania</Polish> - <French>Ouvrir le menu d'exportation</French> - <Hungarian>Exportálási menü megnyitása</Hungarian> - <Italian>Apri menù esportazione</Italian> - <Portuguese>Abrir menu de exportação</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_stringType"> - <English>String input.</English> - <German>Zeichenketteneingabe</German> - <Spanish>Introducir cadena de texto.</Spanish> - <Russian>Строчный ввод.</Russian> - <Polish>Wpisywanie tekstu.</Polish> - <Czech>Vkládání textu.</Czech> - <French>Entrée</French> - <Hungarian>String bevitel.</Hungarian> - <Italian>Stringa di unput.</Italian> - <Portuguese>Input de String</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_arrayType"> - <English>Array. Seperate elements by using ,.</English> - <German>Array. Teile unterschiedliche Elemente mit ,.</German> - <Spanish>Matriz. Separa elementos usando ,.</Spanish> - <Russian>Массив. Разделяйте элемены, используя запятую.</Russian> - <Polish>Tablica. Oddziel elementy używając ,.</Polish> - <French>Tableau. Séparation par ,.</French> - <Czech>Tabulka. Odděl elementy použitím ,.</Czech> - <Hungarian>Array. Válasszad el az elemeket vesszővel.</Hungarian> - <Italian>Array. Separa gli elementi usando ,.</Italian> - <Portuguese>Vetor. Separe elementos usando *,*.</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_scalarType"> - <English>Number</English> - <German>Zahl</German> - <Spanish>Número</Spanish> - <Russian>Число</Russian> - <Czech>Číslo</Czech> - <Polish>Cyfra</Polish> - <French>Nombre</French> - <Hungarian>Szám</Hungarian> - <Italian>Numero</Italian> - <Portuguese>Número</Portuguese> - </Key> - <Key ID="STR_ACE_optionsMenu_unknownType"> - <English>Uknown input type</English> - <German>Unbekannter Eingabetyp</German> - <Spanish>Tipo de entrada desconocida</Spanish> - <Russian>Неизвестный тип ввода</Russian> - <Czech>Neznámý vstup</Czech> - <Polish>Nieznany rodzaj danych</Polish> - <French>Type d'entrée inconnue</French> - <Hungarian>Ismeretlen beviteli típus</Hungarian> - <Italian>Input inserito sconosciuto</Italian> - <Portuguese>Tipo desonhecido de input</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_SaveInput"> - <English>Save input</English> - <German>Speichere Eingabe</German> - <Spanish>Guardar entrada</Spanish> - <Russian>Сохранить ввод</Russian> - <Czech>Uložit vstup</Czech> - <Polish>Zapisz dane</Polish> - <French>Sauvegarder</French> - <Hungarian>Bevitel elmentése</Hungarian> - <Italian>Salva input</Italian> - <Portuguese>Salvar input</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_inClientSettings"> - <English>Include Client Settings</English> - <German>Schließe Client-Einstellungen ein</German> - <Spanish>Incluir configuración de cliente</Spanish> - <Russian>Включить настройки клиента</Russian> - <Czech>Zahrnout nastavení klienta</Czech> - <Polish>Zawrzyj ustawienia klienta</Polish> - <French>Inclure paramètres client</French> - <Hungarian>Kliens-beállítások melléklése</Hungarian> - <Italian>Includi i parametri del client</Italian> - <Portuguese>Incluir opções do cliente</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_exClientSettings"> - <English>Exclude Client Settings</English> - <German>Schließe Client-Einstellungen aus</German> - <Spanish>Excluir configuración de cliente</Spanish> - <Russian>Исключить настройки клиента</Russian> - <Czech>Nezahrnout nastavení klienta</Czech> - <Polish>Wyklucz ustawienia klienta</Polish> - <French>Exclure paramètres client</French> - <Hungarian>Kliens-beállítások elhagyása</Hungarian> - <Italian>Escludi i parametri del client</Italian> - <Portuguese>Excluir opções do cliente</Portuguese> - </Key> - <Key ID="STR_ACE_OptionsMenu_settingsExported"> - <English>Settings exported to clipboard</English> - <German>Einstellungen in die Zwischenablage exportiert</German> - <Spanish>Configuración exportada al portapapeles</Spanish> - <Russian>Настройки экспортированы в буфер обмена</Russian> - <Czech>Nastevení exportována do schránky</Czech> - <Polish>Ustawienia wyeksportowano do schowka</Polish> - <French>Paramètres exportés dans le presse papier</French> - <Hungarian>Beállítások exportálva a vágólapba</Hungarian> - <Italian>Parametri esportati alla clipboard</Italian> - <Portuguese>Opções exportadas para o clipboard.</Portuguese> - </Key> - <Key ID="STR_ACE_optionsMenu_uiScaing"> - <English>Option Menu UI Scaling</English> - <French>Menu option: taille de l'UI</French> - <Polish>Skalowanie UI menu ustawień</Polish> - <Czech>Měřítko UI v menu nastavení</Czech> - <Russian>Размер интерфейса меню настройки</Russian> - <Spanish>Opción de escalado del menú IU</Spanish> - <German>UI Skalierung</German> - <Hungarian>Beállításmenü kezelőfelületének skálázása</Hungarian> - <Portuguese>Escalar o menu de opções</Portuguese> - </Key> - <Key ID="STR_AllowConfigExport_Module_DisplayName"> - <English>Allow Config Export [ACE]</English> - <Polish>Pozwól na eksport ustawień [ACE]</Polish> - </Key> - <Key ID="STR_AllowConfigExport_allowconfigurationExport_DisplayName"> - <English>Allow</English> - <Polish>Zezwól</Polish> - </Key> - <Key ID="STR_AllowConfigExport_allowconfigurationExport_Description"> - <English>Allow export of all settings to a server config formatted.</English> - <Polish>Zezwól na eksport wszystkich ustawień do formatu konfiguracji serwera.</Polish> - </Key> - <Key ID="STR_AllowConfigExport_Module_Description"> - <English>When allowed, you have access to the settings modification and export in SP. Clicking export will place the formated config on your clipboard.</English> - <Polish>Jeżeli ustawione na zezwól, wtedy będziesz mieć dostęp do ekranu modyfikacji wszystich ustawień i zmiennych ACE, a także będziesz mieć możliwość eksportu tychże ustawień do formatu rozpoznawalnego przez userconfig serwera. Kliknięcie opcji Eksportuj skopiuje wszystkie ustawienia do schowka. Działa tylko w trybie SP.</Polish> - </Key> - <Key ID="STR_ACE_Common_Hide"> - <English>Hide</English> - <Polish>Ukryj</Polish> - </Key> - <Key ID="STR_ACE_Common_TopRightDown"> - <English>Top right, downwards</English> - <Polish>Po prawej u góry, w dół</Polish> - </Key> - <Key ID="STR_ACE_Common_TopRightLeft"> - <English>Top right, to the left</English> - <Polish>Po prawej u góry, do lewej</Polish> - </Key> - <Key ID="STR_ACE_Common_TopLeftDown"> - <English>Top left, downwards</English> - <Polish>Po lewej u góry, w dół</Polish> - </Key> - <Key ID="STR_ACE_Common_TopLeftRight"> - <English>Top left, to the right</English> - <Polish>Po lewej u góry, do prawej</Polish> - </Key> - <Key ID="STR_ACE_Common_Top"> - <English>Top</English> - <Polish>Góra</Polish> - </Key> - <Key ID="STR_ACE_Common_Bottom"> - <English>Bottom</English> - <Polish>Dół</Polish> - </Key> - </Package> -</Project> +<?xml version="1.0" encoding="utf-8"?> +<Project name="ACE"> + <Package name="OptionsMenu"> + <Key ID="STR_ACE_OptionsMenu_OpenConfigMenu"> + <English>ACE Options</English> + <German>ACE Optionen</German> + <Spanish>Opciones ACE</Spanish> + <Polish>Ustawienia ACE</Polish> + <Czech>ACE Nastavení</Czech> + <French>Options ACE</French> + <Russian>ACE Настройки</Russian> + <Portuguese>Opções do ACE</Portuguese> + <Hungarian>ACE Beállítások</Hungarian> + <Italian>Opzioni ACE</Italian> + </Key> + <Key ID="STR_ACE_OptionsMenu_FixAnimation"> + <English>Fix Animation</English> + <German>Behebe Animation</German> + <Spanish>Arreglar animación</Spanish> + <Russian>Фикс анимации</Russian> + <Czech>Opravit animace</Czech> + <Polish>Napraw animację</Polish> + <French>Corriger animation</French> + <Hungarian>Animációk kijavítása</Hungarian> + <Italian>Fixa l'animazione</Italian> + <Portuguese>Arrumar Animação</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_ResetAll"> + <English>Reset All</English> + <German>Alles zurücksetzen</German> + <Spanish>Reiniciar todo</Spanish> + <Russian>Полный сброс</Russian> + <Czech>Vyresetovat vše</Czech> + <Polish>Resetuj wszystko</Polish> + <French>Défaut</French> + <Hungarian>Minden visszaállítása</Hungarian> + <Italian>Resetta tutto</Italian> + <Portuguese>Resetar Tudo</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_TabColors"> + <English>Colors</English> + <French>Couleurs</French> + <German>Farben</German> + <Spanish>Colores</Spanish> + <Russian>Цвета</Russian> + <Czech>Barvy</Czech> + <Polish>Kolory</Polish> + <Hungarian>Színek</Hungarian> + <Italian>Colori</Italian> + <Portuguese>Cores</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_TabOptions"> + <English>Options</English> + <German>Optionen</German> + <Spanish>Opciones</Spanish> + <Polish>Opcje</Polish> + <Czech>Nastavení</Czech> + <French>Options</French> + <Russian>Настройки</Russian> + <Portuguese>Opções</Portuguese> + <Hungarian>Beállítások</Hungarian> + <Italian>Opzioni</Italian> + </Key> + <Key ID="STR_ACE_OptionsMenu_TabValues"> + <English>Values</English> + <Spanish>Valores</Spanish> + <Russian>Значения</Russian> + <Czech>Hodnoty</Czech> + <Polish>Wartości</Polish> + <French>Valeurs</French> + <German>Werte</German> + <Hungarian>Értékek</Hungarian> + <Italian>Valori</Italian> + <Portuguese>Valores</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_Enabled"> + <English>Yes</English> + <German>Ja</German> + <Spanish>Si</Spanish> + <Polish>Tak</Polish> + <Czech>Ano</Czech> + <French>Oui</French> + <Russian>Да</Russian> + <Hungarian>Igen</Hungarian> + <Portuguese>Sim</Portuguese> + <Italian>Si</Italian> + </Key> + <Key ID="STR_ACE_OptionsMenu_Disabled"> + <English>No</English> + <German>Nein</German> + <Spanish>No</Spanish> + <Polish>Nie</Polish> + <Czech>Ne</Czech> + <French>Non</French> + <Russian>Нет</Russian> + <Hungarian>Nem</Hungarian> + <Portuguese>Não</Portuguese> + <Italian>No</Italian> + </Key> + <Key ID="STR_ACE_OptionsMenu_Setting"> + <English>Setting:</English> + <Czech>Nastavení:</Czech> + <German>Einstellung:</German> + <Russian>Установки:</Russian> + <Spanish>Ajuste:</Spanish> + <Polish>Ustaw:</Polish> + <French>Paramètres</French> + <Hungarian>Opció:</Hungarian> + <Italian>Parametri:</Italian> + <Portuguese>Opção:</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_Export"> + <English>Export</English> + <German>Exportieren</German> + <Spanish>Exportar</Spanish> + <Russian>Экспорт</Russian> + <Czech>Exportovat</Czech> + <Polish>Eksport</Polish> + <French>Exporter</French> + <Hungarian>Exportálás</Hungarian> + <Italian>Esporta</Italian> + <Portuguese>Exportar</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_OpenExport"> + <English>Open Export Menu</English> + <German>Öffne Exportmenü</German> + <Spanish>Abrir menú de exportación</Spanish> + <Russian>Открыть меню экспорта</Russian> + <Czech>Otevřít exportovací menu</Czech> + <Polish>Otwórz menu eksportowania</Polish> + <French>Ouvrir le menu d'exportation</French> + <Hungarian>Exportálási menü megnyitása</Hungarian> + <Italian>Apri menù esportazione</Italian> + <Portuguese>Abrir menu de exportação</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_stringType"> + <English>String input.</English> + <German>Zeichenketteneingabe</German> + <Spanish>Introducir cadena de texto.</Spanish> + <Russian>Строчный ввод.</Russian> + <Polish>Wpisywanie tekstu.</Polish> + <Czech>Vkládání textu.</Czech> + <French>Entrée</French> + <Hungarian>String bevitel.</Hungarian> + <Italian>Stringa di unput.</Italian> + <Portuguese>Input de String</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_arrayType"> + <English>Array. Seperate elements by using ,.</English> + <German>Array. Teile unterschiedliche Elemente mit ,.</German> + <Spanish>Matriz. Separa elementos usando ,.</Spanish> + <Russian>Массив. Разделяйте элемены, используя запятую.</Russian> + <Polish>Tablica. Oddziel elementy używając ,.</Polish> + <French>Tableau. Séparation par ,.</French> + <Czech>Tabulka. Odděl elementy použitím ,.</Czech> + <Hungarian>Array. Válasszad el az elemeket vesszővel.</Hungarian> + <Italian>Array. Separa gli elementi usando ,.</Italian> + <Portuguese>Vetor. Separe elementos usando *,*.</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_scalarType"> + <English>Number</English> + <German>Zahl</German> + <Spanish>Número</Spanish> + <Russian>Число</Russian> + <Czech>Číslo</Czech> + <Polish>Cyfra</Polish> + <French>Nombre</French> + <Hungarian>Szám</Hungarian> + <Italian>Numero</Italian> + <Portuguese>Número</Portuguese> + </Key> + <Key ID="STR_ACE_optionsMenu_unknownType"> + <English>Uknown input type</English> + <German>Unbekannter Eingabetyp</German> + <Spanish>Tipo de entrada desconocida</Spanish> + <Russian>Неизвестный тип ввода</Russian> + <Czech>Neznámý vstup</Czech> + <Polish>Nieznany rodzaj danych</Polish> + <French>Type d'entrée inconnue</French> + <Hungarian>Ismeretlen beviteli típus</Hungarian> + <Italian>Input inserito sconosciuto</Italian> + <Portuguese>Tipo desonhecido de input</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_SaveInput"> + <English>Save input</English> + <German>Speichere Eingabe</German> + <Spanish>Guardar entrada</Spanish> + <Russian>Сохранить ввод</Russian> + <Czech>Uložit vstup</Czech> + <Polish>Zapisz dane</Polish> + <French>Sauvegarder</French> + <Hungarian>Bevitel elmentése</Hungarian> + <Italian>Salva input</Italian> + <Portuguese>Salvar input</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_inClientSettings"> + <English>Include Client Settings</English> + <German>Schließe Client-Einstellungen ein</German> + <Spanish>Incluir configuración de cliente</Spanish> + <Russian>Включить настройки клиента</Russian> + <Czech>Zahrnout nastavení klienta</Czech> + <Polish>Zawrzyj ustawienia klienta</Polish> + <French>Inclure paramètres client</French> + <Hungarian>Kliens-beállítások melléklése</Hungarian> + <Italian>Includi i parametri del client</Italian> + <Portuguese>Incluir opções do cliente</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_exClientSettings"> + <English>Exclude Client Settings</English> + <German>Schließe Client-Einstellungen aus</German> + <Spanish>Excluir configuración de cliente</Spanish> + <Russian>Исключить настройки клиента</Russian> + <Czech>Nezahrnout nastavení klienta</Czech> + <Polish>Wyklucz ustawienia klienta</Polish> + <French>Exclure paramètres client</French> + <Hungarian>Kliens-beállítások elhagyása</Hungarian> + <Italian>Escludi i parametri del client</Italian> + <Portuguese>Excluir opções do cliente</Portuguese> + </Key> + <Key ID="STR_ACE_OptionsMenu_settingsExported"> + <English>Settings exported to clipboard</English> + <German>Einstellungen in die Zwischenablage exportiert</German> + <Spanish>Configuración exportada al portapapeles</Spanish> + <Russian>Настройки экспортированы в буфер обмена</Russian> + <Czech>Nastevení exportována do schránky</Czech> + <Polish>Ustawienia wyeksportowano do schowka</Polish> + <French>Paramètres exportés dans le presse papier</French> + <Hungarian>Beállítások exportálva a vágólapba</Hungarian> + <Italian>Parametri esportati alla clipboard</Italian> + <Portuguese>Opções exportadas para o clipboard.</Portuguese> + </Key> + <Key ID="STR_ACE_optionsMenu_uiScaing"> + <English>Option Menu UI Scaling</English> + <French>Menu option: taille de l'UI</French> + <Polish>Skalowanie UI menu ustawień</Polish> + <Czech>Měřítko UI v menu nastavení</Czech> + <Russian>Размер интерфейса меню настройки</Russian> + <Spanish>Opción de escalado del menú IU</Spanish> + <German>UI Skalierung</German> + <Hungarian>Beállításmenü kezelőfelületének skálázása</Hungarian> + <Portuguese>Escalar o menu de opções</Portuguese> + </Key> + <Key ID="STR_AllowConfigExport_Module_DisplayName"> + <English>Allow Config Export [ACE]</English> + <Polish>Pozwól na eksport ustawień [ACE]</Polish> + </Key> + <Key ID="STR_AllowConfigExport_allowconfigurationExport_DisplayName"> + <English>Allow</English> + <Polish>Zezwól</Polish> + </Key> + <Key ID="STR_AllowConfigExport_allowconfigurationExport_Description"> + <English>Allow export of all settings to a server config formatted.</English> + <Polish>Zezwól na eksport wszystkich ustawień do formatu konfiguracji serwera.</Polish> + </Key> + <Key ID="STR_AllowConfigExport_Module_Description"> + <English>When allowed, you have access to the settings modification and export in SP. Clicking export will place the formated config on your clipboard.</English> + <Polish>Jeżeli ustawione na zezwól, wtedy będziesz mieć dostęp do ekranu modyfikacji wszystich ustawień i zmiennych ACE, a także będziesz mieć możliwość eksportu tychże ustawień do formatu rozpoznawalnego przez userconfig serwera. Kliknięcie opcji Eksportuj skopiuje wszystkie ustawienia do schowka. Działa tylko w trybie SP.</Polish> + </Key> + <Key ID="STR_ACE_Common_Hide"> + <English>Hide</English> + <Polish>Ukryj</Polish> + </Key> + <Key ID="STR_ACE_Common_TopRightDown"> + <English>Top right, downwards</English> + <Polish>Po prawej u góry, w dół</Polish> + </Key> + <Key ID="STR_ACE_Common_TopRightLeft"> + <English>Top right, to the left</English> + <Polish>Po prawej u góry, do lewej</Polish> + </Key> + <Key ID="STR_ACE_Common_TopLeftDown"> + <English>Top left, downwards</English> + <Polish>Po lewej u góry, w dół</Polish> + </Key> + <Key ID="STR_ACE_Common_TopLeftRight"> + <English>Top left, to the right</English> + <Polish>Po lewej u góry, do prawej</Polish> + </Key> + <Key ID="STR_ACE_Common_Top"> + <English>Top</English> + <Polish>Góra</Polish> + </Key> + <Key ID="STR_ACE_Common_Bottom"> + <English>Bottom</English> + <Polish>Dół</Polish> + </Key> + <Key ID="STR_AllowConfigExport_Module_DisplayName"> + <English>Allow Config Export [ACE]</English> + <Polish>Pozwól na eksport ustawień [ACE]</Polish> + </Key> + <Key ID="STR_AllowConfigExport_allowconfigurationExport_DisplayName"> + <English>Allow</English> + <Polish>Zezwól</Polish> + </Key> + <Key ID="STR_AllowConfigExport_allowconfigurationExport_Description"> + <English>Allow export of all settings to a server config formatted.</English> + <Polish>Zezwól na eksport wszystkich ustawień do formatu konfiguracji serwera.</Polish> + </Key> + <Key ID="STR_AllowConfigExport_Module_Description"> + <English>When allowed, you have access to the settings modification and export in SP. Clicking export will place the formated config on your clipboard.</English> + <Polish>Jeżeli ustawione na zezwól, wtedy będziesz mieć dostęp do ekranu modyfikacji wszystich ustawień i zmiennych ACE, a także będziesz mieć możliwość eksportu tychże ustawień do formatu rozpoznawalnego przez userconfig serwera. Kliknięcie opcji Eksportuj skopiuje wszystkie ustawienia do schowka. Działa tylko w trybie SP.</Polish> + </Key> + <Key ID="STR_ACE_Common_Hide"> + <English>Hide</English> + <Polish>Ukryj</Polish> + </Key> + <Key ID="STR_ACE_Common_TopRightDown"> + <English>Top right, downwards</English> + <Polish>Po prawej u góry, w dół</Polish> + </Key> + <Key ID="STR_ACE_Common_TopRightLeft"> + <English>Top right, to the left</English> + <Polish>Po prawej u góry, do lewej</Polish> + </Key> + <Key ID="STR_ACE_Common_TopLeftDown"> + <English>Top left, downwards</English> + <Polish>Po lewej u góry, w dół</Polish> + </Key> + <Key ID="STR_ACE_Common_TopLeftRight"> + <English>Top left, to the right</English> + <Polish>Po lewej u góry, do prawej</Polish> + </Key> + <Key ID="STR_ACE_Common_Top"> + <English>Top</English> + <Polish>Góra</Polish> + </Key> + <Key ID="STR_ACE_Common_Bottom"> + <English>Bottom</English> + <Polish>Dół</Polish> + </Key> + </Package> +</Project> diff --git a/addons/respawn/CfgVehicles.hpp b/addons/respawn/CfgVehicles.hpp index 00f0bd4493..e90f4ba08e 100644 --- a/addons/respawn/CfgVehicles.hpp +++ b/addons/respawn/CfgVehicles.hpp @@ -27,7 +27,7 @@ class CfgVehicles { defaultValue = 1; }; }; - class ModuleDescription: ModuleDescription { + class ModuleDescription: ModuleDescription { description = "$STR_ACE_Respawn_Module_Description"; }; }; @@ -42,7 +42,7 @@ class CfgVehicles { icon = QUOTE(PATHTOF(UI\Icon_Module_FriendlyFire_ca.paa)); class Arguments {}; - class ModuleDescription: ModuleDescription { + class ModuleDescription: ModuleDescription { description = "$STR_ACE_FriendlyFire_Module_Description"; }; }; @@ -57,7 +57,7 @@ class CfgVehicles { icon = QUOTE(PATHTOF(UI\Icon_Module_Rallypoint_ca.paa)); class Arguments {}; - class ModuleDescription: ModuleDescription { + class ModuleDescription: ModuleDescription { description = "$STR_ACE_Rallypoint_Module_Description"; }; }; diff --git a/addons/switchunits/CfgVehicles.hpp b/addons/switchunits/CfgVehicles.hpp index 48271c6428..0f76c78568 100644 --- a/addons/switchunits/CfgVehicles.hpp +++ b/addons/switchunits/CfgVehicles.hpp @@ -46,8 +46,8 @@ class CfgVehicles { defaultValue = 100; }; }; - class ModuleDescription { - description = "$STR_ACE_SwitchUnits_Module_Description"; + class ModuleDescription { + description = "$STR_ACE_SwitchUnits_Module_Description"; }; }; }; \ No newline at end of file diff --git a/addons/winddeflection/CfgVehicles.hpp b/addons/winddeflection/CfgVehicles.hpp index 2ce9421071..f7e2a33980 100644 --- a/addons/winddeflection/CfgVehicles.hpp +++ b/addons/winddeflection/CfgVehicles.hpp @@ -2,7 +2,7 @@ class CfgVehicles { class ACE_Module; class GVAR(ModuleSettings): ACE_Module { scope = 2; - displayName = "$STR_ACE_WEATHER_WINDDEFLECTION_DISPLAYNAME"; //WIND DEFLECTION + displayName = "$STR_ACE_Weather_windDeflection_DisplayName"; icon = QUOTE(PATHTOF(UI\Icon_Module_Wind_ca.paa)); category = "ACE"; function = QUOTE(DFUNC(initModuleSettings)); @@ -12,32 +12,32 @@ class CfgVehicles { author = "$STR_ACE_Common_ACETeam"; class Arguments { class enabled { - displayName = "$STR_ACE_WEATHER_DEFLECTIONMODULE_DISPLAYNAME"; - description = "$STR_ACE_WEATHER_DEFLECTIONMODULE_DESCRIPTION"; + displayName = "$STR_ACE_Weather_deflectionModule_DisplayName"; + description = "$STR_ACE_Weather_deflectionModule_Description"; typeName = "BOOL"; defaultValue = 1; }; class vehicleEnabled { - displayName = "$STR_ACE_WEATHER_VEHICLEENABLED_DISPLAYNAME"; - description = "$STR_ACE_WEATHER_VEHICLEENABLED_DESCRIPTION"; + displayName = "$STR_ACE_Weather_vehicleEnabled_DisplayName"; + description = "$STR_ACE_Weather_vehicleEnabled_Description"; typeName = "BOOL"; defaultValue = 1; }; class simulationInterval { - displayName = "$STR_ACE_WEATHER_SIMULATIONINTERVAL_DISPLAYNAME"; - description = "$STR_ACE_WEATHER_SIMULATIONINTERVAL_DESCRIPTION"; + displayName = "$STR_ACE_Weather_simulationInterval_DisplayName"; + description = "$STR_ACE_Weather_simulationInterval_Description"; typeName = "NUMBER"; defaultValue = 0.05; }; class simulationRadius { - displayName = "$STR_ACE_WEATHER_SIMULATIONRADIUS_DISPLAYNAME"; - description = "$STR_ACE_WEATHER_SIMULATIONRADIUS_DESCRIPTION"; + displayName = "$STR_ACE_Weather_simulationRadius_DisplayName"; + description = "$STR_ACE_Weather_simulationRadius_Description"; typeName = "NUMBER"; defaultValue = 3000; }; }; - class ModuleDescription { - description = "$STR_ACE_WEATHER_WINDDEFLECTION_DESCRIPTION"; - }; + class ModuleDescription { + description = "$STR_ACE_Weather_windDeflection_Description"; + }; }; }; \ No newline at end of file diff --git a/addons/winddeflection/stringtable.xml b/addons/winddeflection/stringtable.xml index 515591bd32..806bf4c449 100644 --- a/addons/winddeflection/stringtable.xml +++ b/addons/winddeflection/stringtable.xml @@ -62,43 +62,43 @@ <Italian>Umidità: %1%</Italian> <Portuguese>Humidade: %1%</Portuguese> </Key> - <Key ID="STR_ACE_WEATHER_WINDDEFLECTION_DISPLAYNAME"> + <Key ID="STR_ACE_Weather_windDeflection_DisplayName"> <English>Wind Deflection</English> <Polish>Wpływ wiatru</Polish> </Key> - <Key ID="STR_ACE_WEATHER_DEFLECTIONMODULE_DISPLAYNAME"> + <Key ID="STR_ACE_Weather_deflectionModule_DisplayName"> <English>Wind Deflection</English> <Polish>Wpływ wiatru</Polish> </Key> - <Key ID="STR_ACE_WEATHER_DEFLECTIONMODULE_DESCRIPTION"> + <Key ID="STR_ACE_Weather_deflectionModule_Description"> <English>Enables wind deflection</English> <Polish>Aktywuje wpływ wiatru na trajektorię lotu pocisków</Polish> </Key> - <Key ID="STR_ACE_WEATHER_VEHICLEENABLED_DISPLAYNAME"> + <Key ID="STR_ACE_Weather_vehicleEnabled_DisplayName"> <English>Vehicle Enabled</English> <Polish>Włączone dla pojazdów</Polish> </Key> - <Key ID="STR_ACE_WEATHER_VEHICLEENABLED_DESCRIPTION"> + <Key ID="STR_ACE_Weather_vehicleEnabled_Description"> <English>Enables wind deflection for static/vehicle gunners</English> <Polish>Aktywuje wpływ wiatru na trajektorię lotu pocisków dla broni statycznej i na pojazdach</Polish> </Key> - <Key ID="STR_ACE_WEATHER_SIMULATIONINTERVAL_DISPLAYNAME"> + <Key ID="STR_ACE_Weather_simulationInterval_DisplayName"> <English>Simulation Interval</English> <Polish>Interwał symulacji</Polish> </Key> - <Key ID="STR_ACE_WEATHER_SIMULATIONINTERVAL_DESCRIPTION"> + <Key ID="STR_ACE_Weather_simulationInterval_Description"> <English>Defines the interval between every calculation step</English> <Polish>Określa interwał pomiędzy każdym krokiem kalkulacji</Polish> </Key> - <Key ID="STR_ACE_WEATHER_SIMULATIONRADIUS_DISPLAYNAME"> + <Key ID="STR_ACE_Weather_simulationRadius_DisplayName"> <English>Simulation Radius</English> <Polish>Zasięg symulacji</Polish> </Key> - <Key ID="STR_ACE_WEATHER_SIMULATIONRADIUS_DESCRIPTION"> + <Key ID="STR_ACE_Weather_simulationRadius_Description"> <English>Defines the radius around the player (in meters) at which projectiles are wind deflected</English> <Polish>Określa obszar naokoło gracza (w metrach), na którym pociski są znoszone przez wiatr</Polish> </Key> - <Key ID="STR_ACE_WEATHER_WINDDEFLECTION_DESCRIPTION"> + <Key ID="STR_ACE_Weather_windDeflection_Description"> <English>Wind influence on projectiles trajectory</English> <Polish>Wpływ wiatru na trajektorię lotu pocisków</Polish> </Key> From bc72c71e8e193fe6ab359906d6f41fc7b5b41cc4 Mon Sep 17 00:00:00 2001 From: GieNkoV <gienkov.grzegorz@gmail.com> Date: Tue, 12 May 2015 19:11:56 +0200 Subject: [PATCH 30/51] Fix small errors inside stringtables --- addons/common/stringtable.xml | 12 +- addons/explosives/stringtable.xml | 14 +- addons/hearing/stringtable.xml | 2 +- addons/interaction/stringtable.xml | 26 ++- addons/medical/stringtable.xml | 45 ++--- addons/missileguidance/stringtable.xml | 226 ++++++++++++------------- addons/optionsmenu/stringtable.xml | 1 + 7 files changed, 170 insertions(+), 156 deletions(-) diff --git a/addons/common/stringtable.xml b/addons/common/stringtable.xml index 5b908a9133..8f5ebe7191 100644 --- a/addons/common/stringtable.xml +++ b/addons/common/stringtable.xml @@ -275,7 +275,7 @@ <French>Désactiver menu commande</French> <Russian>Выключить командное меню</Russian> <Hungarian>Parancsnoki menü kikapcsolása</Hungarian> - <Italian>Disabilita Menù di comando</Italian> + <Italian>Disabilita menù di comando</Italian> <Portuguese>Desabilitar menu de comando</Portuguese> </Key> <Key ID="STR_ACE_Common_Unknown"> @@ -308,7 +308,7 @@ <Spanish>Aceptar peticiones</Spanish> <Polish>Akceptuj prośby</Polish> <Czech>Přijmout žádost</Czech> - <Italian>Accetta Richieste</Italian> + <Italian>Accetta la richiesta</Italian> <French>Accepter requête</French> <Russian>Принять запросы</Russian> <Hungarian>Kérések elfogadása</Hungarian> @@ -320,7 +320,7 @@ <Spanish>Rechazar peticiones</Spanish> <Polish>Ignoruj prośby</Polish> <Czech>Zamítnout žádost</Czech> - <Italian>Rifiuta Richieste</Italian> + <Italian>Rifiuta la richiesta</Italian> <Russian>Отклонить запросы</Russian> <French>Rejeter requête</French> <Hungarian>Kérések elutasítása</Hungarian> @@ -402,7 +402,7 @@ <English>Hint Background color</English> <German>Hintergrundfarbe der Hinweise</German> <Spanish>Color de fondo de las notificaciones</Spanish> - <Italian>Colore di sfondo dei Suggerimenti</Italian> + <Italian>Colore di sfondo dei suggerimenti</Italian> <Russian>Цвет фона всплывающих подсказок</Russian> <Polish>Kolor tła powiadomień</Polish> <French>Notification: couleur de l'arrière plan</French> @@ -414,7 +414,7 @@ <English>The color of the background from the ACE hints.</English> <German>Die Hintergrundfarbe der ACE-Hinweise.</German> <Spanish>El color de fondo de las notificaciones del ACE</Spanish> - <Italian>Il colore di sfondo dei suggerimenti dell'ACE.</Italian> + <Italian>Il colore di sfondo dei suggerimenti di ACE.</Italian> <Russian>Цвет фона всплывающих подсказок АСЕ.</Russian> <Polish>Kolor tła dla powiadomień ACE</Polish> <French>Notification ACE: couleur de l'arrière plan</French> @@ -426,7 +426,7 @@ <English>Hint text font color</English> <German>Textfarbe der Hinweise</German> <Spanish>Color del texto de las notificaciones</Spanish> - <Italian>Il colore del Testo dei Suggerimenti</Italian> + <Italian>Il colore del testo dei suggerimenti</Italian> <Russian>Цвет шрифта всплывающих подсказок</Russian> <Polish>Kolor tekstu powiadomień</Polish> <French>Notification: couleur du texte</French> diff --git a/addons/explosives/stringtable.xml b/addons/explosives/stringtable.xml index 42b5160030..5f5076175d 100644 --- a/addons/explosives/stringtable.xml +++ b/addons/explosives/stringtable.xml @@ -368,7 +368,7 @@ <Polish>Wybierz zapalnik</Polish> <French>Sélectionner une mise à feu</French> <Czech>Zvolit Detonátor</Czech> - <Italian>Seleziona un Attivatore</Italian> + <Italian>Seleziona un attivatore</Italian> <Hungarian>Gyújtóeszköz kiválasztása</Hungarian> <Portuguese>Selecionar um Gatilho</Portuguese> <Russian>Выберите детонатор</Russian> @@ -392,7 +392,7 @@ <German>Druckplatte</German> <French>Plaque de pression</French> <Czech>Nášlapná nástraha</Czech> - <Italian>Piastra a Pressione</Italian> + <Italian>Piastra a pressione</Italian> <Hungarian>Nyomólap</Hungarian> <Portuguese>Placa de pressão</Portuguese> <Russian>Нажимная плита</Russian> @@ -404,7 +404,7 @@ <German>Stolperdraht</German> <French>Fil de détente</French> <Czech>Nástražný drát</Czech> - <Italian>Filo a Inciampo</Italian> + <Italian>Filo a inciampo</Italian> <Hungarian>Botlódrót</Hungarian> <Portuguese>Linha de tração</Portuguese> <Russian>Растяжка</Russian> @@ -440,7 +440,7 @@ <German>Infrarotsensor (Seitenangriff)</German> <French>Capteur IR (de flanc)</French> <Czech>IR Značkovač (Výbuch stranou)</Czech> - <Italian>Sensore IR (Attacco laterale)</Italian> + <Italian>Sensore IR (attacco laterale)</Italian> <Hungarian>Infravörös szenzor (Side Attack)</Hungarian> <Portuguese>Sensor infravermelho (ataque lateral)</Portuguese> <Russian>ИК сенсор (детонация вбок)</Russian> @@ -452,7 +452,7 @@ <German>Magnetfeldsensor (Bodenangriff)</German> <French>Capteur magnétique (par le bas)</French> <Czech>Magnetický Senzor (Výbuch ze spoda)</Czech> - <Italian>Sensore Magnetico di Prossimità (Attacco inferiore)</Italian> + <Italian>Sensore Magnetico di Prossimità (attacco inferiore)</Italian> <Hungarian>Mágneses mező érzékelő (Bottom Attack)</Hungarian> <Portuguese>Influência magnética (ataque inferior)</Portuguese> <Russian>Магнитный сенсор (детонация вверх)</Russian> @@ -462,7 +462,7 @@ <German>Keine Sprengladungen auf diesem Auslöser.</German> <Spanish>Ningún explosivo en el detonador.</Spanish> <French>Pas d'explosif à mettre à feu.</French> - <Italian>Nessun esplosivo sul sensore.</Italian> + <Italian>Nessun esplosivo</Italian> <Czech>Žádná výbušnina k odpálení.</Czech> <Hungarian>Nincs robbanóanyag a gyújtóeszközhöz kötve.</Hungarian> <Polish>Brak ładunków na zapalnik.</Polish> @@ -491,7 +491,7 @@ <Hungarian>Robbanóanyagok távoli robbantásához</Hungarian> <Portuguese>Usado para detonar remotamente o explosivo quando solto.</Portuguese> <Russian>Используется для дистанционного подрыва, после смерти оператора.</Russian> - <Italian>Usato per attivare esplosivi al momento del rilascio</Italian> + <Italian>Usato per attivare a distanza esplosivi al momento del rilascio</Italian> </Key> <Key ID="STR_ACE_Explosives_Pickup"> <English>Pick up</English> diff --git a/addons/hearing/stringtable.xml b/addons/hearing/stringtable.xml index ae7bea38a2..9e960f6d63 100644 --- a/addons/hearing/stringtable.xml +++ b/addons/hearing/stringtable.xml @@ -106,7 +106,7 @@ <Czech>Vypnout pískání v uších</Czech> <Polish>Wyłącz dzwonienie w uszach</Polish> <Hungarian>Fülcsengés letiltása</Hungarian> - <Italian>Disabilita il ronzio</Italian> + <Italian>Disabilita i fischi nelle orecchie</Italian> <Portuguese>Desabilitar zumbido de ouvidos</Portuguese> </Key> <Key ID="STR_ACE_Hearing_Module_DisplayName"> diff --git a/addons/interaction/stringtable.xml b/addons/interaction/stringtable.xml index 0e6e89b74c..19296083a6 100644 --- a/addons/interaction/stringtable.xml +++ b/addons/interaction/stringtable.xml @@ -119,7 +119,7 @@ <Russian>Меню взаимодействия (с собой)</Russian> <Hungarian>Cselekvő menü (saját) </Hungarian> <Portuguese>Menu de Interação (Individual)</Portuguese> - <Italian>Menù interazione (Individuale)</Italian> + <Italian>Menù interazione (individuale)</Italian> </Key> <Key ID="STR_ACE_Interaction_OpenDoor"> <English>Open / Close Door</English> @@ -263,7 +263,7 @@ <Russian>Жесты</Russian> <Hungarian>Kézjelek</Hungarian> <Portuguese>Gestos</Portuguese> - <Italian>Segnali gestuali</Italian> + <Italian>Gesti</Italian> </Key> <Key ID="STR_ACE_Interaction_Gestures_Attack"> <English>Attack</English> @@ -443,7 +443,7 @@ <Czech>Někdo tě poklepal na PRAVÉ rameno</Czech> <Russian>Вас похлопали по ПРАВОМУ плечу</Russian> <Portuguese>Você foi tocado no ombro</Portuguese> - <Italian>Ti è stato dato un colpetto sulla spalla</Italian> + <Italian>Ti è stato dato un colpetto sulla spalla destra</Italian> </Key> <Key ID="STR_ACE_Interaction_YouWereTappedLeft"> <English>You were tapped on the LEFT shoulder.</English> @@ -455,7 +455,7 @@ <Czech>Někdo tě poklepal na LEVÉ rameno</Czech> <Russian>Вас похлопали по ЛЕВОМУ плечу</Russian> <Portuguese>Você foi tocado no ombro.</Portuguese> - <Italian>Ti è stato dato un colpetto sulla spalla</Italian> + <Italian>Ti è stato dato un colpetto sulla spalla sinistra</Italian> </Key> <Key ID="STR_ACE_Interaction_CancelSelection"> <English>Cancel</English> @@ -503,7 +503,7 @@ <Hungarian>A földre!</Hungarian> <Russian>Ложись!</Russian> <Portuguese>Abaixe-se!</Portuguese> - <Italian>A Terra!</Italian> + <Italian>A terra!</Italian> </Key> <Key ID="STR_ACE_Interaction_TeamManagement"> <English>Team Management</English> @@ -575,6 +575,7 @@ <Czech>Přiřadit k červeným</Czech> <Russian>Назначить в Красную группу</Russian> <French>Assigner à rouge</French> + <Italian>Assegna al team rosso</Italian> </Key> <Key ID="STR_ACE_Interaction_AssignTeamGreen"> <English>Assign Green</English> @@ -586,6 +587,7 @@ <Czech>Přiřadit k zeleným</Czech> <Russian>Назначить в Зеленую группу</Russian> <French>Assigner à vert</French> + <Italian>Assegna al team verde</Italian> </Key> <Key ID="STR_ACE_Interaction_AssignTeamBlue"> <English>Assign Blue</English> @@ -597,6 +599,7 @@ <Czech>Přiřadit k modrým</Czech> <Russian>Назначить в Синюю группу</Russian> <French>Assigner à bleu</French> + <Italian>Assegna al team blu</Italian> </Key> <Key ID="STR_ACE_Interaction_AssignTeamYellow"> <English>Assign Yellow</English> @@ -608,6 +611,7 @@ <Czech>Přiřadit ke žlutým</Czech> <Russian>Назначить в Желтую группу</Russian> <French>Assigner à jaune</French> + <Italian>Assegna al team giallo</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamRed"> <English>Join Red</English> @@ -619,6 +623,7 @@ <Czech>Připojit k červeným</Czech> <Russian>Присоединиться к Красной группе</Russian> <French>Rejoindre rouge</French> + <Italian>Unirsi al team rosso</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamGreen"> <English>Join Green</English> @@ -630,6 +635,7 @@ <Czech> Připojit k zeleným</Czech> <Russian>Присоединиться к Зеленой группе</Russian> <French>Rejoindre vert</French> + <Italian>Unirsi al team verde</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamBlue"> <English>Join Blue</English> @@ -641,6 +647,7 @@ <Czech>Připojit k modrým</Czech> <Russian>Присоединиться к Синей группе</Russian> <French>Rejoindre bleu</French> + <Italian>Unirsi al team blu</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamYellow"> <English>Join Yellow</English> @@ -652,6 +659,7 @@ <Czech>Připojit ke žlutým</Czech> <Russian>Присоединиться к Жёлтой группе</Russian> <French>Rejoindre jaune</French> + <Italian>Unirsi al team giallo</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinedTeam"> <English>You joined Team %1</English> @@ -721,7 +729,7 @@ <Spanish>Tecla modificadora</Spanish> <Russian>Клавиша-модификатор</Russian> <Portuguese>Tecla Modificadora</Portuguese> - <Italian>Modifica tasto</Italian> + <Italian>Tasto modifica</Italian> <Hungarian>Módosító billentyű</Hungarian> <Czech>Modifikátor</Czech> </Key> @@ -735,7 +743,7 @@ <Hungarian>Hatótávolságon kívül</Hungarian> <Polish>Poza zasięgiem</Polish> <Czech>Mimo dosah</Czech> - <Italian>Non in raggio</Italian> + <Italian>Fuori limite</Italian> </Key> <Key ID="STR_ACE_Interaction_Equipment"> <English>Equipment</English> @@ -758,8 +766,8 @@ <Czech>Odstrčit</Czech> <Hungarian>Tolás</Hungarian> <Russian>Толкать</Russian> - <Italian>Spingi</Italian> <Portuguese>Empurrar</Portuguese> + <Italian>Spingere</Italian> </Key> <Key ID="STR_ACE_Interaction_Interact"> <English>Interact</English> @@ -770,7 +778,7 @@ <Polish>Interakcja</Polish> <Spanish>Interactuar</Spanish> <Hungarian>Cselekvés</Hungarian> - <Italian>Interagisci</Italian> + <Italian>Interagire</Italian> <Portuguese>Interagir</Portuguese> </Key> <Key ID="STR_ACE_Interaction_Passengers"> diff --git a/addons/medical/stringtable.xml b/addons/medical/stringtable.xml index e522e215ef..9cfc7e15d5 100644 --- a/addons/medical/stringtable.xml +++ b/addons/medical/stringtable.xml @@ -83,7 +83,7 @@ <French>Injecter de la morphine</French> <Hungarian>Morfium beadása</Hungarian> <Portuguese>Injetar Morfina</Portuguese> - <Italian>Inietta Morfina</Italian> + <Italian>Inietta morfina</Italian> </Key> <Key ID="STR_ACE_Medical_Transfuse_Blood"> <English>Transfuse Blood</English> @@ -95,7 +95,7 @@ <French>Transfusion</French> <Hungarian>Infúzió (vér)</Hungarian> <Portuguese>Transfundir Sangue</Portuguese> - <Italian>Effettua trasfusione di sangue</Italian> + <Italian>Trasfusione di sangue</Italian> </Key> <Key ID="STR_ACE_Medical_Transfuse_Plasma"> <English>Transfuse Plasma</English> @@ -106,7 +106,7 @@ <French>Transfuser du Plasma</French> <Russian>Перелить плазму</Russian> <Hungarian>Infúzió (vérplazma)</Hungarian> - <Italian>Effettua trasfusione di plasma</Italian> + <Italian>Trasfusione di Plasma</Italian> <Portuguese>Transfundir Plasma</Portuguese> </Key> <Key ID="STR_ACE_Medical_Transfuse_Saline"> @@ -118,7 +118,7 @@ <French>Transfuser de la solution saline</French> <Russian>Перелить физраствор</Russian> <Hungarian>Infúzió (sós víz)</Hungarian> - <Italian>Effettua trasfusione di soluzione salina</Italian> + <Italian>Trasfusione di soluzione salina</Italian> <Portuguese>Transfundir Soro</Portuguese> </Key> <Key ID="STR_ACE_Medical_Apply_Tourniquet"> @@ -274,7 +274,7 @@ <French>Transfusion de saline ...</French> <Russian>Переливание физраствора ...</Russian> <Hungarian>Infúzió sós vizzel ...</Hungarian> - <Italian>Effettuo la rasfusione di salina</Italian> + <Italian>Effettuo la rasfusione di soluzione salina</Italian> <Portuguese>Transfundindo Soro...</Portuguese> </Key> <Key ID="STR_ACE_Medical_Transfusing_Plasma"> @@ -370,7 +370,7 @@ <Czech>QuikClot</Czech> <French>Hémostatique</French> <Hungarian>QuikClot</Hungarian> - <Italian>QuikClot(polvere emostatica)</Italian> + <Italian>QuikClot (polvere emostatica)</Italian> <Portuguese>QuikClot</Portuguese> </Key> <Key ID="STR_ACE_Medical_Actions_CheckPulse"> @@ -632,7 +632,7 @@ <Polish>Natychmiastowy</Polish> <French>Urgence Immédiate</French> <German>Sofort</German> - <Czech>Okamžiý</Czech> + <Czech>Okamžitý</Czech> <Hungarian>Azonnali</Hungarian> <Italian>Immediata</Italian> <Portuguese>Imediato</Portuguese> @@ -801,7 +801,7 @@ <French>Bandage fait d'un matériel spécial utilisé pour couvrir une blessure, qui peut etre appliqué dès que le saignement a été stoppé.</French> <Polish>Opatrunek materiałowy, używany do przykrywania ran, zakładany na ranę po zatamowaniu krwawienia.</Polish> <Hungarian>Egy különleges anyagú kötszer sebek betakarására, amelyet a vérzés elállítása után helyeznek fel.</Hungarian> - <Italian>Una benda apposita, utilizzata per coprire una ferita, la quale è applicata sopra di essa una volta fermata l'emorragia.</Italian> + <Italian>Una benda apposita, utilizzata per coprire una ferita, la quale viene applicata su di essa una volta fermata l'emorragia.</Italian> <Portuguese>Uma curativo, material específico para cobrir um ferimento que é aplicado assim que o sangramento é estancando.</Portuguese> <Czech>Obvaz je vhodným způsobem upravený sterilní materiál, určený k překrytí rány, případně k fixaci poranění.</Czech> </Key> @@ -825,7 +825,7 @@ <French>Utilisé pour couvrir des blessures de taille moyenne à grande. Arrête l'hémorragies</French> <Polish>Używany w celu opatrywania średnich i dużych ran oraz tamowania krwawienia.</Polish> <Hungarian>Közepestől nagyig terjedő sebek betakarására és vérzés elállítására használt kötszer</Hungarian> - <Italian>Usato su medie o larghe ferite per fermare emorragie.</Italian> + <Italian>Usato su ferite medie o larghe per fermare emorragie.</Italian> <Portuguese>Usado para o preenchimento de cavidades geradas por ferimentos médios e grandes e estancar o sangramento.</Portuguese> <Czech>Používá se k zastavení středních až silnějších krvácení</Czech> </Key> @@ -850,7 +850,7 @@ <Polish>Bandaż (elastyczny)</Polish> <Czech>Obvaz (elastický)</Czech> <Hungarian>Rögzító kötszer</Hungarian> - <Italian>Benda (Elastica)</Italian> + <Italian>Benda (elastica)</Italian> <Portuguese>Bandagem (Elástica)</Portuguese> </Key> <Key ID="STR_ACE_Medical_Bandage_Elastic_Desc_Short"> @@ -861,7 +861,7 @@ <French>Bandage compressif élastique</French> <Polish>Zestaw bandaży elastycznych.</Polish> <Hungarian>Rugalmas kötszercsomag, "rögzítő"</Hungarian> - <Italian>Kit bendaggio, elastico</Italian> + <Italian>Kit di bendaggio, elastico</Italian> <Portuguese>Kit de Bandagem, Elástica</Portuguese> <Czech>Sada obvazů, Elastická</Czech> </Key> @@ -873,7 +873,7 @@ <Polish>Elastyczna opaska podtrzymująca opatrunek oraz usztywniająca okolice stawów.</Polish> <Spanish>Brinda una compresión uniforme y ofrece soporte extra a una zona lesionada</Spanish> <Hungarian>Egyenletes nyomást és támogatást biztosít a sebesült felületnek.</Hungarian> - <Italian>Permette di comprimevere e aiutare la zone ferita.</Italian> + <Italian>Permette di comprimere e aiutare la zone ferita.</Italian> <Portuguese>Esta bandagem pode ser utilizada para comprimir o ferimento e diminuir o sangramento e garantir que o ferimento não abra em movimento.</Portuguese> <Czech>Hodí se k fixačním účelům a to i v oblastech kloubů.</Czech> </Key> @@ -958,7 +958,7 @@ <German>Atropin Autoinjektor</German> <Czech>Autoinjektor atropin</Czech> <Hungarian>Atropin autoinjektor</Hungarian> - <Italian>Autoiniettore di Atropina</Italian> + <Italian>Autoiniettore di atropina</Italian> <Portuguese>Auto-injetor de Atropina</Portuguese> </Key> <Key ID="STR_ACE_Medical_Atropine_Desc_Short"> @@ -994,7 +994,7 @@ <German>Epiniphrin Autoinjektor</German> <Czech>Autoinjektor adrenalin</Czech> <Hungarian>Epinefrin autoinjektor</Hungarian> - <Italian>Autoiniettore di Epinefrina</Italian> + <Italian>Autoiniettore di epinefrina</Italian> <Portuguese>Auto-injetor de epinefrina</Portuguese> </Key> <Key ID="STR_ACE_Medical_Epinephrine_Desc_Short"> @@ -1271,6 +1271,7 @@ <Hungarian>Elsősegélycsomag, terepen való sebvarráshoz és haladó ellátáshoz</Hungarian> <Portuguese>Kit de primeiros socorros para sutura ou tratamentos avançados</Portuguese> <Czech>Osobní lékárnička obsahuje zdravotnický materiál umožňující šití a pokročilejší ošetřování raněných v poli </Czech> + <Italian>Pronto soccorso personale da campo per mettersi i punti o per trattamenti avanzati.</Italian> </Key> <Key ID="STR_ACE_Medical_Use_Aid_Kit"> <English>Use Personal Aid Kit</English> @@ -1282,13 +1283,14 @@ <Hungarian>Elsősegélycsomag használata</Hungarian> <Portuguese>Usar o kit de primeiros socorros</Portuguese> <Czech>Použít osobní lékárničku</Czech> + <Italian>Usa il pronto soccorso personale</Italian> </Key> <Key ID="STR_ACE_Medical_SurgicalKit_Display"> <English>Surgical Kit</English> <French>Trousse chirurgicale</French> <Russian>Хирургический набор</Russian> <Spanish>Kit quirúrgico</Spanish> - <Polish>Zestaw chirurgiczny</Polish> + <Polish>Zestaw do szycia ran</Polish> <German>Operationsset</German> <Hungarian>Sebészeti készlet</Hungarian> <Italian>Kit chirurgico</Italian> @@ -1583,10 +1585,6 @@ <Czech>%1 zkontroloval srdeční tep: %2</Czech> <Portuguese>%1 verificou a frequência cardíaca: %2</Portuguese> </Key> - <Key ID="STR_ACE_Medical_Check_Pulse_None"> - <English>None</English> - <Polish>Brak</Polish> - </Key> <Key ID="STR_ACE_Medical_Check_Pulse_Weak"> <English>Weak</English> <German>Schwach</German> @@ -1781,7 +1779,7 @@ </Key> <Key ID="STR_ACE_Medical_lostBlood"> <English>He's lost some blood</English> - <Italian>Ha perso molto sangue</Italian> + <Italian>Ha perso sangue</Italian> <Spanish>Ha perdido un poco de sangre</Spanish> <Russian>Есть кровопотеря</Russian> <German>Er hat etwas Blut verloren</German> @@ -1801,6 +1799,7 @@ <French>Il a perdu beaucoup de sang</French> <Czech>Ztratil hodně krve</Czech> <Portuguese>Ele perdeu muito sangue</Portuguese> + <Italian>Ha perso molto sangue</Italian> </Key> <Key ID="STR_ACE_Medical_noBloodloss"> <English>He hasn't lost blood</English> @@ -2244,6 +2243,7 @@ <Czech>Styl menu (Zdravotní)</Czech> <Portuguese>Estilo do menu (Médico)</Portuguese> <Hungarian>Menü stílusa (Orvosi)</Hungarian> + <Italian>Stile del menù (medico)</Italian> </Key> <Key ID="STR_ACE_Medical_menuTypeDescription"> <English>Select the type of menu you prefer; default 3d selections or radial.</English> @@ -2255,6 +2255,7 @@ <Portuguese>Selecione o tipo de menu que você prefere; padrão seleções 3d ou radial.</Portuguese> <Hungarian>Válaszd ki a neked megfelelő menüt: Alapértelmezett 3D válogatás, vagy kerek.</Hungarian> <Czech>Zvolte typ menu: základní 3D výběr nebo kruhový</Czech> + <Italian>Seleziona il tipo di menù che preferisci: selezione 3d predefinita o radiale.</Italian> </Key> <Key ID="STR_ACE_Medical_useSelection"> <English>Selections (3d)</English> @@ -2266,6 +2267,7 @@ <Portuguese>Seleção (3d)</Portuguese> <Hungarian>Választékok (3D)</Hungarian> <Czech>3D výběr</Czech> + <Italian>Selezione (3D)</Italian> </Key> <Key ID="STR_ACE_Medical_useRadial"> <English>Radial</English> @@ -2277,6 +2279,7 @@ <Portuguese>Radial</Portuguese> <Hungarian>Kerek</Hungarian> <Czech>Kruhový</Czech> + <Italian>Radiale</Italian> </Key> <Key ID="STR_ACE_Medical_Wounds_Abrasion"> <English>Scrape</English> @@ -2684,6 +2687,7 @@ <Spanish>Tratando ...</Spanish> <Portuguese>Tratando...</Portuguese> <Czech>Ošetřuji ...</Czech> + <Italian>Curando ...</Italian> </Key> <Key ID="STR_ACE_Medical_RemovingTourniquet"> <English>Removing Tourniquet ...</English> @@ -2695,6 +2699,7 @@ <Hungarian>Érszorító eltávolítása ...</Hungarian> <Czech>Sundavám škrtidlo ...</Czech> <Russian>Снятие жгута ...</Russian> + <Italian>Togliendo il laccio emostatico ...</Italian> </Key> <Key ID="STR_ACE_Medical_Category_DisplayName"> <English>ACE Medical</English> diff --git a/addons/missileguidance/stringtable.xml b/addons/missileguidance/stringtable.xml index ef9bdeea26..24149e61a0 100644 --- a/addons/missileguidance/stringtable.xml +++ b/addons/missileguidance/stringtable.xml @@ -1,113 +1,113 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project name="ACE"> - <Package name="missileguidance"> - <Key ID="STR_ACE_MissileGuidance"> - <English>Advanced Missile Guidance</English> - <Spanish>Guiado Avanzado de Misiles</Spanish> - <French>Guidage avancé de missile</French> - <Polish>Zaawansowane naprowadzanie rakiet</Polish> - <German>Erweitertes Raketenlenksystem</German> - <Czech>Pokročilé řízení střel</Czech> - <Italian>Guida missili avanzata</Italian> - <Portuguese>Avançado Missile Guidance</Portuguese> - <Hungarian>Fejlett rakétairányító</Hungarian> - <Russian>Продвинутое наведение ракет</Russian> - </Key> - <Key ID="STR_ACE_MissileGuidance_Desc"> - <English>Advanced missile guidance, or AMG, provides multiple enhancements to missile locking and firing. It is also a framework required for missile weapon types.</English> - <Polish>Zaawansowane namierzanie rakiet, lub ZNR, dostarcza wiele poprawek do systemu namierzania rakiet oraz dodaje nowe tryby strzału. Jest to wymagana opcja dla broni rakietowych.</Polish> - <Italian>Guida dei missili avanzata, o AMG, offre diversi miglioramenti alla teleguida di missili. E' anche un sistema necessario per i tipi di armi missile.</Italian> - <Russian>Продвинутое наведение ракет, или ПНР, обеспечивает множество усовершествований для наведения и стрельбы ракет. Также, это система, необходимая для всех ракетных типов оружия.</Russian> - <Spanish>Guiado Avanzado de Misiles, o AMG en sus siglas en inglés, ofrece múltiples mejoras en el fijado y disparo de misiles. Es también un sistema requerido para armas de tipo misil.</Spanish> - <German>Das Erweiterte Raketenlenksystem, auch ERls genannt, bietet viele Verbesserungen zum Aufschalten und Feuern mittels gelenkten Raketen. </German> - <French>Le guidage avancé de missile, ou AMG en anglais, apporte de multiple améliorations au verouillage et au tir de missiles. C'est aussi un framework requis pour tout arme de type missile.</French> - <Hungarian>A fejlett rakétairányító (vagy AMG) többféle módosítást tartalmaz a rakéták célkövetéséhez és tüzeléséhez. Ez egy szükséges keresztrendszer a rakéta-alapú fegyverekhez.</Hungarian> - <Portuguese>Orientação avançada de mísseis ou OAM, fornece vários aprimoramentos para travamento de mísseis e disparos. Também é um sistema requerido para disparar armas que utilizem mísseis.</Portuguese> - <Czech>Pokočilé navádění raket (AMG) poskytuje několik vylepšení pro lepší zaměření a následnou střelbu. Je to prvek vyžadovaný u typu zbraní jako jsou rakety.</Czech> - </Key> - <Key ID="STR_ACE_Hydra70_DAGR"> - <English>Hydra-70 DAGR Missile</English> - <Spanish>Misil Hydra-70 DAGR</Spanish> - <French>Hydra-70 DAGR</French> - <Polish>Hydra-70 DAGR</Polish> - <German>Hydra-70 DAGR Rackete</German> - <Czech>Hydra-70 DAGR</Czech> - <Italian>Missile Hydra-70 DAGR</Italian> - <Portuguese>Míssil Hydra-70 DAGR </Portuguese> - <Hungarian>Hydra-70 DAGR rakéta</Hungarian> - <Russian>Hydra-70 DAGR</Russian> - </Key> - <Key ID="STR_ACE_Hydra70_DAGR_Short"> - <English>DAGR</English> - <Spanish>DAGR</Spanish> - <French>DAGR</French> - <Polish>DAGR</Polish> - <German>DAGR</German> - <Czech>DAGR</Czech> - <Italian>DAGR</Italian> - <Portuguese>DAGR</Portuguese> - <Hungarian>DAGR</Hungarian> - <Russian>DAGR</Russian> - </Key> - <Key ID="STR_ACE_Hydra70_DAGR_Desc"> - <English>Hydra-70 DAGR Laser Guided Missile</English> - <Spanish>Misil guiado por láser Hydra-70 DAGR</Spanish> - <French>Missile à guidage laser Hydra-70 DAGR</French> - <Polish>Laserowo naprowadzana rakieta Hydra-70 DAGR</Polish> - <German>Hydra-70 DAGR lasergelenkte Rakete</German> - <Czech>Hydra-70 DAGR laserem naváděná střela</Czech> - <Italian>Hydra-70 DAGR missile guida laser</Italian> - <Portuguese>Míssil guiado a laser Hydra-70 DAGR </Portuguese> - <Hungarian>Hydra-70 DAGR lézer-irányított rakéta</Hungarian> - <Russian>Управляемая ракета лазерного наведения Hydra-70 DAGR</Russian> - </Key> - <Key ID="STR_ACE_Hellfire_AGM114K"> - <English>Hellfire II AGM-114K Missile</English> - <Spanish>Misil Hellfire II AGM-114K</Spanish> - <French>Hellfire II AGM-114K</French> - <Polish>Hellfire II AGM-114K</Polish> - <German>Hellfire II AGM-114K</German> - <Czech>Hellfire II AGM-114K</Czech> - <Italian>Missile Hellfire II AGM-114K</Italian> - <Portuguese>Míssil Hellfire II AGM-114K</Portuguese> - <Hungarian>Hellfire II AGM-114K rakéta</Hungarian> - <Russian>Hellfire II AGM-114K</Russian> - </Key> - <Key ID="STR_ACE_Hellfire_AGM114K_Short"> - <English>AGM-114K</English> - <Spanish>AGM-114K</Spanish> - <French>AGM-114K</French> - <Polish>AGM-114K</Polish> - <German>AGM-114K</German> - <Czech>AGM-114K</Czech> - <Italian>AGM-114K</Italian> - <Portuguese>AGM-114K</Portuguese> - <Hungarian>AGM-114K</Hungarian> - <Russian>AGM-114K</Russian> - </Key> - <Key ID="STR_ACE_Hellfire_AGM114K_desc"> - <English>Hellfire II AGM-114K Laser Guided Missile</English> - <Spanish>Misil guiado por láser Hellfire II AGM-114K</Spanish> - <French>Missile à guidage laser Hellfire II AGM-114K</French> - <Polish>Laserowo naprowadzana rakieta Hellfire II AGM-114K</Polish> - <German>Hellfire II AGM-114K Lasergelenkte Rakete</German> - <Czech>Hellfire II AGM-114K laserem naváděná střela</Czech> - <Italian>Missile guida laser Hellfire II AGM-114K</Italian> - <Portuguese>Míssil guiado a laser Hellfire II AGM-114K</Portuguese> - <Hungarian>Hellfire II AGM-114K lézer-irányított rakéta</Hungarian> - <Russian>Управляемая ракета лазерного наведения Hellfire II AGM-114K</Russian> - </Key> - <Key ID="STR_ACE_MissileGuidance_Off"> - <English>Off</English> - <Polish>Wyłącz</Polish> - </Key> - <Key ID="STR_ACE_MissileGuidance_PlayerOnly"> - <English>Player Only</English> - <Polish>Tylko gracz</Polish> - </Key> - <Key ID="STR_ACE_MissileGuidance_PlayerAndAi"> - <English>Player and AI</English> - <Polish>Gracz oraz AI</Polish> - </Key> - </Package> -</Project> +<?xml version="1.0" encoding="utf-8"?> +<Project name="ACE"> + <Package name="missileguidance"> + <Key ID="STR_ACE_MissileGuidance"> + <English>Advanced Missile Guidance</English> + <Spanish>Guiado Avanzado de Misiles</Spanish> + <French>Guidage avancé de missile</French> + <Polish>Zaawansowane naprowadzanie rakiet</Polish> + <German>Erweitertes Raketenlenksystem</German> + <Czech>Pokročilé řízení střel</Czech> + <Italian>Guida missili avanzata</Italian> + <Portuguese>Avançado Missile Guidance</Portuguese> + <Hungarian>Fejlett rakétairányító</Hungarian> + <Russian>Продвинутое наведение ракет</Russian> + </Key> + <Key ID="STR_ACE_MissileGuidance_Desc"> + <English>Advanced missile guidance, or AMG, provides multiple enhancements to missile locking and firing. It is also a framework required for missile weapon types.</English> + <Polish>Zaawansowane namierzanie rakiet, lub ZNR, dostarcza wiele poprawek do systemu namierzania rakiet oraz dodaje nowe tryby strzału. Jest to wymagana opcja dla broni rakietowych.</Polish> + <Italian>Guida dei missili avanzata, o AMG, offre diversi miglioramenti alla teleguida di missili. E' anche un sistema necessario per i tipi di armi missile.</Italian> + <Russian>Продвинутое наведение ракет, или ПНР, обеспечивает множество усовершествований для наведения и стрельбы ракет. Также, это система, необходимая для всех ракетных типов оружия.</Russian> + <Spanish>Guiado Avanzado de Misiles, o AMG en sus siglas en inglés, ofrece múltiples mejoras en el fijado y disparo de misiles. Es también un sistema requerido para armas de tipo misil.</Spanish> + <German>Das Erweiterte Raketenlenksystem, auch ERls genannt, bietet viele Verbesserungen zum Aufschalten und Feuern mittels gelenkten Raketen. </German> + <French>Le guidage avancé de missile, ou AMG en anglais, apporte de multiple améliorations au verouillage et au tir de missiles. C'est aussi un framework requis pour tout arme de type missile.</French> + <Hungarian>A fejlett rakétairányító (vagy AMG) többféle módosítást tartalmaz a rakéták célkövetéséhez és tüzeléséhez. Ez egy szükséges keresztrendszer a rakéta-alapú fegyverekhez.</Hungarian> + <Portuguese>Orientação avançada de mísseis ou OAM, fornece vários aprimoramentos para travamento de mísseis e disparos. Também é um sistema requerido para disparar armas que utilizem mísseis.</Portuguese> + <Czech>Pokočilé navádění raket (AMG) poskytuje několik vylepšení pro lepší zaměření a následnou střelbu. Je to prvek vyžadovaný u typu zbraní jako jsou rakety.</Czech> + </Key> + <Key ID="STR_ACE_Hydra70_DAGR"> + <English>Hydra-70 DAGR Missile</English> + <Spanish>Misil Hydra-70 DAGR</Spanish> + <French>Hydra-70 DAGR</French> + <Polish>Hydra-70 DAGR</Polish> + <German>Hydra-70 DAGR Rackete</German> + <Czech>Hydra-70 DAGR</Czech> + <Italian>Missile Hydra-70 DAGR</Italian> + <Portuguese>Míssil Hydra-70 DAGR </Portuguese> + <Hungarian>Hydra-70 DAGR rakéta</Hungarian> + <Russian>Hydra-70 DAGR</Russian> + </Key> + <Key ID="STR_ACE_Hydra70_DAGR_Short"> + <English>DAGR</English> + <Spanish>DAGR</Spanish> + <French>DAGR</French> + <Polish>DAGR</Polish> + <German>DAGR</German> + <Czech>DAGR</Czech> + <Italian>DAGR</Italian> + <Portuguese>DAGR</Portuguese> + <Hungarian>DAGR</Hungarian> + <Russian>DAGR</Russian> + </Key> + <Key ID="STR_ACE_Hydra70_DAGR_Desc"> + <English>Hydra-70 DAGR Laser Guided Missile</English> + <Spanish>Misil guiado por láser Hydra-70 DAGR</Spanish> + <French>Missile à guidage laser Hydra-70 DAGR</French> + <Polish>Laserowo naprowadzana rakieta Hydra-70 DAGR</Polish> + <German>Hydra-70 DAGR lasergelenkte Rakete</German> + <Czech>Hydra-70 DAGR laserem naváděná střela</Czech> + <Italian>Hydra-70 DAGR missile guida laser</Italian> + <Portuguese>Míssil guiado a laser Hydra-70 DAGR </Portuguese> + <Hungarian>Hydra-70 DAGR lézer-irányított rakéta</Hungarian> + <Russian>Управляемая ракета лазерного наведения Hydra-70 DAGR</Russian> + </Key> + <Key ID="STR_ACE_Hellfire_AGM114K"> + <English>Hellfire II AGM-114K Missile</English> + <Spanish>Misil Hellfire II AGM-114K</Spanish> + <French>Hellfire II AGM-114K</French> + <Polish>Hellfire II AGM-114K</Polish> + <German>Hellfire II AGM-114K</German> + <Czech>Hellfire II AGM-114K</Czech> + <Italian>Missile Hellfire II AGM-114K</Italian> + <Portuguese>Míssil Hellfire II AGM-114K</Portuguese> + <Hungarian>Hellfire II AGM-114K rakéta</Hungarian> + <Russian>Hellfire II AGM-114K</Russian> + </Key> + <Key ID="STR_ACE_Hellfire_AGM114K_Short"> + <English>AGM-114K</English> + <Spanish>AGM-114K</Spanish> + <French>AGM-114K</French> + <Polish>AGM-114K</Polish> + <German>AGM-114K</German> + <Czech>AGM-114K</Czech> + <Italian>AGM-114K</Italian> + <Portuguese>AGM-114K</Portuguese> + <Hungarian>AGM-114K</Hungarian> + <Russian>AGM-114K</Russian> + </Key> + <Key ID="STR_ACE_Hellfire_AGM114K_desc"> + <English>Hellfire II AGM-114K Laser Guided Missile</English> + <Spanish>Misil guiado por láser Hellfire II AGM-114K</Spanish> + <French>Missile à guidage laser Hellfire II AGM-114K</French> + <Polish>Laserowo naprowadzana rakieta Hellfire II AGM-114K</Polish> + <German>Hellfire II AGM-114K Lasergelenkte Rakete</German> + <Czech>Hellfire II AGM-114K laserem naváděná střela</Czech> + <Italian>Missile guida laser Hellfire II AGM-114K</Italian> + <Portuguese>Míssil guiado a laser Hellfire II AGM-114K</Portuguese> + <Hungarian>Hellfire II AGM-114K lézer-irányított rakéta</Hungarian> + <Russian>Управляемая ракета лазерного наведения Hellfire II AGM-114K</Russian> + </Key> + <Key ID="STR_ACE_MissileGuidance_Off"> + <English>Off</English> + <Polish>Wyłącz</Polish> + </Key> + <Key ID="STR_ACE_MissileGuidance_PlayerOnly"> + <English>Player Only</English> + <Polish>Tylko gracz</Polish> + </Key> + <Key ID="STR_ACE_MissileGuidance_PlayerAndAi"> + <English>Player and AI</English> + <Polish>Gracz oraz AI</Polish> + </Key> + </Package> +</Project> diff --git a/addons/optionsmenu/stringtable.xml b/addons/optionsmenu/stringtable.xml index 495db21df7..aa78e83645 100644 --- a/addons/optionsmenu/stringtable.xml +++ b/addons/optionsmenu/stringtable.xml @@ -239,6 +239,7 @@ <German>UI Skalierung</German> <Hungarian>Beállításmenü kezelőfelületének skálázása</Hungarian> <Portuguese>Escalar o menu de opções</Portuguese> + <Italian>Proporzioni della interfaccia utente</Italian> </Key> <Key ID="STR_AllowConfigExport_Module_DisplayName"> <English>Allow Config Export [ACE]</English> From ed1acd8c15089324690a4a476d542abed27f38ee Mon Sep 17 00:00:00 2001 From: GieNkoV <gienkov.grzegorz@gmail.com> Date: Tue, 12 May 2015 19:42:35 +0200 Subject: [PATCH 31/51] Some small errors fixed #2 Mainly tabs and wrong italian strings (got those from newest master) --- addons/common/stringtable.xml | 6 +++--- addons/interaction/stringtable.xml | 18 +++++++++--------- addons/nametags/stringtable.xml | 8 ++++---- addons/optionsmenu/stringtable.xml | 16 ++++++++-------- addons/respawn/stringtable.xml | 2 ++ 5 files changed, 26 insertions(+), 24 deletions(-) diff --git a/addons/common/stringtable.xml b/addons/common/stringtable.xml index 8f5ebe7191..1b960de982 100644 --- a/addons/common/stringtable.xml +++ b/addons/common/stringtable.xml @@ -308,11 +308,11 @@ <Spanish>Aceptar peticiones</Spanish> <Polish>Akceptuj prośby</Polish> <Czech>Přijmout žádost</Czech> - <Italian>Accetta la richiesta</Italian> <French>Accepter requête</French> <Russian>Принять запросы</Russian> <Hungarian>Kérések elfogadása</Hungarian> <Portuguese>Aceitar Pedido</Portuguese> + <Italian>Accetta la richiesta</Italian> </Key> <Key ID="STR_ACE_ACTION_DECLINE_REQUEST_KEY_TITLE"> <English>Decline Requests</English> @@ -320,11 +320,11 @@ <Spanish>Rechazar peticiones</Spanish> <Polish>Ignoruj prośby</Polish> <Czech>Zamítnout žádost</Czech> - <Italian>Rifiuta la richiesta</Italian> <Russian>Отклонить запросы</Russian> <French>Rejeter requête</French> <Hungarian>Kérések elutasítása</Hungarian> <Portuguese>Rejeitar pedido</Portuguese> + <Italian>Rifiuta la richiesta</Italian> </Key> <Key ID="STR_ACE_ACTION_ACCEPT_REQUEST_KEY_TOOLTIP"> <English>Accept Requests send by other players. These can be requests to use / share equipment, perform certain actions.</English> @@ -438,7 +438,7 @@ <English>The color of the text font from the ACE hints. This color is the default color for all text displayed through the ACE Hint system, if the hint text has no other color specified.</English> <German>Wähle die Textfarbe für ACE-Hinweise. Die gewählte Farbe wird als Standartfarbe der Hinweise angezeigt, wenn der Hinweis selbst keine spezifische Farbe hat. </German> <Spanish>El color del texto de las notificaciones del ACE. Este es el color predeterminado para todo el texto que se muestra a través del sistema de notificaciones del ACE, si el texto de notificación no tiene otro color especificado.</Spanish> - <Italian>Il colore del testo dei suggerimenti dell'ACE. Questo è il colore standard per tutti i caratteri mostrati dal sistema di suggerimenti dell'ACE, se il colore del testo non è specificato.</Italian> + <Italian>Il colore del testo dei suggerimenti di ACE. Questo è il colore predefinito per tutto il testo mostrato dal sistema di suggerimenti di ACE quando il colore del testo non ha altro colore specificato.</Italian> <Russian>Цвет шрифта текста всплывающих подсказок АСЕ. Этот цвет является стандартным для всего текста, транслирующегося через систему подсказок АСЕ, если не установлено другого цвета для текста подсказок.</Russian> <Polish>Kolor tekstu dla powiadomień ACE. Ten kolor jest domyślnym dla wszystkich tekstów wyświetlanych poprzez System Powiadomień ACE, jeżeli dla powiadomienia nie określono innego koloru.</Polish> <French>Notification ACE: couleur du texte. C'est la couleur par défaut de tout texte affiché dans les notifications ACE, si aucune couleur n'est spécifiée pour les notifications</French> diff --git a/addons/interaction/stringtable.xml b/addons/interaction/stringtable.xml index 19296083a6..b2e75ccdff 100644 --- a/addons/interaction/stringtable.xml +++ b/addons/interaction/stringtable.xml @@ -575,7 +575,7 @@ <Czech>Přiřadit k červeným</Czech> <Russian>Назначить в Красную группу</Russian> <French>Assigner à rouge</French> - <Italian>Assegna al team rosso</Italian> + <Italian>Assegna al team rosso</Italian> </Key> <Key ID="STR_ACE_Interaction_AssignTeamGreen"> <English>Assign Green</English> @@ -587,7 +587,7 @@ <Czech>Přiřadit k zeleným</Czech> <Russian>Назначить в Зеленую группу</Russian> <French>Assigner à vert</French> - <Italian>Assegna al team verde</Italian> + <Italian>Assegna al team verde</Italian> </Key> <Key ID="STR_ACE_Interaction_AssignTeamBlue"> <English>Assign Blue</English> @@ -599,7 +599,7 @@ <Czech>Přiřadit k modrým</Czech> <Russian>Назначить в Синюю группу</Russian> <French>Assigner à bleu</French> - <Italian>Assegna al team blu</Italian> + <Italian>Assegna al team blu</Italian> </Key> <Key ID="STR_ACE_Interaction_AssignTeamYellow"> <English>Assign Yellow</English> @@ -611,7 +611,7 @@ <Czech>Přiřadit ke žlutým</Czech> <Russian>Назначить в Желтую группу</Russian> <French>Assigner à jaune</French> - <Italian>Assegna al team giallo</Italian> + <Italian>Assegna al team giallo</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamRed"> <English>Join Red</English> @@ -623,7 +623,7 @@ <Czech>Připojit k červeným</Czech> <Russian>Присоединиться к Красной группе</Russian> <French>Rejoindre rouge</French> - <Italian>Unirsi al team rosso</Italian> + <Italian>Unirsi al team rosso</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamGreen"> <English>Join Green</English> @@ -635,7 +635,7 @@ <Czech> Připojit k zeleným</Czech> <Russian>Присоединиться к Зеленой группе</Russian> <French>Rejoindre vert</French> - <Italian>Unirsi al team verde</Italian> + <Italian>Unirsi al team verde</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamBlue"> <English>Join Blue</English> @@ -647,7 +647,7 @@ <Czech>Připojit k modrým</Czech> <Russian>Присоединиться к Синей группе</Russian> <French>Rejoindre bleu</French> - <Italian>Unirsi al team blu</Italian> + <Italian>Unirsi al team blu</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinTeamYellow"> <English>Join Yellow</English> @@ -659,7 +659,7 @@ <Czech>Připojit ke žlutým</Czech> <Russian>Присоединиться к Жёлтой группе</Russian> <French>Rejoindre jaune</French> - <Italian>Unirsi al team giallo</Italian> + <Italian>Unirsi al team giallo</Italian> </Key> <Key ID="STR_ACE_Interaction_JoinedTeam"> <English>You joined Team %1</English> @@ -767,7 +767,7 @@ <Hungarian>Tolás</Hungarian> <Russian>Толкать</Russian> <Portuguese>Empurrar</Portuguese> - <Italian>Spingere</Italian> + <Italian>Spingere</Italian> </Key> <Key ID="STR_ACE_Interaction_Interact"> <English>Interact</English> diff --git a/addons/nametags/stringtable.xml b/addons/nametags/stringtable.xml index 070257e807..1a0a2f1369 100644 --- a/addons/nametags/stringtable.xml +++ b/addons/nametags/stringtable.xml @@ -70,8 +70,8 @@ <Czech>Zobrazit info o posádce vozidla</Czech> <Russian>Показывать информацию об экипаже</Russian> <Hungarian>Jármű-legénység adatainak mutatása</Hungarian> - <Italian>Mostra le informazioni sull'equipaggio del veicolo</Italian> <Portuguese>Mostrar tripulantes</Portuguese> + <Italian>Mostra l'elenco del personale a bordo</Italian> </Key> <Key ID="STR_ACE_NameTags_ShowNamesForAI"> <English>Show name tags for AI units</English> @@ -82,7 +82,7 @@ <Polish>Wyświetl imiona jednostek AI</Polish> <French>Afficher les noms des IA</French> <Hungarian>Névcímkék mutatása MI-egységeknél</Hungarian> - <Italian>Mostra le tag nomi per le unità AI</Italian> + <Italian>Mostra i nomi delle le unità AI</Italian> <Portuguese>Mostrar nomes para unidades de IA</Portuguese> </Key> <Key ID="STR_ACE_NameTags_ShowSoundWaves"> @@ -94,7 +94,7 @@ <Polish>Pokaż fale dźwiękowe (wymagana opcja Pokaż imiona graczy)</Polish> <French>Afficher "qui parle" (si noms affichés)</French> <Hungarian>"Hanghullámok" mutatása (a nevek mutatása szükséges)</Hungarian> - <Italian>Mostra barra movimento audio (richiede mostra nomi abilitato)</Italian> + <Italian>Mostra movimento audio (richiede mostra nomi abilitato)</Italian> <Portuguese>Mostrar onda sonora (requer nome de jogadores)</Portuguese> </Key> <Key ID="STR_ACE_NameTags_DefaultNametagColor"> @@ -106,7 +106,7 @@ <French>Couleur d'affichage par défaut (si dans aucun groupe)</French> <Czech>Standardní barva jmenovek (pro nečleny jednotky)</Czech> <Hungarian>Alap névcímke-szín (csoporton kívüli személyek)</Hungarian> - <Italian>Colore nametag di default (membri non del gruppo)</Italian> + <Italian>Colore dei nomi non appartenenti al gruppo</Italian> <Portuguese>Cor padrão do nome (unidades fora do grupo)</Portuguese> </Key> <Key ID="STR_ACE_NameTags_Module_DisplayName"> diff --git a/addons/optionsmenu/stringtable.xml b/addons/optionsmenu/stringtable.xml index aa78e83645..18ee57310a 100644 --- a/addons/optionsmenu/stringtable.xml +++ b/addons/optionsmenu/stringtable.xml @@ -239,7 +239,7 @@ <German>UI Skalierung</German> <Hungarian>Beállításmenü kezelőfelületének skálázása</Hungarian> <Portuguese>Escalar o menu de opções</Portuguese> - <Italian>Proporzioni della interfaccia utente</Italian> + <Italian>Proporzioni della interfaccia utente</Italian> </Key> <Key ID="STR_AllowConfigExport_Module_DisplayName"> <English>Allow Config Export [ACE]</English> @@ -257,31 +257,31 @@ <English>When allowed, you have access to the settings modification and export in SP. Clicking export will place the formated config on your clipboard.</English> <Polish>Jeżeli ustawione na zezwól, wtedy będziesz mieć dostęp do ekranu modyfikacji wszystich ustawień i zmiennych ACE, a także będziesz mieć możliwość eksportu tychże ustawień do formatu rozpoznawalnego przez userconfig serwera. Kliknięcie opcji Eksportuj skopiuje wszystkie ustawienia do schowka. Działa tylko w trybie SP.</Polish> </Key> - <Key ID="STR_ACE_Common_Hide"> + <Key ID="STR_ACE_Common_Hide"> <English>Hide</English> <Polish>Ukryj</Polish> </Key> - <Key ID="STR_ACE_Common_TopRightDown"> + <Key ID="STR_ACE_Common_TopRightDown"> <English>Top right, downwards</English> <Polish>Po prawej u góry, w dół</Polish> </Key> - <Key ID="STR_ACE_Common_TopRightLeft"> + <Key ID="STR_ACE_Common_TopRightLeft"> <English>Top right, to the left</English> <Polish>Po prawej u góry, do lewej</Polish> </Key> - <Key ID="STR_ACE_Common_TopLeftDown"> + <Key ID="STR_ACE_Common_TopLeftDown"> <English>Top left, downwards</English> <Polish>Po lewej u góry, w dół</Polish> </Key> - <Key ID="STR_ACE_Common_TopLeftRight"> + <Key ID="STR_ACE_Common_TopLeftRight"> <English>Top left, to the right</English> <Polish>Po lewej u góry, do prawej</Polish> </Key> - <Key ID="STR_ACE_Common_Top"> + <Key ID="STR_ACE_Common_Top"> <English>Top</English> <Polish>Góra</Polish> </Key> - <Key ID="STR_ACE_Common_Bottom"> + <Key ID="STR_ACE_Common_Bottom"> <English>Bottom</English> <Polish>Dół</Polish> </Key> diff --git a/addons/respawn/stringtable.xml b/addons/respawn/stringtable.xml index 5351d0f3bc..d7d5b7ac98 100644 --- a/addons/respawn/stringtable.xml +++ b/addons/respawn/stringtable.xml @@ -35,6 +35,7 @@ <French>Téléportation à la base</French> <Portuguese>Teletransportar para a Base</Portuguese> <Hungarian>Bázisra teleportálás</Hungarian> + <Italian>Teleporta alla base</Italian> </Key> <Key ID="STR_ACE_Respawn_TeleportToRallypoint"> <English>Teleport to Rallypoint</English> @@ -46,6 +47,7 @@ <French>Téléporation au point de ralliement</French> <Portuguese>Teletransportar para o ponto de encontro</Portuguese> <Hungarian>Gyülekezőpontra teleportálás</Hungarian> + <Italian>Teleporta al rallypoint</Italian> </Key> <Key ID="STR_ACE_Respawn_TeleportedToBase"> <English>Teleported to Base</English> From 1610221a70d516b536602f0a114282458f2eb662 Mon Sep 17 00:00:00 2001 From: GieNkoV <gienkov.grzegorz@gmail.com> Date: Tue, 12 May 2015 20:01:10 +0200 Subject: [PATCH 32/51] Remove duplicated strings --- addons/captives/stringtable.xml | 8 - addons/medical/stringtable.xml | 372 ----------------------------- addons/mk6mortar/stringtable.xml | 32 --- addons/optionsmenu/stringtable.xml | 44 ---- 4 files changed, 456 deletions(-) diff --git a/addons/captives/stringtable.xml b/addons/captives/stringtable.xml index 0d01cbafc6..07cf780e19 100644 --- a/addons/captives/stringtable.xml +++ b/addons/captives/stringtable.xml @@ -201,13 +201,5 @@ <English>Sync a unit to make them surrender.<br />Source: ace_captives</English> <Polish>Zsynchronizuj z jednostką aby sprawić by się poddała<br />Źródło: ace_captives</Polish> </Key> - <Key ID="STR_ACE_Captives_ModuleSurrender_DisplayName"> - <English>Make Unit Surrender</English> - <Polish>Poddaj się!</Polish> - </Key> - <Key ID="STR_ACE_Captives_ModuleSurrender_Description"> - <English>Sync a unit to make them surrender.<br />Source: ace_captives</English> - <Polish>Zsynchronizuj z jednostką aby sprawić by się poddała<br />Źródło: ace_captives</Polish> - </Key> </Package> </Project> diff --git a/addons/medical/stringtable.xml b/addons/medical/stringtable.xml index 9cfc7e15d5..a5ffc6a4ba 100644 --- a/addons/medical/stringtable.xml +++ b/addons/medical/stringtable.xml @@ -3065,378 +3065,6 @@ <English>[ACE] Medical Supply Crate (Advanced)</English> <Polish>[ACE] Skrzynka z zapasami medycznymi (zaawansowana)</Polish> </Key> - <Key ID="STR_ACE_Medical_Category_DisplayName"> - <English>ACE Medical</English> - <Polish>ACE Opcje medyczne</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_Module_DisplayName"> - <English>Medical Settings [ACE]</English> - <Polish>Ustawienia medyczne [ACE]</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_level_DisplayName"> - <English>Medical Level</English> - <Polish>Poziom medyczny</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_level_Description"> - <English>What is the medical simulation level?</English> - <Polish>Jaki jest poziom symulacji medycznej?</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_basic"> - <English>Basic</English> - <Polish>Podstawowy</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_advanced"> - <English>Advanced</English> - <Polish>Zaawansowany</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_medicSetting_DisplayName"> - <English>Medics setting</English> - <Polish>Poziom medyków</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_medicSetting_Description"> - <English>What is the level of detail prefered for medics?</English> - <Polish>Jaki jest poziom detali medycznych wyświetlanych dla medyków?</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_medicSetting_disable"> - <English>Disable medics</English> - <Polish>Wyłącz medyków</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_allowLitterCreation_DisplayName"> - <English>Enable Litter</English> - <Polish>Aktywuj odpadki</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_allowLitterCreation_Description"> - <English>Enable litter being created upon treatment</English> - <Polish>Twórz odpadki medyczne podczas leczenia</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_litterCleanUpDelay_DisplayName"> - <English>Life time of litter objects</English> - <Polish>Długość życia odpadków</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_litterCleanUpDelay_Description"> - <English>How long should litter objects stay? In seconds. -1 is forever.</English> - <Polish>Ile czasu musi upłynąć, aby odpadki zaczęły znikać? W sekundach. -1 dla nieskończoności.</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_enableScreams_DisplayName"> - <English>Enable Screams</English> - <Polish>Aktywuj wrzaski</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_enableScreams_Description"> - <English>Enable screaming by injuried units</English> - <Polish>Aktywuj wrzeszczenie z bólu przez ranne jednostki</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_playerDamageThreshold_DisplayName"> - <English>Player Damage</English> - <Polish>Próg obrażeń graczy</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_playerDamageThreshold_Description"> - <English>What is the damage a player can take before being killed?</English> - <Polish>Jaki jest próg obrażeń, jakie gracz może otrzymać zanim zostanie zabity?</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_AIDamageThreshold_DisplayName"> - <English>AI Damage</English> - <Polish>Próg obrażeń AI</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_AIDamageThreshold_Description"> - <English>What is the damage an AI can take before being killed?</English> - <Polish>Jaki jest próg obrażeń, jakie AI może otrzymać zanim zostanie zabite?</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_enableUnconsciousnessAI_DisplayName"> - <English>AI Unconsciousness</English> - <Polish>Nieprzytomność AI</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_enableUnconsciousnessAI_Description"> - <English>Allow AI to go unconscious</English> - <Polish>Czy AI może być nieprzytomne od odniesionych obrażeń?</Polish> - </Key> - <Key ID="STR_ACE_Medical_disabled"> - <English>Disabled</English> - <Polish>Wyłączone</Polish> - </Key> - <Key ID="STR_ACE_Medical_enabled"> - <English>Enabled</English> - <Polish>Włączone</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_preventInstaDeath_DisplayName"> - <English>Prevent instant death</English> - <Polish>Wył. natychmiast. śmierć</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_preventInstaDeath_Description"> - <English>Have a unit move to unconscious instead of death</English> - <Polish>Spraw, aby jednostka została przeniesiona do stanu nieprzytomności zamiast ginąć na miejscu od śmiertelnych obrażeń</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_bleedingCoefficient_DisplayName"> - <English>Bleeding coefficient</English> - <Polish>Mnożnik krwawienia</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_bleedingCoefficient_Description"> - <English>Coefficient to modify the bleeding speed</English> - <Polish>Mnożnik modyfikujący prędkość wykrwawiania się</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_painCoefficient_DisplayName"> - <English>Pain coefficient</English> - <Polish>Mnożnik bólu</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_painCoefficient_Description"> - <English>Coefficient to modify the pain intensity</English> - <Polish>Mnożnik modyfikujący intensywność bólu</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_keepLocalSettingsSynced_DisplayName"> - <English>Sync status</English> - <Polish>Synchronizuj status</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_keepLocalSettingsSynced_Description"> - <English>Keep unit status synced. Recommended on.</English> - <Polish>Utrzymuj synchronizację statusu jednostek. Zalecane zostawienie tej opcji włączonej.</Polish> - </Key> - <Key ID="STR_ACE_MedicalSettings_Module_Description"> - <English>Provides a medical system for both players and AI.</English> - <Polish>Moduł ten dostarcza system medyczny dla graczy oraz AI.</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_Module_DisplayName"> - <English>Advanced Medical Settings [ACE]</English> - <Polish>Zaawansowane ustawienia medyczne [ACE]</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_enableFor_DisplayName"> - <English>Enabled for</English> - <Polish>Aktywne dla</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_enableFor_Description"> - <English>Select what units the advanced medical system will be enabled for</English> - <Polish>Wybierz dla kogo zaawansowany system medyczny będzie aktywny</Polish> - </Key> - <Key ID="STR_ACE_Medical_playeronly"> - <English>Players only</English> - <Polish>Tylko dla graczy</Polish> - </Key> - <Key ID="STR_ACE_Medical_playersandai"> - <English>Players and AI</English> - <Polish>Gracze oraz AI</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_enableAdvancedWounds_DisplayName"> - <English>Enable Advanced wounds</English> - <Polish>Akt. zaawansowane rany</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_enableAdvancedWounds_Description"> - <English>Allow reopening of bandaged wounds?</English> - <Polish>Pozwól na otwieranie się zabandażowanych ran?</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_enableVehicleCrashes_DisplayName"> - <English>Vehicle Crashes</English> - <Polish>Obrażenia od kolizji</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_enableVehicleCrashes_Description"> - <English>Do units take damage from a vehicle crash?</English> - <Polish>Czy jednostki otrzymują obrażenia w wyniku kolizji pojazdów?</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_PAK_DisplayName"> - <English>Allow PAK</English> - <Polish>Ust. apteczek osobistych</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_PAK_Description"> - <English>Who can use the PAK for full heal?</English> - <Polish>Kto może skorzystać z apteczki osobistej w celu pełnego uleczenia?</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_anyone"> - <English>Anyone</English> - <Polish>Wszyscy</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_Medic"> - <English>Medics only</English> - <Polish>Tylko medycy</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_Special"> - <English>Doctors only</English> - <Polish>Tylko doktorzy</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_DisplayName"> - <English>Remove PAK on use</English> - <Polish>Usuń apteczkę po użyciu</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_PAK_Description"> - <English>Should PAK be removed on usage?</English> - <Polish>Czy apteczka osobista powinna zniknąć z ekwipunku po jej użyciu?</Polish> - </Key> - <Key ID="STR_ACE_Medical_No"> - <English>No</English> - <Polish>Nie</Polish> - </Key> - <Key ID="STR_ACE_Medical_Yes"> - <English>Yes</English> - <Polish>Tak</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_PAK_DisplayName"> - <English>Locations PAK</English> - <Polish>Ogr. apteczek osobistych</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_PAK_Description"> - <English>Where can the personal aid kit be used?</English> - <Polish>Gdzie można korzystać z apteczek osobistych?</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_anywhere"> - <English>Anywhere</English> - <Polish>Wszędzie</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_vehicle"> - <English>Medical vehicles</English> - <Polish>Pojazdy medyczne</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_facility"> - <English>Medical facility</English> - <Polish>Budynki medyczne</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_vehicleAndFacility"> - <English>Vehicles & facility</English> - <Polish>Pojazdy i budynki medyczne</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_disabled"> - <English>Disabled</English> - <Polish>Wyłączone</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_SurgicalKit_DisplayName"> - <English>Allow Surgical kit (Adv)</English> - <Polish>Ust. zestawu chirurg.</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_medicSetting_SurgicalKit_Description"> - <English>Who can use the surgical kit?</English> - <Polish>Kto może skorzystać z zestawu chirurgicznego w celu zszycia ran?</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_SurgicalKit_DisplayName"> - <English>Remove Surgical kit (Adv)</English> - <Polish>Usuń zest. chir. po użyciu</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_consumeItem_SurgicalKit_Description"> - <English>Should Surgical kit be removed on usage?</English> - <Polish>Czy zestaw chirurgiczny powinien zniknąć z ekwipunku po jego użyciu?</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_SurgicalKit_DisplayName"> - <English>Locations Surgical kit (Adv)</English> - <Polish>Ogr. zestawu chirurg.</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_useLocation_SurgicalKit_Description"> - <English>Where can the Surgical kit be used?</English> - <Polish>Gdzie można korzystać z zestawu chirurgicznego?</Polish> - </Key> - <Key ID="STR_ACE_AdvancedMedicalSettings_Module_Description"> - <English>Configure the treatment settings from ACE Medical</English> - <Polish>Skonfiguruj zaawansowane ustawienia leczenia systemu medycznego ACE</Polish> - </Key> - <Key ID="STR_ACE_ReviveSettings_Module_DisplayName"> - <English>Revive Settings [ACE]</English> - <Polish>Ustawienia wskrzeszania [ACE]</Polish> - </Key> - <Key ID="STR_ACE_ReviveSettings_enableRevive_DisplayName"> - <English>Enable Revive</English> - <Polish>Aktywuj wskrzeszanie</Polish> - </Key> - <Key ID="STR_ACE_ReviveSettings_enableRevive_Description"> - <English>Enable a basic revive system</English> - <Polish>Aktywuj podstawowy system wskrzeszania</Polish> - </Key> - <Key ID="STR_ACE_ReviveSettings_maxReviveTime_DisplayName"> - <English>Max Revive time</English> - <Polish>Maks. czas agonii</Polish> - </Key> - <Key ID="STR_ACE_ReviveSettings_maxReviveTime_Description"> - <English>Max amount of seconds a unit can spend in revive state</English> - <Polish>Maksymalna długość agonii w sekundach (czas na wskrzeszenie)</Polish> - </Key> - <Key ID="STR_ACE_ReviveSettings_amountOfReviveLives_DisplayName"> - <English>Max Revive lives</English> - <Polish>Maks. ilość wskrzeszeń</Polish> - </Key> - <Key ID="STR_ACE_ReviveSettings_amountOfReviveLives_Description"> - <English>Max amount of lives a unit. 0 or -1 is disabled.</English> - <Polish>Maksymalna ilość wskrzeszeń. Wpisz 0 lub -1 aby wyłączyć.</Polish> - </Key> - <Key ID="STR_ACE_ReviveSettings_Module_Description"> - <English>Provides a medical system for both players and AI.</English> - <Polish>Moduł ten aktywuje podstawowy system wskrzeszania. Jednostka po otrzymaniu śmiertelnych obrażeń przechodzi do stanu agonii, która trwa określoną długość czasu. W tym czasie aby wskrzesić i jednocześnie odratować jednostkę należy opatrzeć jej rany i wykonać RKO.</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicRoles_Module_DisplayName"> - <English>Set Medic Class [ACE]</English> - <Polish>Ustaw klasę medyka [ACE]</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicRoles_EnableList_DisplayName"> - <English>List</English> - <Polish>Lista</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicRoles_EnableList_Description"> - <English>List of unit names that will be classified as medic, separated by commas.</English> - <Polish>Lista nazw jednostek, które są sklasyfikowane jako medycy, oddzielone przecinkami.</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicRoles_role_DisplayName"> - <English>Is Medic</English> - <Polish>Klasa medyczna</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicRoles_role_Description"> - <English></English> - <Polish></Polish> - </Key> - <Key ID="STR_ACE_AssignMedicRoles_role_none"> - <English>None</English> - <Polish>Żadna</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicRoles_role_medic"> - <English>Regular medic</English> - <Polish>Zwykły medyk</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicRoles_role_doctor"> - <English>Doctor (Only Advanced Medics)</English> - <Polish>Doktor (tylko zaawansowani medycy)</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicRoles_Module_Description"> - <English>Assigns the ACE medic class to a unit</English> - <Polish>Moduł ten przypisuje klasę medyka ACE do jednostek.</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicVehicle_Module_DisplayName"> - <English>Set Medical Vehicle [ACE]</English> - <Polish>Ustaw pojazd medyczny [ACE]</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicVehicle_EnableList_DisplayName"> - <English>List</English> - <Polish>Lista</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicVehicle_EnableList_Description"> - <English>List of vehicles that will be classified as medical vehicle, separated by commas.</English> - <Polish>Lista nazw pojazdów, które są sklasyfikowane jako pojazdy medyczne, oddzielone przecinkami.</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicVehicle_enabled_DisplayName"> - <English>Is Medical Vehicle</English> - <Polish>Jest pojazdem med.</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicVehicle_enabled_Description"> - <English>Whatever or not the objects in the list will be a medical vehicle.</English> - <Polish>Czy pojazdy z tej listy są pojazdami medycznymi.</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicVehicle_Module_Description"> - <English>Assigns the ACE medic class to a unit</English> - <Polish>Moduł ten pozwala na przypisanie danym pojazdom statusu pojazdów medycznych. Wewnątrz takiego pojazdu można wykonywać zaawansowane zabiegi medyczne.</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicalFacility_Module_DisplayName"> - <English>Set Medical Facility [ACE]</English> - <Polish>Ustaw budynek medyczny [ACE]</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicalFacility_enabled_DisplayName"> - <English>Is Medical Facility</English> - <Polish>Jest budynkiem med.</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicalFacility_enabled_Description"> - <English>Registers an object as a medical facility</English> - <Polish>Przypisuje danemu obiektowi status budynku medycznego</Polish> - </Key> - <Key ID="STR_ACE_AssignMedicalFacility_Module_Description"> - <English>Defines an object as a medical facility. This allows for more advanced treatments. Can be used on buildings and vehicles.</English> - <Polish>Moduł ten pozwala przypisać status budynku medycznego danemu obiektowi. Budynek taki pozwala na wykonywanie zaawansowanych zabiegów medycznych. Może być użyte na pojazdach i budynkach.</Polish> - </Key> - <Key ID="STR_ACE_medicalSupplyCrate"> - <English>[ACE] Medical Supply Crate (Basic)</English> - <Polish>[ACE] Skrzynka z zapasami medycznymi (podstawowa)</Polish> - </Key> - <Key ID="STR_ACE_medicalSupplyCrate_advanced"> - <English>[ACE] Medical Supply Crate (Advanced)</English> - <Polish>[ACE] Skrzynka z zapasami medycznymi (zaawansowana)</Polish> - </Key> </Package> </Project> diff --git a/addons/mk6mortar/stringtable.xml b/addons/mk6mortar/stringtable.xml index cb4a7c5376..37c7d322ad 100644 --- a/addons/mk6mortar/stringtable.xml +++ b/addons/mk6mortar/stringtable.xml @@ -81,37 +81,5 @@ <English></English> <Polish>Moduł ten pozwala dostosować ustawienia moździerza MK6.</Polish> </Key> - <Key ID="STR_ACE_mk6mortar_Module_DisplayName"> - <English>MK6 Settings</English> - <Polish>Moździerz MK6 - Ustawienia</Polish> - </Key> - <Key ID="STR_ACE_mk6mortar_airResistanceEnabled_DisplayName"> - <English>Air Resistance</English> - <Polish>Opór powietrza</Polish> - </Key> - <Key ID="STR_ACE_mk6mortar_airResistanceEnabled_Description"> - <English>For Player Shots, Model Air Resistance and Wind Effects</English> - <Polish>Modeluj opór powietrza oraz wpływ wiatru na tor lotu pocisku dla strzałów z moździerza MK6 przez graczy</Polish> - </Key> - <Key ID="STR_ACE_mk6mortar_allowComputerRangefinder_DisplayName"> - <English>Allow MK6 Computer</English> - <Polish>Komputer MK6</Polish> - </Key> - <Key ID="STR_ACE_mk6mortar_allowComputerRangefinder_Description"> - <English>Show the Computer and Rangefinder (these NEED to be removed if you enable air resistance)</English> - <Polish>Zezwól na komputer i dalmierz (opcja ta MUSI zostać wyłączona jeżeli aktywowałeś opór powietrza)</Polish> - </Key> - <Key ID="STR_ACE_mk6mortar_allowCompass_DisplayName"> - <English>Allow MK6 Compass</English> - <Polish>Kompas MK6</Polish> - </Key> - <Key ID="STR_ACE_mk6mortar_allowCompass_Description"> - <English>Show the MK6 Digital Compass</English> - <Polish>Pokaż kompas MK6</Polish> - </Key> - <Key ID="STR_ACE_mk6mortar_Module_Description"> - <English></English> - <Polish>Moduł ten pozwala dostosować ustawienia moździerza MK6.</Polish> - </Key> </Package> </Project> diff --git a/addons/optionsmenu/stringtable.xml b/addons/optionsmenu/stringtable.xml index 18ee57310a..22a1a88cfa 100644 --- a/addons/optionsmenu/stringtable.xml +++ b/addons/optionsmenu/stringtable.xml @@ -285,49 +285,5 @@ <English>Bottom</English> <Polish>Dół</Polish> </Key> - <Key ID="STR_AllowConfigExport_Module_DisplayName"> - <English>Allow Config Export [ACE]</English> - <Polish>Pozwól na eksport ustawień [ACE]</Polish> - </Key> - <Key ID="STR_AllowConfigExport_allowconfigurationExport_DisplayName"> - <English>Allow</English> - <Polish>Zezwól</Polish> - </Key> - <Key ID="STR_AllowConfigExport_allowconfigurationExport_Description"> - <English>Allow export of all settings to a server config formatted.</English> - <Polish>Zezwól na eksport wszystkich ustawień do formatu konfiguracji serwera.</Polish> - </Key> - <Key ID="STR_AllowConfigExport_Module_Description"> - <English>When allowed, you have access to the settings modification and export in SP. Clicking export will place the formated config on your clipboard.</English> - <Polish>Jeżeli ustawione na zezwól, wtedy będziesz mieć dostęp do ekranu modyfikacji wszystich ustawień i zmiennych ACE, a także będziesz mieć możliwość eksportu tychże ustawień do formatu rozpoznawalnego przez userconfig serwera. Kliknięcie opcji Eksportuj skopiuje wszystkie ustawienia do schowka. Działa tylko w trybie SP.</Polish> - </Key> - <Key ID="STR_ACE_Common_Hide"> - <English>Hide</English> - <Polish>Ukryj</Polish> - </Key> - <Key ID="STR_ACE_Common_TopRightDown"> - <English>Top right, downwards</English> - <Polish>Po prawej u góry, w dół</Polish> - </Key> - <Key ID="STR_ACE_Common_TopRightLeft"> - <English>Top right, to the left</English> - <Polish>Po prawej u góry, do lewej</Polish> - </Key> - <Key ID="STR_ACE_Common_TopLeftDown"> - <English>Top left, downwards</English> - <Polish>Po lewej u góry, w dół</Polish> - </Key> - <Key ID="STR_ACE_Common_TopLeftRight"> - <English>Top left, to the right</English> - <Polish>Po lewej u góry, do prawej</Polish> - </Key> - <Key ID="STR_ACE_Common_Top"> - <English>Top</English> - <Polish>Góra</Polish> - </Key> - <Key ID="STR_ACE_Common_Bottom"> - <English>Bottom</English> - <Polish>Dół</Polish> - </Key> </Package> </Project> From 2620f5ebd92aba72b6fdd9f4938e82a9c600b5bf Mon Sep 17 00:00:00 2001 From: SilentSpike <silentspike100+Github@gmail.com> Date: Tue, 12 May 2015 19:55:38 +0100 Subject: [PATCH 33/51] Made module also default to disabled --- addons/zeus/CfgVehicles.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/zeus/CfgVehicles.hpp b/addons/zeus/CfgVehicles.hpp index a1f71f405a..5750ab52d6 100644 --- a/addons/zeus/CfgVehicles.hpp +++ b/addons/zeus/CfgVehicles.hpp @@ -18,25 +18,25 @@ class CfgVehicles { displayName = "Ascension Messages"; description = "Display global popup messages when a player is assigned as Zeus."; typeName = "BOOL"; - defaultValue = 1; + defaultValue = 0; }; class zeusBird { displayName = "Zeus Eagle"; description = "Spawn an eagle that follows the Zeus camera."; typeName = "BOOL"; - defaultValue = 1; + defaultValue = 0; }; class remoteWind { displayName = "Wind Sounds"; description = "Play wind sounds when Zeus remote controls a unit."; typeName = "BOOL"; - defaultValue = 1; + defaultValue = 0; }; class radioOrdnance { - displayName = "Ordnance Radio Warning"; + displayName = "Ordnance Warning"; description = "Play a radio warning when Zeus uses ordnance."; typeName = "BOOL"; - defaultValue = 1; + defaultValue = 0; }; class revealMines { displayName = "Reveal Mines"; @@ -46,6 +46,7 @@ class CfgVehicles { class disable { name = "Disabled"; value = 0; + default = 1; }; class partial { name = "Reveal to Allies"; @@ -54,7 +55,6 @@ class CfgVehicles { class full { name = "Allies + Map Markers"; value = 2; - default = 1; }; }; }; From 3ff9ea230a9556e5721fe860bce681e0308ce9fa Mon Sep 17 00:00:00 2001 From: jaynus <jaynus@gmail.com> Date: Wed, 13 May 2015 08:34:14 -0700 Subject: [PATCH 34/51] initial pick from vehicledamage for new extension build process. --- extensions/CMakeLists.txt | 84 +- .../AdvancedBallistics.cpp | 34 +- extensions/advanced_ballistics/CMakeLists.txt | 7 +- extensions/break_line/CMakeLists.txt | 7 +- extensions/break_line/ace_break_line.cpp | 4 +- extensions/clipboard/ace_clipboard.cpp | 17 +- extensions/cmake/FindDirectX.cmake | 215 + extensions/common/CMakeLists.txt | 18 + extensions/common/arguments.hpp | 90 + extensions/common/directx/d3d_display.cpp | 439 ++ extensions/common/directx/d3d_display.hpp | 130 + extensions/common/dispatch.hpp | 153 + extensions/common/easyloggingc++.hpp | 6718 +++++++++++++++++ extensions/common/glm/CMakeLists.txt | 43 + extensions/common/glm/common.hpp | 35 + extensions/common/glm/detail/_features.hpp | 428 ++ extensions/common/glm/detail/_fixes.hpp | 59 + extensions/common/glm/detail/_noise.hpp | 136 + extensions/common/glm/detail/_swizzle.hpp | 833 ++ .../common/glm/detail/_swizzle_func.hpp | 725 ++ extensions/common/glm/detail/_vectorize.hpp | 160 + extensions/common/glm/detail/dummy.cpp | 232 + extensions/common/glm/detail/func_common.hpp | 456 ++ extensions/common/glm/detail/func_common.inl | 758 ++ .../common/glm/detail/func_exponential.hpp | 132 + .../common/glm/detail/func_exponential.inl | 161 + .../common/glm/detail/func_geometric.hpp | 142 + .../common/glm/detail/func_geometric.inl | 201 + extensions/common/glm/detail/func_integer.hpp | 232 + extensions/common/glm/detail/func_integer.inl | 393 + extensions/common/glm/detail/func_matrix.hpp | 178 + extensions/common/glm/detail/func_matrix.inl | 310 + extensions/common/glm/detail/func_noise.hpp | 93 + extensions/common/glm/detail/func_noise.inl | 388 + extensions/common/glm/detail/func_packing.hpp | 197 + extensions/common/glm/detail/func_packing.inl | 119 + .../common/glm/detail/func_trigonometric.hpp | 205 + .../common/glm/detail/func_trigonometric.inl | 224 + .../glm/detail/func_vector_relational.hpp | 140 + .../glm/detail/func_vector_relational.inl | 131 + extensions/common/glm/detail/glm.cpp | 286 + .../common/glm/detail/intrinsic_common.hpp | 87 + .../common/glm/detail/intrinsic_common.inl | 313 + .../glm/detail/intrinsic_exponential.hpp | 77 + .../glm/detail/intrinsic_exponential.inl | 27 + .../common/glm/detail/intrinsic_geometric.hpp | 74 + .../common/glm/detail/intrinsic_geometric.inl | 147 + .../common/glm/detail/intrinsic_integer.hpp | 48 + .../common/glm/detail/intrinsic_integer.inl | 139 + .../common/glm/detail/intrinsic_matrix.hpp | 67 + .../common/glm/detail/intrinsic_matrix.inl | 1070 +++ .../glm/detail/intrinsic_trigonometric.hpp | 46 + .../glm/detail/intrinsic_trigonometric.inl | 27 + .../detail/intrinsic_vector_relational.hpp | 46 + .../detail/intrinsic_vector_relational.inl | 366 + extensions/common/glm/detail/precision.hpp | 44 + extensions/common/glm/detail/setup.hpp | 962 +++ extensions/common/glm/detail/type_float.hpp | 96 + extensions/common/glm/detail/type_gentype.hpp | 224 + extensions/common/glm/detail/type_gentype.inl | 370 + extensions/common/glm/detail/type_half.hpp | 48 + extensions/common/glm/detail/type_half.inl | 277 + extensions/common/glm/detail/type_int.hpp | 326 + extensions/common/glm/detail/type_mat.hpp | 793 ++ extensions/common/glm/detail/type_mat.inl | 32 + extensions/common/glm/detail/type_mat2x2.hpp | 223 + extensions/common/glm/detail/type_mat2x2.inl | 548 ++ extensions/common/glm/detail/type_mat2x3.hpp | 201 + extensions/common/glm/detail/type_mat2x3.inl | 506 ++ extensions/common/glm/detail/type_mat2x4.hpp | 202 + extensions/common/glm/detail/type_mat2x4.inl | 515 ++ extensions/common/glm/detail/type_mat3x2.hpp | 207 + extensions/common/glm/detail/type_mat3x2.inl | 540 ++ extensions/common/glm/detail/type_mat3x3.hpp | 230 + extensions/common/glm/detail/type_mat3x3.inl | 631 ++ extensions/common/glm/detail/type_mat3x4.hpp | 206 + extensions/common/glm/detail/type_mat3x4.inl | 579 ++ extensions/common/glm/detail/type_mat4x2.hpp | 212 + extensions/common/glm/detail/type_mat4x2.inl | 587 ++ extensions/common/glm/detail/type_mat4x3.hpp | 211 + extensions/common/glm/detail/type_mat4x3.inl | 631 ++ extensions/common/glm/detail/type_mat4x4.hpp | 235 + extensions/common/glm/detail/type_mat4x4.inl | 790 ++ extensions/common/glm/detail/type_vec.hpp | 518 ++ extensions/common/glm/detail/type_vec.inl | 31 + extensions/common/glm/detail/type_vec1.hpp | 322 + extensions/common/glm/detail/type_vec1.inl | 616 ++ extensions/common/glm/detail/type_vec2.hpp | 403 + extensions/common/glm/detail/type_vec2.inl | 909 +++ extensions/common/glm/detail/type_vec3.hpp | 425 ++ extensions/common/glm/detail/type_vec3.inl | 1042 +++ extensions/common/glm/detail/type_vec4.hpp | 531 ++ extensions/common/glm/detail/type_vec4.inl | 1124 +++ .../common/glm/detail/type_vec4_avx.inl | 41 + .../common/glm/detail/type_vec4_avx2.inl | 41 + .../common/glm/detail/type_vec4_sse2.inl | 120 + extensions/common/glm/exponential.hpp | 35 + extensions/common/glm/ext.hpp | 143 + extensions/common/glm/fwd.hpp | 2601 +++++++ extensions/common/glm/geometric.hpp | 35 + extensions/common/glm/glm.hpp | 117 + extensions/common/glm/gtc/bitfield.hpp | 236 + extensions/common/glm/gtc/bitfield.inl | 542 ++ extensions/common/glm/gtc/constants.hpp | 205 + extensions/common/glm/gtc/constants.inl | 210 + extensions/common/glm/gtc/epsilon.hpp | 102 + extensions/common/glm/gtc/epsilon.inl | 154 + extensions/common/glm/gtc/integer.hpp | 105 + extensions/common/glm/gtc/integer.inl | 74 + extensions/common/glm/gtc/matrix_access.hpp | 88 + extensions/common/glm/gtc/matrix_access.inl | 92 + extensions/common/glm/gtc/matrix_integer.hpp | 515 ++ extensions/common/glm/gtc/matrix_inverse.hpp | 78 + extensions/common/glm/gtc/matrix_inverse.inl | 148 + .../common/glm/gtc/matrix_transform.hpp | 304 + .../common/glm/gtc/matrix_transform.inl | 413 + extensions/common/glm/gtc/noise.hpp | 89 + extensions/common/glm/gtc/noise.inl | 837 ++ extensions/common/glm/gtc/packing.hpp | 478 ++ extensions/common/glm/gtc/packing.inl | 490 ++ extensions/common/glm/gtc/quaternion.hpp | 377 + extensions/common/glm/gtc/quaternion.inl | 784 ++ extensions/common/glm/gtc/random.hpp | 120 + extensions/common/glm/gtc/random.inl | 379 + extensions/common/glm/gtc/reciprocal.hpp | 134 + extensions/common/glm/gtc/reciprocal.inl | 221 + extensions/common/glm/gtc/round.hpp | 203 + extensions/common/glm/gtc/round.inl | 378 + extensions/common/glm/gtc/type_precision.hpp | 890 +++ extensions/common/glm/gtc/type_precision.inl | 36 + extensions/common/glm/gtc/type_ptr.hpp | 178 + extensions/common/glm/gtc/type_ptr.inl | 479 ++ extensions/common/glm/gtc/ulp.hpp | 92 + extensions/common/glm/gtc/ulp.inl | 350 + extensions/common/glm/gtc/vec1.hpp | 193 + extensions/common/glm/gtc/vec1.inl | 31 + .../common/glm/gtx/associated_min_max.hpp | 231 + .../common/glm/gtx/associated_min_max.inl | 384 + extensions/common/glm/gtx/bit.hpp | 120 + extensions/common/glm/gtx/bit.inl | 107 + extensions/common/glm/gtx/closest_point.hpp | 74 + extensions/common/glm/gtx/closest_point.inl | 75 + extensions/common/glm/gtx/color_space.hpp | 97 + extensions/common/glm/gtx/color_space.inl | 172 + .../common/glm/gtx/color_space_YCoCg.hpp | 85 + .../common/glm/gtx/color_space_YCoCg.inl | 87 + extensions/common/glm/gtx/common.hpp | 74 + extensions/common/glm/gtx/common.inl | 102 + extensions/common/glm/gtx/compatibility.hpp | 158 + extensions/common/glm/gtx/compatibility.inl | 83 + extensions/common/glm/gtx/component_wise.hpp | 84 + extensions/common/glm/gtx/component_wise.inl | 70 + extensions/common/glm/gtx/dual_quaternion.hpp | 321 + extensions/common/glm/gtx/dual_quaternion.inl | 400 + extensions/common/glm/gtx/euler_angles.hpp | 156 + extensions/common/glm/gtx/euler_angles.inl | 287 + extensions/common/glm/gtx/extend.hpp | 67 + extensions/common/glm/gtx/extend.inl | 78 + .../common/glm/gtx/extented_min_max.hpp | 162 + .../common/glm/gtx/extented_min_max.inl | 169 + .../common/glm/gtx/fast_exponential.hpp | 120 + .../common/glm/gtx/fast_exponential.inl | 166 + .../common/glm/gtx/fast_square_root.hpp | 117 + .../common/glm/gtx/fast_square_root.inl | 110 + .../common/glm/gtx/fast_trigonometry.hpp | 104 + .../common/glm/gtx/fast_trigonometry.inl | 162 + extensions/common/glm/gtx/gradient_paint.hpp | 77 + extensions/common/glm/gtx/gradient_paint.inl | 66 + .../glm/gtx/handed_coordinate_space.hpp | 75 + .../glm/gtx/handed_coordinate_space.inl | 56 + extensions/common/glm/gtx/integer.hpp | 101 + extensions/common/glm/gtx/integer.inl | 211 + extensions/common/glm/gtx/intersect.hpp | 112 + extensions/common/glm/gtx/intersect.inl | 217 + extensions/common/glm/gtx/io.hpp | 224 + extensions/common/glm/gtx/io.inl | 618 ++ extensions/common/glm/gtx/log_base.hpp | 73 + extensions/common/glm/gtx/log_base.inl | 47 + .../common/glm/gtx/matrix_cross_product.hpp | 72 + .../common/glm/gtx/matrix_cross_product.inl | 67 + .../common/glm/gtx/matrix_decompose.hpp | 70 + .../common/glm/gtx/matrix_decompose.inl | 231 + .../common/glm/gtx/matrix_interpolation.hpp | 89 + .../common/glm/gtx/matrix_interpolation.inl | 163 + .../common/glm/gtx/matrix_major_storage.hpp | 144 + .../common/glm/gtx/matrix_major_storage.inl | 196 + .../common/glm/gtx/matrix_operation.hpp | 113 + .../common/glm/gtx/matrix_operation.inl | 147 + extensions/common/glm/gtx/matrix_query.hpp | 102 + extensions/common/glm/gtx/matrix_query.inl | 143 + .../common/glm/gtx/matrix_transform_2d.hpp | 106 + .../common/glm/gtx/matrix_transform_2d.inl | 97 + extensions/common/glm/gtx/mixed_product.hpp | 66 + extensions/common/glm/gtx/mixed_product.inl | 45 + extensions/common/glm/gtx/multiple.hpp | 106 + extensions/common/glm/gtx/multiple.inl | 64 + extensions/common/glm/gtx/norm.hpp | 128 + extensions/common/glm/gtx/norm.inl | 170 + extensions/common/glm/gtx/normal.hpp | 68 + extensions/common/glm/gtx/normal.inl | 45 + extensions/common/glm/gtx/normalize_dot.hpp | 74 + extensions/common/glm/gtx/normalize_dot.inl | 46 + .../common/glm/gtx/number_precision.hpp | 86 + .../common/glm/gtx/number_precision.inl | 36 + extensions/common/glm/gtx/optimum_pow.hpp | 79 + extensions/common/glm/gtx/optimum_pow.inl | 52 + extensions/common/glm/gtx/orthonormalize.hpp | 74 + extensions/common/glm/gtx/orthonormalize.inl | 59 + extensions/common/glm/gtx/perpendicular.hpp | 68 + extensions/common/glm/gtx/perpendicular.inl | 44 + .../common/glm/gtx/polar_coordinates.hpp | 73 + .../common/glm/gtx/polar_coordinates.inl | 66 + extensions/common/glm/gtx/projection.hpp | 65 + extensions/common/glm/gtx/projection.inl | 40 + extensions/common/glm/gtx/quaternion.hpp | 214 + extensions/common/glm/gtx/quaternion.inl | 285 + extensions/common/glm/gtx/range.hpp | 102 + extensions/common/glm/gtx/raw_data.hpp | 76 + extensions/common/glm/gtx/raw_data.inl | 31 + .../common/glm/gtx/rotate_normalized_axis.hpp | 93 + .../common/glm/gtx/rotate_normalized_axis.inl | 88 + extensions/common/glm/gtx/rotate_vector.hpp | 146 + extensions/common/glm/gtx/rotate_vector.inl | 217 + .../common/glm/gtx/scalar_multiplication.hpp | 98 + .../common/glm/gtx/scalar_relational.hpp | 61 + .../common/glm/gtx/scalar_relational.inl | 118 + extensions/common/glm/gtx/simd_mat4.hpp | 205 + extensions/common/glm/gtx/simd_mat4.inl | 602 ++ extensions/common/glm/gtx/simd_quat.hpp | 335 + extensions/common/glm/gtx/simd_quat.inl | 645 ++ extensions/common/glm/gtx/simd_vec4.hpp | 574 ++ extensions/common/glm/gtx/simd_vec4.inl | 727 ++ extensions/common/glm/gtx/spline.hpp | 90 + extensions/common/glm/gtx/spline.inl | 92 + extensions/common/glm/gtx/std_based_type.hpp | 92 + extensions/common/glm/gtx/std_based_type.inl | 36 + extensions/common/glm/gtx/string_cast.hpp | 74 + extensions/common/glm/gtx/string_cast.inl | 455 ++ extensions/common/glm/gtx/transform.hpp | 85 + extensions/common/glm/gtx/transform.inl | 60 + extensions/common/glm/gtx/transform2.hpp | 136 + extensions/common/glm/gtx/transform2.inl | 177 + extensions/common/glm/gtx/type_aligned.hpp | 995 +++ extensions/common/glm/gtx/type_aligned.inl | 36 + extensions/common/glm/gtx/vector_angle.hpp | 89 + extensions/common/glm/gtx/vector_angle.inl | 87 + extensions/common/glm/gtx/vector_query.hpp | 91 + extensions/common/glm/gtx/vector_query.inl | 222 + extensions/common/glm/gtx/wrap.hpp | 74 + extensions/common/glm/gtx/wrap.inl | 185 + extensions/common/glm/integer.hpp | 35 + extensions/common/glm/mat2x2.hpp | 81 + extensions/common/glm/mat2x3.hpp | 61 + extensions/common/glm/mat2x4.hpp | 60 + extensions/common/glm/mat3x2.hpp | 60 + extensions/common/glm/mat3x3.hpp | 81 + extensions/common/glm/mat3x4.hpp | 60 + extensions/common/glm/mat4x2.hpp | 60 + extensions/common/glm/mat4x3.hpp | 60 + extensions/common/glm/mat4x4.hpp | 81 + extensions/common/glm/matrix.hpp | 35 + extensions/common/glm/packing.hpp | 35 + extensions/common/glm/trigonometric.hpp | 35 + extensions/common/glm/vec2.hpp | 35 + extensions/common/glm/vec3.hpp | 35 + extensions/common/glm/vec4.hpp | 35 + extensions/common/glm/vector_relational.hpp | 35 + extensions/common/logging.hpp | 6 + extensions/common/lzoconf.h | 453 ++ extensions/common/lzodefs.h | 3134 ++++++++ extensions/common/membuf.hpp | 56 + extensions/common/minilzo.c | 6231 +++++++++++++++ extensions/common/minilzo.h | 106 + extensions/common/p3d/animation.cpp | 72 + extensions/common/p3d/animation.hpp | 69 + extensions/common/p3d/compressed.cpp | 237 + extensions/common/p3d/compressed.hpp | 166 + extensions/common/p3d/lod_info.cpp | 289 + extensions/common/p3d/lod_info.hpp | 237 + extensions/common/p3d/lod_types.hpp | 33 + extensions/common/p3d/model.cpp | 116 + extensions/common/p3d/model.hpp | 57 + extensions/common/p3d/model_info.cpp | 91 + extensions/common/p3d/model_info.hpp | 74 + extensions/common/p3d/parser.cpp | 26 + extensions/common/p3d/parser.hpp | 17 + extensions/common/p3d/parser_ref.txt | 269 + extensions/common/p3d/read_helpers.hpp | 11 + extensions/common/p3d/skeleton.cpp | 46 + extensions/common/p3d/skeleton.hpp | 36 + extensions/common/pbo/archive.cpp | 91 + extensions/common/pbo/archive.hpp | 61 + extensions/common/pbo/search.cpp | 301 + extensions/common/pbo/search.hpp | 27 + extensions/common/shared.cpp | 41 + extensions/common/shared.hpp | 77 + extensions/common/simplepipe_win32.cpp | 179 + extensions/common/simplepipe_win32.hpp | 57 + extensions/common/simulation/object.cpp | 464 ++ extensions/common/simulation/object.hpp | 221 + extensions/common/singleton.hpp | 31 + extensions/common/targetver.h | 2 +- extensions/common/transform_matrix.hpp | 34 + extensions/common/vector.cpp | 11 + extensions/common/vector.hpp | 161 + extensions/dynload/CMakeLists.txt | 14 + extensions/dynload/ace_dynload.cpp | 66 + extensions/dynload/ace_dynload_dllmain.cpp | 33 + extensions/dynload/dynloader.hpp | 168 + extensions/fcs/CMakeLists.txt | 7 +- extensions/fcs/ace_fcs.cpp | 5 +- extensions/lib/bullet3 | 1 + 312 files changed, 79346 insertions(+), 40 deletions(-) create mode 100644 extensions/cmake/FindDirectX.cmake create mode 100644 extensions/common/CMakeLists.txt create mode 100644 extensions/common/arguments.hpp create mode 100644 extensions/common/directx/d3d_display.cpp create mode 100644 extensions/common/directx/d3d_display.hpp create mode 100644 extensions/common/dispatch.hpp create mode 100644 extensions/common/easyloggingc++.hpp create mode 100644 extensions/common/glm/CMakeLists.txt create mode 100644 extensions/common/glm/common.hpp create mode 100644 extensions/common/glm/detail/_features.hpp create mode 100644 extensions/common/glm/detail/_fixes.hpp create mode 100644 extensions/common/glm/detail/_noise.hpp create mode 100644 extensions/common/glm/detail/_swizzle.hpp create mode 100644 extensions/common/glm/detail/_swizzle_func.hpp create mode 100644 extensions/common/glm/detail/_vectorize.hpp create mode 100644 extensions/common/glm/detail/dummy.cpp create mode 100644 extensions/common/glm/detail/func_common.hpp create mode 100644 extensions/common/glm/detail/func_common.inl create mode 100644 extensions/common/glm/detail/func_exponential.hpp create mode 100644 extensions/common/glm/detail/func_exponential.inl create mode 100644 extensions/common/glm/detail/func_geometric.hpp create mode 100644 extensions/common/glm/detail/func_geometric.inl create mode 100644 extensions/common/glm/detail/func_integer.hpp create mode 100644 extensions/common/glm/detail/func_integer.inl create mode 100644 extensions/common/glm/detail/func_matrix.hpp create mode 100644 extensions/common/glm/detail/func_matrix.inl create mode 100644 extensions/common/glm/detail/func_noise.hpp create mode 100644 extensions/common/glm/detail/func_noise.inl create mode 100644 extensions/common/glm/detail/func_packing.hpp create mode 100644 extensions/common/glm/detail/func_packing.inl create mode 100644 extensions/common/glm/detail/func_trigonometric.hpp create mode 100644 extensions/common/glm/detail/func_trigonometric.inl create mode 100644 extensions/common/glm/detail/func_vector_relational.hpp create mode 100644 extensions/common/glm/detail/func_vector_relational.inl create mode 100644 extensions/common/glm/detail/glm.cpp create mode 100644 extensions/common/glm/detail/intrinsic_common.hpp create mode 100644 extensions/common/glm/detail/intrinsic_common.inl create mode 100644 extensions/common/glm/detail/intrinsic_exponential.hpp create mode 100644 extensions/common/glm/detail/intrinsic_exponential.inl create mode 100644 extensions/common/glm/detail/intrinsic_geometric.hpp create mode 100644 extensions/common/glm/detail/intrinsic_geometric.inl create mode 100644 extensions/common/glm/detail/intrinsic_integer.hpp create mode 100644 extensions/common/glm/detail/intrinsic_integer.inl create mode 100644 extensions/common/glm/detail/intrinsic_matrix.hpp create mode 100644 extensions/common/glm/detail/intrinsic_matrix.inl create mode 100644 extensions/common/glm/detail/intrinsic_trigonometric.hpp create mode 100644 extensions/common/glm/detail/intrinsic_trigonometric.inl create mode 100644 extensions/common/glm/detail/intrinsic_vector_relational.hpp create mode 100644 extensions/common/glm/detail/intrinsic_vector_relational.inl create mode 100644 extensions/common/glm/detail/precision.hpp create mode 100644 extensions/common/glm/detail/setup.hpp create mode 100644 extensions/common/glm/detail/type_float.hpp create mode 100644 extensions/common/glm/detail/type_gentype.hpp create mode 100644 extensions/common/glm/detail/type_gentype.inl create mode 100644 extensions/common/glm/detail/type_half.hpp create mode 100644 extensions/common/glm/detail/type_half.inl create mode 100644 extensions/common/glm/detail/type_int.hpp create mode 100644 extensions/common/glm/detail/type_mat.hpp create mode 100644 extensions/common/glm/detail/type_mat.inl create mode 100644 extensions/common/glm/detail/type_mat2x2.hpp create mode 100644 extensions/common/glm/detail/type_mat2x2.inl create mode 100644 extensions/common/glm/detail/type_mat2x3.hpp create mode 100644 extensions/common/glm/detail/type_mat2x3.inl create mode 100644 extensions/common/glm/detail/type_mat2x4.hpp create mode 100644 extensions/common/glm/detail/type_mat2x4.inl create mode 100644 extensions/common/glm/detail/type_mat3x2.hpp create mode 100644 extensions/common/glm/detail/type_mat3x2.inl create mode 100644 extensions/common/glm/detail/type_mat3x3.hpp create mode 100644 extensions/common/glm/detail/type_mat3x3.inl create mode 100644 extensions/common/glm/detail/type_mat3x4.hpp create mode 100644 extensions/common/glm/detail/type_mat3x4.inl create mode 100644 extensions/common/glm/detail/type_mat4x2.hpp create mode 100644 extensions/common/glm/detail/type_mat4x2.inl create mode 100644 extensions/common/glm/detail/type_mat4x3.hpp create mode 100644 extensions/common/glm/detail/type_mat4x3.inl create mode 100644 extensions/common/glm/detail/type_mat4x4.hpp create mode 100644 extensions/common/glm/detail/type_mat4x4.inl create mode 100644 extensions/common/glm/detail/type_vec.hpp create mode 100644 extensions/common/glm/detail/type_vec.inl create mode 100644 extensions/common/glm/detail/type_vec1.hpp create mode 100644 extensions/common/glm/detail/type_vec1.inl create mode 100644 extensions/common/glm/detail/type_vec2.hpp create mode 100644 extensions/common/glm/detail/type_vec2.inl create mode 100644 extensions/common/glm/detail/type_vec3.hpp create mode 100644 extensions/common/glm/detail/type_vec3.inl create mode 100644 extensions/common/glm/detail/type_vec4.hpp create mode 100644 extensions/common/glm/detail/type_vec4.inl create mode 100644 extensions/common/glm/detail/type_vec4_avx.inl create mode 100644 extensions/common/glm/detail/type_vec4_avx2.inl create mode 100644 extensions/common/glm/detail/type_vec4_sse2.inl create mode 100644 extensions/common/glm/exponential.hpp create mode 100644 extensions/common/glm/ext.hpp create mode 100644 extensions/common/glm/fwd.hpp create mode 100644 extensions/common/glm/geometric.hpp create mode 100644 extensions/common/glm/glm.hpp create mode 100644 extensions/common/glm/gtc/bitfield.hpp create mode 100644 extensions/common/glm/gtc/bitfield.inl create mode 100644 extensions/common/glm/gtc/constants.hpp create mode 100644 extensions/common/glm/gtc/constants.inl create mode 100644 extensions/common/glm/gtc/epsilon.hpp create mode 100644 extensions/common/glm/gtc/epsilon.inl create mode 100644 extensions/common/glm/gtc/integer.hpp create mode 100644 extensions/common/glm/gtc/integer.inl create mode 100644 extensions/common/glm/gtc/matrix_access.hpp create mode 100644 extensions/common/glm/gtc/matrix_access.inl create mode 100644 extensions/common/glm/gtc/matrix_integer.hpp create mode 100644 extensions/common/glm/gtc/matrix_inverse.hpp create mode 100644 extensions/common/glm/gtc/matrix_inverse.inl create mode 100644 extensions/common/glm/gtc/matrix_transform.hpp create mode 100644 extensions/common/glm/gtc/matrix_transform.inl create mode 100644 extensions/common/glm/gtc/noise.hpp create mode 100644 extensions/common/glm/gtc/noise.inl create mode 100644 extensions/common/glm/gtc/packing.hpp create mode 100644 extensions/common/glm/gtc/packing.inl create mode 100644 extensions/common/glm/gtc/quaternion.hpp create mode 100644 extensions/common/glm/gtc/quaternion.inl create mode 100644 extensions/common/glm/gtc/random.hpp create mode 100644 extensions/common/glm/gtc/random.inl create mode 100644 extensions/common/glm/gtc/reciprocal.hpp create mode 100644 extensions/common/glm/gtc/reciprocal.inl create mode 100644 extensions/common/glm/gtc/round.hpp create mode 100644 extensions/common/glm/gtc/round.inl create mode 100644 extensions/common/glm/gtc/type_precision.hpp create mode 100644 extensions/common/glm/gtc/type_precision.inl create mode 100644 extensions/common/glm/gtc/type_ptr.hpp create mode 100644 extensions/common/glm/gtc/type_ptr.inl create mode 100644 extensions/common/glm/gtc/ulp.hpp create mode 100644 extensions/common/glm/gtc/ulp.inl create mode 100644 extensions/common/glm/gtc/vec1.hpp create mode 100644 extensions/common/glm/gtc/vec1.inl create mode 100644 extensions/common/glm/gtx/associated_min_max.hpp create mode 100644 extensions/common/glm/gtx/associated_min_max.inl create mode 100644 extensions/common/glm/gtx/bit.hpp create mode 100644 extensions/common/glm/gtx/bit.inl create mode 100644 extensions/common/glm/gtx/closest_point.hpp create mode 100644 extensions/common/glm/gtx/closest_point.inl create mode 100644 extensions/common/glm/gtx/color_space.hpp create mode 100644 extensions/common/glm/gtx/color_space.inl create mode 100644 extensions/common/glm/gtx/color_space_YCoCg.hpp create mode 100644 extensions/common/glm/gtx/color_space_YCoCg.inl create mode 100644 extensions/common/glm/gtx/common.hpp create mode 100644 extensions/common/glm/gtx/common.inl create mode 100644 extensions/common/glm/gtx/compatibility.hpp create mode 100644 extensions/common/glm/gtx/compatibility.inl create mode 100644 extensions/common/glm/gtx/component_wise.hpp create mode 100644 extensions/common/glm/gtx/component_wise.inl create mode 100644 extensions/common/glm/gtx/dual_quaternion.hpp create mode 100644 extensions/common/glm/gtx/dual_quaternion.inl create mode 100644 extensions/common/glm/gtx/euler_angles.hpp create mode 100644 extensions/common/glm/gtx/euler_angles.inl create mode 100644 extensions/common/glm/gtx/extend.hpp create mode 100644 extensions/common/glm/gtx/extend.inl create mode 100644 extensions/common/glm/gtx/extented_min_max.hpp create mode 100644 extensions/common/glm/gtx/extented_min_max.inl create mode 100644 extensions/common/glm/gtx/fast_exponential.hpp create mode 100644 extensions/common/glm/gtx/fast_exponential.inl create mode 100644 extensions/common/glm/gtx/fast_square_root.hpp create mode 100644 extensions/common/glm/gtx/fast_square_root.inl create mode 100644 extensions/common/glm/gtx/fast_trigonometry.hpp create mode 100644 extensions/common/glm/gtx/fast_trigonometry.inl create mode 100644 extensions/common/glm/gtx/gradient_paint.hpp create mode 100644 extensions/common/glm/gtx/gradient_paint.inl create mode 100644 extensions/common/glm/gtx/handed_coordinate_space.hpp create mode 100644 extensions/common/glm/gtx/handed_coordinate_space.inl create mode 100644 extensions/common/glm/gtx/integer.hpp create mode 100644 extensions/common/glm/gtx/integer.inl create mode 100644 extensions/common/glm/gtx/intersect.hpp create mode 100644 extensions/common/glm/gtx/intersect.inl create mode 100644 extensions/common/glm/gtx/io.hpp create mode 100644 extensions/common/glm/gtx/io.inl create mode 100644 extensions/common/glm/gtx/log_base.hpp create mode 100644 extensions/common/glm/gtx/log_base.inl create mode 100644 extensions/common/glm/gtx/matrix_cross_product.hpp create mode 100644 extensions/common/glm/gtx/matrix_cross_product.inl create mode 100644 extensions/common/glm/gtx/matrix_decompose.hpp create mode 100644 extensions/common/glm/gtx/matrix_decompose.inl create mode 100644 extensions/common/glm/gtx/matrix_interpolation.hpp create mode 100644 extensions/common/glm/gtx/matrix_interpolation.inl create mode 100644 extensions/common/glm/gtx/matrix_major_storage.hpp create mode 100644 extensions/common/glm/gtx/matrix_major_storage.inl create mode 100644 extensions/common/glm/gtx/matrix_operation.hpp create mode 100644 extensions/common/glm/gtx/matrix_operation.inl create mode 100644 extensions/common/glm/gtx/matrix_query.hpp create mode 100644 extensions/common/glm/gtx/matrix_query.inl create mode 100644 extensions/common/glm/gtx/matrix_transform_2d.hpp create mode 100644 extensions/common/glm/gtx/matrix_transform_2d.inl create mode 100644 extensions/common/glm/gtx/mixed_product.hpp create mode 100644 extensions/common/glm/gtx/mixed_product.inl create mode 100644 extensions/common/glm/gtx/multiple.hpp create mode 100644 extensions/common/glm/gtx/multiple.inl create mode 100644 extensions/common/glm/gtx/norm.hpp create mode 100644 extensions/common/glm/gtx/norm.inl create mode 100644 extensions/common/glm/gtx/normal.hpp create mode 100644 extensions/common/glm/gtx/normal.inl create mode 100644 extensions/common/glm/gtx/normalize_dot.hpp create mode 100644 extensions/common/glm/gtx/normalize_dot.inl create mode 100644 extensions/common/glm/gtx/number_precision.hpp create mode 100644 extensions/common/glm/gtx/number_precision.inl create mode 100644 extensions/common/glm/gtx/optimum_pow.hpp create mode 100644 extensions/common/glm/gtx/optimum_pow.inl create mode 100644 extensions/common/glm/gtx/orthonormalize.hpp create mode 100644 extensions/common/glm/gtx/orthonormalize.inl create mode 100644 extensions/common/glm/gtx/perpendicular.hpp create mode 100644 extensions/common/glm/gtx/perpendicular.inl create mode 100644 extensions/common/glm/gtx/polar_coordinates.hpp create mode 100644 extensions/common/glm/gtx/polar_coordinates.inl create mode 100644 extensions/common/glm/gtx/projection.hpp create mode 100644 extensions/common/glm/gtx/projection.inl create mode 100644 extensions/common/glm/gtx/quaternion.hpp create mode 100644 extensions/common/glm/gtx/quaternion.inl create mode 100644 extensions/common/glm/gtx/range.hpp create mode 100644 extensions/common/glm/gtx/raw_data.hpp create mode 100644 extensions/common/glm/gtx/raw_data.inl create mode 100644 extensions/common/glm/gtx/rotate_normalized_axis.hpp create mode 100644 extensions/common/glm/gtx/rotate_normalized_axis.inl create mode 100644 extensions/common/glm/gtx/rotate_vector.hpp create mode 100644 extensions/common/glm/gtx/rotate_vector.inl create mode 100644 extensions/common/glm/gtx/scalar_multiplication.hpp create mode 100644 extensions/common/glm/gtx/scalar_relational.hpp create mode 100644 extensions/common/glm/gtx/scalar_relational.inl create mode 100644 extensions/common/glm/gtx/simd_mat4.hpp create mode 100644 extensions/common/glm/gtx/simd_mat4.inl create mode 100644 extensions/common/glm/gtx/simd_quat.hpp create mode 100644 extensions/common/glm/gtx/simd_quat.inl create mode 100644 extensions/common/glm/gtx/simd_vec4.hpp create mode 100644 extensions/common/glm/gtx/simd_vec4.inl create mode 100644 extensions/common/glm/gtx/spline.hpp create mode 100644 extensions/common/glm/gtx/spline.inl create mode 100644 extensions/common/glm/gtx/std_based_type.hpp create mode 100644 extensions/common/glm/gtx/std_based_type.inl create mode 100644 extensions/common/glm/gtx/string_cast.hpp create mode 100644 extensions/common/glm/gtx/string_cast.inl create mode 100644 extensions/common/glm/gtx/transform.hpp create mode 100644 extensions/common/glm/gtx/transform.inl create mode 100644 extensions/common/glm/gtx/transform2.hpp create mode 100644 extensions/common/glm/gtx/transform2.inl create mode 100644 extensions/common/glm/gtx/type_aligned.hpp create mode 100644 extensions/common/glm/gtx/type_aligned.inl create mode 100644 extensions/common/glm/gtx/vector_angle.hpp create mode 100644 extensions/common/glm/gtx/vector_angle.inl create mode 100644 extensions/common/glm/gtx/vector_query.hpp create mode 100644 extensions/common/glm/gtx/vector_query.inl create mode 100644 extensions/common/glm/gtx/wrap.hpp create mode 100644 extensions/common/glm/gtx/wrap.inl create mode 100644 extensions/common/glm/integer.hpp create mode 100644 extensions/common/glm/mat2x2.hpp create mode 100644 extensions/common/glm/mat2x3.hpp create mode 100644 extensions/common/glm/mat2x4.hpp create mode 100644 extensions/common/glm/mat3x2.hpp create mode 100644 extensions/common/glm/mat3x3.hpp create mode 100644 extensions/common/glm/mat3x4.hpp create mode 100644 extensions/common/glm/mat4x2.hpp create mode 100644 extensions/common/glm/mat4x3.hpp create mode 100644 extensions/common/glm/mat4x4.hpp create mode 100644 extensions/common/glm/matrix.hpp create mode 100644 extensions/common/glm/packing.hpp create mode 100644 extensions/common/glm/trigonometric.hpp create mode 100644 extensions/common/glm/vec2.hpp create mode 100644 extensions/common/glm/vec3.hpp create mode 100644 extensions/common/glm/vec4.hpp create mode 100644 extensions/common/glm/vector_relational.hpp create mode 100644 extensions/common/logging.hpp create mode 100644 extensions/common/lzoconf.h create mode 100644 extensions/common/lzodefs.h create mode 100644 extensions/common/membuf.hpp create mode 100644 extensions/common/minilzo.c create mode 100644 extensions/common/minilzo.h create mode 100644 extensions/common/p3d/animation.cpp create mode 100644 extensions/common/p3d/animation.hpp create mode 100644 extensions/common/p3d/compressed.cpp create mode 100644 extensions/common/p3d/compressed.hpp create mode 100644 extensions/common/p3d/lod_info.cpp create mode 100644 extensions/common/p3d/lod_info.hpp create mode 100644 extensions/common/p3d/lod_types.hpp create mode 100644 extensions/common/p3d/model.cpp create mode 100644 extensions/common/p3d/model.hpp create mode 100644 extensions/common/p3d/model_info.cpp create mode 100644 extensions/common/p3d/model_info.hpp create mode 100644 extensions/common/p3d/parser.cpp create mode 100644 extensions/common/p3d/parser.hpp create mode 100644 extensions/common/p3d/parser_ref.txt create mode 100644 extensions/common/p3d/read_helpers.hpp create mode 100644 extensions/common/p3d/skeleton.cpp create mode 100644 extensions/common/p3d/skeleton.hpp create mode 100644 extensions/common/pbo/archive.cpp create mode 100644 extensions/common/pbo/archive.hpp create mode 100644 extensions/common/pbo/search.cpp create mode 100644 extensions/common/pbo/search.hpp create mode 100644 extensions/common/shared.cpp create mode 100644 extensions/common/shared.hpp create mode 100644 extensions/common/simplepipe_win32.cpp create mode 100644 extensions/common/simplepipe_win32.hpp create mode 100644 extensions/common/simulation/object.cpp create mode 100644 extensions/common/simulation/object.hpp create mode 100644 extensions/common/singleton.hpp create mode 100644 extensions/common/transform_matrix.hpp create mode 100644 extensions/common/vector.cpp create mode 100644 extensions/common/vector.hpp create mode 100644 extensions/dynload/CMakeLists.txt create mode 100644 extensions/dynload/ace_dynload.cpp create mode 100644 extensions/dynload/ace_dynload_dllmain.cpp create mode 100644 extensions/dynload/dynloader.hpp create mode 160000 extensions/lib/bullet3 diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index 9f4a8a29fa..b1c1703f94 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -1,11 +1,20 @@ cmake_minimum_required (VERSION 3.0) project (ACE) +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +if(WIN32) +add_definitions(/DWINVER=0x0600 /D_WIN32_WINNT=0x0600) +endif() + if (NOT CMAKE_BUILD_TYPE AND CMAKE_COMPILER_IS_GNUCXX) message(STATUS "No build type selected, default to Debug") set(CMAKE_BUILD_TYPE "Debug") endif() +option(DEVEL "DEVEL" OFF) +option(USE_BULLET "USE_BULLET" OFF) +option(USE_DIRECTX "USE_DIRECTX" OFF) option(USE_64BIT_BUILD "USE_64BIT_BUILD" OFF) option(USE_STATIC_LINKING "USE_STATIC_LINKING" ON) @@ -15,15 +24,66 @@ if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") set(CMAKE_SHARED_LINKER_FLAGS "-static-libgcc -static-libstdc++") else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:x86") set(CMAKE_CXX_FLAGS_DEBUG "/D _DEBUG /MTd /Zi /Ob0 /Od /RTC1") set(CMAKE_CXX_FLAGS_MINSIZEREL "/MT /O1 /Ob1 /D NDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Ob2 /D NDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MT /Zi /O2 /Ob1 /D NDEBUG") endif() -file(GLOB ACE_COMMON_SOURCES common/*.h common/*.hpp common/*.c common/*.cpp) -add_library(ace_common STATIC ${ACE_COMMON_SOURCES}) -include_directories(AFTER "common") +include_directories("common") + +if(USE_BULLET) + # Dependencies + # + set(BACKUP_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}) + set(BACKUP_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}) + set(BACKUP_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + + add_definitions(-DUSE_DIRECTX) + add_subdirectory(lib/bullet3) + + set_target_properties(App_BasicExample PROPERTIES FOLDER Bullet3) + set_target_properties(App_HelloWorld PROPERTIES FOLDER Bullet3) + set_target_properties(App_ExampleBrowser PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet2FileLoader PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet3Collision PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet3Dynamics PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet3Geometry PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet3Common PROPERTIES FOLDER Bullet3) + set_target_properties(Bullet3OpenCL_clew PROPERTIES FOLDER Bullet3) + set_target_properties(BulletCollision PROPERTIES FOLDER Bullet3) + set_target_properties(BulletDynamics PROPERTIES FOLDER Bullet3) + set_target_properties(BulletFileLoader PROPERTIES FOLDER Bullet3) + set_target_properties(BulletSoftBody PROPERTIES FOLDER Bullet3) + + set_target_properties(BulletWorldImporter PROPERTIES FOLDER Bullet3) + set_target_properties(BulletXmlWorldImporter PROPERTIES FOLDER Bullet3) + set_target_properties(ConvexDecomposition PROPERTIES FOLDER Bullet3) + set_target_properties(GIMPACTUtils PROPERTIES FOLDER Bullet3) + set_target_properties(gtest PROPERTIES FOLDER Bullet3) + set_target_properties(gwen PROPERTIES FOLDER Bullet3) + set_target_properties(HACD PROPERTIES FOLDER Bullet3) + set_target_properties(OpenGLWindow PROPERTIES FOLDER Bullet3) + set_target_properties(LinearMath PROPERTIES FOLDER Bullet3) + + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${BACKUP_ARCHIVE_OUTPUT_DIRECTORY}) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${BACKUP_LIBRARY_OUTPUT_DIRECTORY}) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${BACKUP_RUNTIME_OUTPUT_DIRECTORY}) + + include_directories(BEFORE "lib/bullet3/src") +endif() +if(USE_DIRECTX) + add_definitions(-DUSE_DIRECTX) + set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) + find_package (DirectX) + link_directories (BEFORE ${DirectX_D3DX11_LIBRARY}) + include_directories (BEFORE ${DirectX_D3DX11_INCLUDE_DIR} ) +endif() +if(DEVEL) + add_definitions(-DDEVEL) +endif() + string(TIMESTAMP ACE_BUILDSTAMP "%Y-%m-%dT%H:%M:%SZ") set(ACE_VERSION_MAJOR 3) @@ -50,13 +110,29 @@ if(MSVC) set(GLOBAL_RC ${CMAKE_CURRENT_BINARY_DIR}/common/ace_version_win32.rc) endif() -include_directories(AFTER ${CMAKE_CURRENT_BINARY_DIR}/common) +include_directories(${CMAKE_CURRENT_BINARY_DIR}/common) set(GLOBAL_SOURCES ${GLOBAL_RC}) + # Add extensions to build here +add_subdirectory(common) + +# Extensions + add_subdirectory(fcs) add_subdirectory(break_line) add_subdirectory(clipboard) add_subdirectory(advanced_ballistics) +# Test Extension for dynamically loading/unloading built extensions; does not build in release +if (DEVEL) + add_subdirectory(dynload) + add_subdirectory(tests) + if(USE_DIRECTX) + add_subdirectory(lib/directxtk) + endif() +endif() + + + message("Build Type: ${CMAKE_BUILD_TYPE}") \ No newline at end of file diff --git a/extensions/advanced_ballistics/AdvancedBallistics.cpp b/extensions/advanced_ballistics/AdvancedBallistics.cpp index e6c55184a7..7e87592e00 100644 --- a/extensions/advanced_ballistics/AdvancedBallistics.cpp +++ b/extensions/advanced_ballistics/AdvancedBallistics.cpp @@ -1,4 +1,4 @@ -#include "ace_common.h" +#include "shared.hpp" #include <string> #include <vector> @@ -235,9 +235,11 @@ extern "C" void __stdcall RVExtension(char *output, int outputSize, const char *function) { + ZERO_OUTPUT(); + if (!strcmp(function, "version")) { int n = sprintf_s(output, outputSize, "%s", ACE_FULL_VERSION_STR); - return; + EXTENSION_RETURN(); } char* input = _strdup(function); @@ -257,7 +259,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) retard = calculateRetard(dragModel, ballisticCoefficient, velocity); int n = sprintf_s(output, outputSize, "%f", retard); - return; + EXTENSION_RETURN(); } else if (!strcmp(mode, "atmosphericCorrection")) { double ballisticCoefficient = 1.0; double temperature = 15.0; @@ -273,7 +275,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) ballisticCoefficient = calculateAtmosphericCorrection(ballisticCoefficient, temperature, pressure, humidity, atmosphereModel); int n = sprintf_s(output, outputSize, "%f", ballisticCoefficient); - return; + EXTENSION_RETURN(); } else if (!strcmp(mode, "new")) { unsigned int index = 0; double airFriction = 0.0; @@ -339,8 +341,10 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) tickTime = strtod(strtok_s(NULL, ":", &next_token), NULL); tickTime += strtod(strtok_s(NULL, ":", &next_token), NULL); - if (index >= bulletDatabase.size()) - bulletDatabase.resize(index+1); + while (index >= bulletDatabase.size()) { + Bullet bullet; + bulletDatabase.push_back(bullet); + } bulletDatabase[index].airFriction = airFriction; bulletDatabase[index].ballisticCoefficients = ballisticCoefficients; @@ -366,7 +370,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) bulletDatabase[index].randSeed = 0; int n = sprintf_s(output, outputSize, "%s", ""); - return; + EXTENSION_RETURN(); } else if (!strcmp(mode, "simulate")) { // simulate:0:[-0.109985,542.529,-3.98301]:[3751.57,5332.23,214.252]:[0.598153,2.38829,0]:28.6:0:0.481542:0:215.16 unsigned int index = 0; @@ -583,7 +587,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) }; int n = sprintf_s(output, outputSize, "_bullet setVelocity (_bulletVelocity vectorAdd [%f, %f, %f]); _bullet setPosASL (_bulletPosition vectorAdd [%f, %f, %f]);", velocityOffset[0], velocityOffset[1], velocityOffset[2], positionOffset[0], positionOffset[1], positionOffset[2]); - return; + EXTENSION_RETURN(); } else if (!strcmp(mode, "set")) { int height = 0; int numObjects = 0; @@ -598,7 +602,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) map->gridSurfaceIsWater.push_back(surfaceIsWater); int n = sprintf_s(output, outputSize, "%s", ""); - return; + EXTENSION_RETURN(); } else if (!strcmp(mode, "init")) { int mapSize = 0; int mapGrids = 0; @@ -609,15 +613,11 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) mapGrids = (int)ceil((double)mapSize / 50.0) + 1; gridCells = mapGrids * mapGrids; - - auto map_iter = mapDatabase.find(worldName); - if (map_iter == mapDatabase.end()) - return; - map = &map_iter->second; + map = &mapDatabase[worldName]; if (map->gridHeights.size() == gridCells) { int n = sprintf_s(output, outputSize, "%s", "Terrain already initialized"); - return; + EXTENSION_RETURN(); } map->mapSize = mapSize; @@ -630,9 +630,9 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) map->gridSurfaceIsWater.reserve(gridCells); int n = sprintf_s(output, outputSize, "%s", ""); - return; + EXTENSION_RETURN(); } int n = sprintf_s(output, outputSize, "%s", ""); - return; + EXTENSION_RETURN(); } diff --git a/extensions/advanced_ballistics/CMakeLists.txt b/extensions/advanced_ballistics/CMakeLists.txt index 19b9fc41d9..51e709f6d2 100644 --- a/extensions/advanced_ballistics/CMakeLists.txt +++ b/extensions/advanced_ballistics/CMakeLists.txt @@ -1,9 +1,10 @@ set(ACE_EXTENSION_NAME "ace_advanced_ballistics") file(GLOB SOURCES *.h *.hpp *.c *.cpp) -add_library( ${ACE_EXTENSION_NAME} SHARED ${GLOBAL_SOURCES} ${SOURCES}) -add_dependencies(${ACE_EXTENSION_NAME} ace_common) -SET_TARGET_PROPERTIES(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "") +add_library( ${ACE_EXTENSION_NAME} SHARED ${SOURCES} ${GLOBAL_SOURCES}) +target_link_libraries(${ACE_EXTENSION_NAME} ace_common) +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "") +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES FOLDER Extensions) if(CMAKE_COMPILER_IS_GNUCXX) set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES LINK_SEARCH_START_STATIC 1) diff --git a/extensions/break_line/CMakeLists.txt b/extensions/break_line/CMakeLists.txt index 00a74d4c3a..5d29d295c8 100644 --- a/extensions/break_line/CMakeLists.txt +++ b/extensions/break_line/CMakeLists.txt @@ -1,9 +1,10 @@ set(ACE_EXTENSION_NAME "ace_break_line") file(GLOB SOURCES *.h *.hpp *.c *.cpp) -add_library( ${ACE_EXTENSION_NAME} SHARED ${GLOBAL_SOURCES} ${SOURCES}) -add_dependencies(${ACE_EXTENSION_NAME} ace_common) -SET_TARGET_PROPERTIES(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "") +add_library( ${ACE_EXTENSION_NAME} SHARED ${SOURCES} ${GLOBAL_SOURCES}) +target_link_libraries(${ACE_EXTENSION_NAME} ace_common) +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "") +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES FOLDER Extensions) if(CMAKE_COMPILER_IS_GNUCXX) set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES LINK_SEARCH_START_STATIC 1) diff --git a/extensions/break_line/ace_break_line.cpp b/extensions/break_line/ace_break_line.cpp index 2b253c05bc..440566b744 100644 --- a/extensions/break_line/ace_break_line.cpp +++ b/extensions/break_line/ace_break_line.cpp @@ -11,7 +11,7 @@ * String with line breaks */ -#include "ace_common.h" +#include "shared.hpp" #include <sstream> #include <vector> @@ -65,12 +65,14 @@ std::string addLineBreaks(const std::vector<std::string> &words) { #pragma warning( disable : 4996 ) void __stdcall RVExtension(char *output, int outputSize, const char *function) { + ZERO_OUTPUT(); if (!strcmp(function, "version")) { strncpy(output, ACE_FULL_VERSION_STR, outputSize); } else { strncpy(output, addLineBreaks(splitString(function)).c_str(), outputSize); output[outputSize - 1] = '\0'; } + EXTENSION_RETURN(); } #pragma warning( pop ) diff --git a/extensions/clipboard/ace_clipboard.cpp b/extensions/clipboard/ace_clipboard.cpp index 4809a14acf..41e3a5721f 100644 --- a/extensions/clipboard/ace_clipboard.cpp +++ b/extensions/clipboard/ace_clipboard.cpp @@ -9,7 +9,7 @@ * Returns: * None */ -#include "ace_common.h" +#include "shared.hpp" #include <vector> #include <string> @@ -23,12 +23,15 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { std::string cur_input(function); std::string result; - if (cur_input.length() < 1) - return; + ZERO_OUTPUT(); + + if (cur_input.length() < 1) { + EXTENSION_RETURN(); + } if (!strcmp(function, "version")) { strncpy(output, ACE_FULL_VERSION_STR, outputSize); - return; + EXTENSION_RETURN(); } #ifdef _WIN32 @@ -38,14 +41,14 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { if (!hClipboardData) { result = "GlobalAlloc() failed, GetLastError=" + GetLastError(); gClipboardData = ""; - return; + EXTENSION_RETURN(); } char *pClipboardData = (char *)GlobalLock(hClipboardData); if (!pClipboardData) { result = "GlobalLock() failed, GetLastError=" + GetLastError(); gClipboardData = ""; - return; + EXTENSION_RETURN(); } memcpy(pClipboardData, gClipboardData.c_str(), gClipboardData.length()); pClipboardData[gClipboardData.length() + 1] = 0x00; @@ -82,6 +85,6 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { #endif - + EXTENSION_RETURN(); } diff --git a/extensions/cmake/FindDirectX.cmake b/extensions/cmake/FindDirectX.cmake new file mode 100644 index 0000000000..69bf1d62e8 --- /dev/null +++ b/extensions/cmake/FindDirectX.cmake @@ -0,0 +1,215 @@ +# - try to find DirectX include directories and libraries +# +# Once done this will define: +# +# DirectX_XYZ_FOUND - system has the XYZ API +# DirectX_XYZ_INCLUDE_FOUND - system has the include for the XYZ API +# DirectX_XYZ_INCLUDE_DIR - include directory for the XYZ API +# DirectX_XYZ_LIBRARY - path/name for the XYZ library +# +# Where XYZ can be any of: +# +# DDRAW +# D3D +# D3DX +# D3D8 +# D3DX8 +# D3D9 +# D3DX9 +# D3D10 +# D3D10_1 +# D3DX10 +# D3D11 +# D3D11_1 +# D3D11_2 +# D3DX11 +# D2D1 +# + + +include (CheckIncludeFileCXX) +include (FindPackageMessage) + + +if (WIN32) + + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set (DirectX_ARCHITECTURE x64) + else () + set (DirectX_ARCHITECTURE x86) + endif () + + # Can't use "$ENV{ProgramFiles(x86)}" to avoid violating CMP0053. See + # http://public.kitware.com/pipermail/cmake-developers/2014-October/023190.html + set (ProgramFiles_x86 "ProgramFiles(x86)") + if ("$ENV{${ProgramFiles_x86}}") + set (ProgramFiles "$ENV{${ProgramFiles_x86}}") + else () + set (ProgramFiles "$ENV{ProgramFiles}") + endif () + + find_path (DirectX_ROOT_DIR + Include/d3d9.h + PATHS + "$ENV{DXSDK_DIR}" + "${ProgramFiles}/Microsoft DirectX SDK (June 2010)" + "${ProgramFiles}/Microsoft DirectX SDK (February 2010)" + "${ProgramFiles}/Microsoft DirectX SDK (March 2009)" + "${ProgramFiles}/Microsoft DirectX SDK (August 2008)" + "${ProgramFiles}/Microsoft DirectX SDK (June 2008)" + "${ProgramFiles}/Microsoft DirectX SDK (March 2008)" + "${ProgramFiles}/Microsoft DirectX SDK (November 2007)" + "${ProgramFiles}/Microsoft DirectX SDK (August 2007)" + "${ProgramFiles}/Microsoft DirectX SDK" + DOC "DirectX SDK root directory" + ) + if (DirectX_ROOT_DIR) + set (DirectX_INC_SEARCH_PATH "${DirectX_ROOT_DIR}/Include") + set (DirectX_LIB_SEARCH_PATH "${DirectX_ROOT_DIR}/Lib/${DirectX_ARCHITECTURE}") + set (DirectX_BIN_SEARCH_PATH "${DirectX_ROOT_DIR}/Utilities/bin/x86") + endif () + + # With VS 2011 and Windows 8 SDK, the DirectX SDK is included as part of + # the Windows SDK. + # + # See also: + # - http://msdn.microsoft.com/en-us/library/windows/desktop/ee663275.aspx + if (DEFINED MSVC_VERSION AND NOT ${MSVC_VERSION} LESS 1700) + set (USE_WINSDK_HEADERS TRUE) + endif () + + # Find a header in the DirectX SDK + macro (find_dxsdk_header var_name header) + set (include_dir_var "DirectX_${var_name}_INCLUDE_DIR") + set (include_found_var "DirectX_${var_name}_INCLUDE_FOUND") + find_path (${include_dir_var} ${header} + HINTS ${DirectX_INC_SEARCH_PATH} + DOC "The directory where ${header} resides" + CMAKE_FIND_ROOT_PATH_BOTH + ) + if (${include_dir_var}) + set (${include_found_var} TRUE) + find_package_message (${var_name}_INC "Found ${header} header: ${${include_dir_var}}/${header}" "[${${include_dir_var}}]") + endif () + mark_as_advanced (${include_found_var}) + endmacro () + + # Find a library in the DirectX SDK + macro (find_dxsdk_library var_name library) + # DirectX SDK + set (library_var "DirectX_${var_name}_LIBRARY") + find_library (${library_var} ${library} + HINTS ${DirectX_LIB_SEARCH_PATH} + DOC "The directory where ${library} resides" + CMAKE_FIND_ROOT_PATH_BOTH + ) + if (${library_var}) + find_package_message (${var_name}_LIB "Found ${library} library: ${${library_var}}" "[${${library_var}}]") + endif () + mark_as_advanced (${library_var}) + endmacro () + + # Find a header in the Windows SDK + macro (find_winsdk_header var_name header) + if (USE_WINSDK_HEADERS) + # Windows SDK + set (include_dir_var "DirectX_${var_name}_INCLUDE_DIR") + set (include_found_var "DirectX_${var_name}_INCLUDE_FOUND") + check_include_file_cxx (${header} ${include_found_var}) + set (${include_dir_var}) + mark_as_advanced (${include_found_var}) + else () + find_dxsdk_header (${var_name} ${header}) + endif () + endmacro () + + # Find a library in the Windows SDK + macro (find_winsdk_library var_name library) + if (USE_WINSDK_HEADERS) + # XXX: We currently just assume the library exists + set (library_var "DirectX_${var_name}_LIBRARY") + set (${library_var} ${library}) + mark_as_advanced (${library_var}) + else () + find_dxsdk_library (${var_name} ${library}) + endif () + endmacro () + + # Combine header and library variables into an API found variable + macro (find_combined var_name inc_var_name lib_var_name) + if (DirectX_${inc_var_name}_INCLUDE_FOUND AND DirectX_${lib_var_name}_LIBRARY) + set (DirectX_${var_name}_FOUND 1) + find_package_message (${var_name} "Found ${var_name} API" "[${DirectX_${lib_var_name}_LIBRARY}][${DirectX_${inc_var_name}_INCLUDE_DIR}]") + endif () + endmacro () + + find_winsdk_header (DDRAW ddraw.h) + find_winsdk_library (DDRAW ddraw) + find_combined (DDRAW DDRAW DDRAW) + + if (CMAKE_GENERATOR_TOOLSET MATCHES "_xp$") + # Windows 7 SDKs, used by XP toolset, do not include d3d.h + find_dxsdk_header (D3D d3d.h) + else () + find_winsdk_header (D3D d3d.h) + endif () + find_combined (D3D D3D DDRAW) + + find_dxsdk_header (D3DX d3dx.h) + find_combined (D3DX D3DX D3DX) + + find_dxsdk_header (D3D8 d3d8.h) + find_dxsdk_library (D3D8 d3d8) + find_combined (D3D8 D3D8 D3D8) + + find_dxsdk_header (D3DX8 d3dx8.h) + find_dxsdk_library (D3DX8 d3dx8) + find_combined (D3DX8 D3DX8 D3DX8) + + find_winsdk_header (D3D9 d3d9.h) + find_winsdk_library (D3D9 d3d9) + find_combined (D3D9 D3D9 D3D9) + + find_dxsdk_header (D3DX9 d3dx9.h) + find_dxsdk_library (D3DX9 d3dx9) + find_combined (D3DX9 D3DX9 D3DX9) + + find_winsdk_header (DXGI dxgi.h) + find_winsdk_header (DXGI1_2 dxgi1_2.h) + find_winsdk_header (DXGI1_3 dxgi1_3.h) + find_winsdk_library (DXGI dxgi) + + find_winsdk_header (D3D10 d3d10.h) + find_winsdk_library (D3D10 d3d10) + find_combined (D3D10 D3D10 D3D10) + + find_winsdk_header (D3D10_1 d3d10_1.h) + find_winsdk_library (D3D10_1 d3d10_1) + find_combined (D3D10_1 D3D10_1 D3D10_1) + + find_dxsdk_header (D3DX10 d3dx10.h) + find_dxsdk_library (D3DX10 d3dx10) + find_combined (D3DX10 D3DX10 D3DX10) + + find_winsdk_header (D3D11 d3d11.h) + find_winsdk_library (D3D11 d3d11) + find_combined (D3D11 D3D11 D3D11) + find_winsdk_header (D3D11_1 d3d11_1.h) + find_combined (D3D11_1 D3D11_1 D3D11) + find_winsdk_header (D3D11_2 d3d11_2.h) + find_combined (D3D11_2 D3D11_2 D3D11) + + find_dxsdk_header (D3DX11 d3dx11.h) + find_dxsdk_library (D3DX11 d3dx11) + find_combined (D3DX11 D3DX11 D3DX11) + + find_winsdk_header (D2D1 d2d1.h) + find_winsdk_library (D2D1 d2d1) + find_combined (D2D1 D2D1 D2D1) + + find_program (DirectX_FXC_EXECUTABLE fxc + HINTS ${DirectX_BIN_SEARCH_PATH} + DOC "Path to fxc.exe executable." + ) + +endif () \ No newline at end of file diff --git a/extensions/common/CMakeLists.txt b/extensions/common/CMakeLists.txt new file mode 100644 index 0000000000..620023ceb1 --- /dev/null +++ b/extensions/common/CMakeLists.txt @@ -0,0 +1,18 @@ +file(GLOB_RECURSE ACE_COMMON_SOURCES *.h *.hpp *.c *.cpp) + + +file(GLOB ACE_BASE_COMMON_SOURCES *.h *.hpp *.c *.cpp) +file(GLOB ACE_P3D_SOURCES p3d/*.h p3d/*.hpp p3d/*.c p3d/*.cpp) +file(GLOB ACE_PBO_SOURCES pbo/*.h pbo/*.hpp pbo/*.c pbo/*.cpp) +file(GLOB ACE_SIMULATION_SOURCES simulation/*.h simulation/*.hpp simulation/*.c simulation/*.cpp) +file(GLOB ACE_DIRECTX_SOURCES directx/*.h directx/*.hpp directx/*.c directx/*.cpp) +file(GLOB ACE_GLM_SOURCES glm/*.h glm/*.hpp glm/*.c glm/*.cpp) + +SOURCE_GROUP("common" FILES ${ACE_BASE_COMMON_SOURCES}) +SOURCE_GROUP("p3d" FILES ${ACE_P3D_SOURCES}) +SOURCE_GROUP("pbo" FILES ${ACE_PBO_SOURCES}) +SOURCE_GROUP("simulation" FILES ${ACE_SIMULATION_SOURCES}) +SOURCE_GROUP("directx" FILES ${ACE_DIRECTX_SOURCES}) +SOURCE_GROUP("glm" FILES ${ACE_GLM_SOURCES}) + +add_library(ace_common STATIC ${ACE_GLM_SOURCES} ${ACE_BASE_COMMON_SOURCES} ${ACE_P3D_SOURCES} ${ACE_PBO_SOURCES} ${ACE_SIMULATION_SOURCES} ${ACE_DIRECTX_SOURCES}) diff --git a/extensions/common/arguments.hpp b/extensions/common/arguments.hpp new file mode 100644 index 0000000000..70e942a241 --- /dev/null +++ b/extensions/common/arguments.hpp @@ -0,0 +1,90 @@ +#pragma once + +#include "shared.hpp" +#include "vector.hpp" + +#include <vector> +#include <string> + +namespace ace { + class argument_accessor { + public: + argument_accessor(const uint32_t index, const std::vector<std::string> & ar) : _index(index), _args(ar) { } + + const std::string & as_string() const { return _args[_index]; } + operator const std::string &() const { return as_string(); } + + float as_float() const { return atof(_args[_index].c_str()); } + operator float() const { return as_float(); } + + int as_int() const { return atoi(_args[_index].c_str()); } + operator int() const { return as_int(); } + + int as_uint32() const { return (uint32_t)atoi(_args[_index].c_str()); } + operator uint32_t() const { return as_uint32(); } + + ace::vector3<float> as_vector() const { + std::vector<std::string> t = ace::split(_args[_index], ';'); + return ace::vector3<float>(atof(t[0].c_str()), + atof(t[1].c_str()), + atof(t[2].c_str())); + } + operator ace::vector3<float>() const { return as_vector(); } + + protected: + const uint32_t _index; + const std::vector<std::string> & _args; + }; + + class arguments { + public: + arguments(const std::string & str) : _original(str) { + _args = ace::split(str, ','); + for (int i = 0; i < _args.size(); i++) { + _args[i] = trim(_args[i]); + } + } + + size_t size() const { return _args.size(); } + + const argument_accessor operator[] (int index) const { return argument_accessor(index, _args); } + + const std::string & as_string(uint32_t _index) const { return _args[_index]; } + float as_float(uint32_t _index) const { return atof(_args[_index].c_str()); } + int as_int(uint32_t _index) const { return atoi(_args[_index].c_str()); } + int as_uint32(uint32_t _index) const { return (uint32_t)atoi(_args[_index].c_str()); } + ace::vector3<float> as_vector(uint32_t _index) const { + std::vector<std::string> t = ace::split(_args[_index], ';'); + return ace::vector3<float>(atof(t[0].c_str()), + atof(t[1].c_str()), + atof(t[2].c_str())); + } + + const std::string & get() const { + return _original; + } + + std::string create(const std::string & command) const { + std::stringstream ss; + ss << command << ":"; + + for (auto & v : _args) { + ss << v << ","; + } + + // Remove the trailing , + std::string result = ss.str(); + result.erase(result.length()); + + return result; + } + static std::string create(const std::string & command, const arguments & args) { + return args.create(command); + } + + + protected: + std::vector<std::string> _args; + const std::string _original; + }; +} \ No newline at end of file diff --git a/extensions/common/directx/d3d_display.cpp b/extensions/common/directx/d3d_display.cpp new file mode 100644 index 0000000000..bfc7a0e013 --- /dev/null +++ b/extensions/common/directx/d3d_display.cpp @@ -0,0 +1,439 @@ +#ifdef USE_DIRECTX + +#include "shared.hpp" +#include "d3d_display.hpp" + +#include <TlHelp32.h> + +#include <thread> + +using namespace DirectX; + +namespace ace { + namespace debug { + + DWORD GetMainThreadId() { + const std::shared_ptr<void> hThreadSnapshot( + CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0), CloseHandle); + if (hThreadSnapshot.get() == INVALID_HANDLE_VALUE) { + throw std::runtime_error("GetMainThreadId failed"); + } + THREADENTRY32 tEntry; + tEntry.dwSize = sizeof(THREADENTRY32); + DWORD result = 0; + DWORD currentPID = GetCurrentProcessId(); + for (BOOL success = Thread32First(hThreadSnapshot.get(), &tEntry); + !result && success && GetLastError() != ERROR_NO_MORE_FILES; + success = Thread32Next(hThreadSnapshot.get(), &tEntry)) + { + if (tEntry.th32OwnerProcessID == currentPID) { + result = tEntry.th32ThreadID; + } + } + return result; + } + + d3d_display::d3d_display() : _fullscreen(false) {} + d3d_display::~d3d_display() {} + + bool d3d_display::render_thread(uint32_t w, uint32_t h, bool f) { + _render_thread = std::make_unique<d3d_display_worker>(this, d3d_display_worker_args(w, h, f) ); + return true; + } + + void d3d_display::render_worker(d3d_display_worker_args args) { + { + create(args.width, args.height, args.fullscreen); + init(); + } + run(); + } + + bool d3d_display::run() { + MSG msg = { 0 }; + + while (WM_QUIT != msg.message) { + if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } else { + render(); + } + } + + return true; + } + + bool d3d_display::init() { + + std::lock_guard<std::mutex> _lock(_render_lock); + + HRESULT hr = S_OK; + RECT rc; + + GetClientRect(_hWnd, &rc); + UINT width = rc.right - rc.left; + UINT height = rc.bottom - rc.top; + UINT createDeviceFlags = 0; +#ifdef _DEBUG + createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; +#endif + + D3D_DRIVER_TYPE driverTypes[] = + { + D3D_DRIVER_TYPE_HARDWARE, + D3D_DRIVER_TYPE_WARP, + D3D_DRIVER_TYPE_REFERENCE, + }; + UINT numDriverTypes = ARRAYSIZE(driverTypes); + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, + }; + UINT numFeatureLevels = ARRAYSIZE(featureLevels); + + DXGI_SWAP_CHAIN_DESC sd; + ZeroMemory(&sd, sizeof(sd)); + sd.BufferCount = 1; + sd.BufferDesc.Width = width; + sd.BufferDesc.Height = height; + sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + sd.BufferDesc.RefreshRate.Numerator = 60; + sd.BufferDesc.RefreshRate.Denominator = 1; + sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + sd.OutputWindow = _hWnd; + sd.SampleDesc.Count = 1; + sd.SampleDesc.Quality = 0; + sd.Windowed = _fullscreen ? FALSE : TRUE; + + for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) + { + _driverType = driverTypes[driverTypeIndex]; + hr = D3D11CreateDeviceAndSwapChain(nullptr, _driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, + D3D11_SDK_VERSION, &sd, &_pSwapChain, &_pd3dDevice, &_featureLevel, &_pImmediateContext); + if (SUCCEEDED(hr)) + break; + } + if (FAILED(hr)) + return false; + + // Create a render target view + ID3D11Texture2D* pBackBuffer = nullptr; + hr = _pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer); + if (FAILED(hr)) + return false; + + hr = _pd3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &_pRenderTargetView); + pBackBuffer->Release(); + if (FAILED(hr)) + return false; + + // Create depth stencil texture + D3D11_TEXTURE2D_DESC descDepth; + ZeroMemory(&descDepth, sizeof(descDepth)); + descDepth.Width = width; + descDepth.Height = height; + descDepth.MipLevels = 1; + descDepth.ArraySize = 1; + descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; + descDepth.SampleDesc.Count = 1; + descDepth.SampleDesc.Quality = 0; + descDepth.Usage = D3D11_USAGE_DEFAULT; + descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL; + descDepth.CPUAccessFlags = 0; + descDepth.MiscFlags = 0; + hr = _pd3dDevice->CreateTexture2D(&descDepth, nullptr, &_pDepthStencil); + if (FAILED(hr)) + return false; + + // Create the depth stencil view + D3D11_DEPTH_STENCIL_VIEW_DESC descDSV; + ZeroMemory(&descDSV, sizeof(descDSV)); + descDSV.Format = descDepth.Format; + descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + descDSV.Texture2D.MipSlice = 0; + hr = _pd3dDevice->CreateDepthStencilView(_pDepthStencil, &descDSV, &_pDepthStencilView); + if (FAILED(hr)) + return false; + + _pImmediateContext->OMSetRenderTargets(1, &_pRenderTargetView, _pDepthStencilView); + + // Setup the viewport + D3D11_VIEWPORT vp; + vp.Width = (FLOAT)width; + vp.Height = (FLOAT)height; + vp.MinDepth = 0.0f; + vp.MaxDepth = 1.0f; + vp.TopLeftX = 0; + vp.TopLeftY = 0; + _pImmediateContext->RSSetViewports(1, &vp); + + XMStoreFloat4x4(&_World, XMMatrixIdentity()); + XMStoreFloat4x4(&_View, XMMatrixLookAtLH(XMLoadFloat4(&_camera.camPosition), XMLoadFloat4(&_camera.camTarget), XMLoadFloat4(&_camera.camUp))); + XMStoreFloat4x4(&_Projection, XMMatrixPerspectiveFovLH(XM_PIDIV4, width / (FLOAT)height, 0.01f, 100.0f)); + + init_input(); + + return true; + } + + bool d3d_display::init_input() { + RAWINPUTDEVICE Rid[2]; + + Rid[0].usUsagePage = 0x01; // magic numbers + Rid[0].usUsage = 0x02; // magically means mouse + Rid[0].dwFlags = 0; // (use this if you DO NOT WANT to capture mouse) + //Rid[0].dwFlags = RIDEV_CAPTUREMOUSE | RIDEV_NOLEGACY ; // (use this to CAPTURE MOUSE) + Rid[0].hwndTarget = _hWnd; + + Rid[1].usUsagePage = 0x01; // magic numbers + Rid[1].usUsage = 0x06; // magically means keyboard + Rid[1].dwFlags = 0; // use RIDEV_NOHOTKEYS for no winkey + Rid[1].hwndTarget = _hWnd; + + if (!RegisterRawInputDevices(Rid, 2, sizeof(Rid[0]))) { + LOG(ERROR) << "Could not register raw input devices. "; + exit(1); + } + } + + bool d3d_display::create(uint32_t width = 1024, uint32_t height = 768, bool fullscreen = false) { + std::lock_guard<std::mutex> _lock(_render_lock); + + _fullscreen = fullscreen; + + WNDCLASSEXW wcex; + wcex.cbSize = sizeof(WNDCLASSEXW); + wcex.style = CS_HREDRAW | CS_VREDRAW; + wcex.lpfnWndProc = (WNDPROC)&ace::debug::d3d_display::wndproc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = (HINSTANCE)GetCurrentProcess(); + //wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_SAMPLE1); + //wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); + wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wcex.lpszMenuName = nullptr; + wcex.lpszClassName = L"ACE3BaseDisplayClass"; + //wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SAMPLE1); + if (!RegisterClassExW(&wcex)) { + return false; + } + + // Create window + _hInst = (HINSTANCE)GetCurrentProcess(); + RECT rc = { 0, 0, width, height }; + AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, FALSE); + _hWnd = CreateWindowW(L"ACE3BaseDisplayClass", L"ACE3 D3D Render", WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, nullptr, nullptr, _hInst, + nullptr); + + if (!_hWnd) { + return false; + } + + // Attach our input to the master input + //AttachThreadInput(GetCurrentThreadId(), GetMainThraedId()); + + SetWindowLongPtr(_hWnd, GWLP_USERDATA, (LONG)this); + + ShowWindow(_hWnd, 5); + + return true; + } + + bool d3d_display::destroy() { + if (_pImmediateContext) _pImmediateContext->ClearState(); + + if (_pBatchInputLayout) _pBatchInputLayout->Release(); + + if (_pTextureRV1) _pTextureRV1->Release(); + if (_pTextureRV2) _pTextureRV2->Release(); + + if (_pDepthStencilView) _pDepthStencilView->Release(); + if (_pDepthStencil) _pDepthStencil->Release(); + if (_pRenderTargetView) _pRenderTargetView->Release(); + if (_pSwapChain) _pSwapChain->Release(); + if (_pImmediateContext) _pImmediateContext->Release(); + if (_pd3dDevice) _pd3dDevice->Release(); + + return true; + } + + bool d3d_display::render() { + // Update our time + static float t = 0.0f; + static float dt = 0.f; + if (_driverType == D3D_DRIVER_TYPE_REFERENCE) { + t += (float)XM_PI * 0.0125f; + } else { + static uint64_t dwTimeStart = 0; + static uint64_t dwTimeLast = 0; + uint64_t dwTimeCur = GetTickCount64(); + if (dwTimeStart == 0) + dwTimeStart = dwTimeCur; + t = (dwTimeCur - dwTimeStart) / 1000.0f; + dt = (dwTimeCur - dwTimeLast) / 1000.0f; + dwTimeLast = dwTimeCur; + } + + { + std::lock_guard<std::mutex> _lock(_render_lock); + + _pImmediateContext->ClearRenderTargetView(_pRenderTargetView, Colors::MidnightBlue); + _pImmediateContext->ClearDepthStencilView(_pDepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0); + + update_camera(); + step(); + + _pSwapChain->Present(0, 0); + } + + return true; + } + + bool d3d_display::step() { + return true; + } + + void d3d_display::_move_camera(ace::vector3<float> direction) { + + } + void d3d_display::_rotate_camera(ace::vector3<float> direction) { + + } + void d3d_display::update_camera() { + XMVECTOR DefaultForward, DefaultRight, camPosition; + + DefaultForward = XMLoadFloat4(&_camera.DefaultForward); + DefaultRight = XMLoadFloat4(&_camera.DefaultRight); + camPosition = XMLoadFloat4(&_camera.camPosition); + + XMMATRIX camRotationMatrix = XMMatrixRotationRollPitchYaw(_camera.camPitch, _camera.camYaw, 0); + XMVECTOR camTarget = XMVector3TransformCoord(DefaultForward, camRotationMatrix); + camTarget = XMVector3Normalize(camTarget); + + XMVECTOR camRight = XMVector3TransformCoord(DefaultRight, camRotationMatrix); + XMVECTOR camForward = XMVector3TransformCoord(DefaultForward, camRotationMatrix); + XMVECTOR camUp = XMVector3Cross(camForward, camRight); + + camPosition += _camera.moveLeftRight * camRight; + camPosition += _camera.moveBackForward * camForward; + XMStoreFloat4(&_camera.camPosition, camPosition); + + _camera.moveLeftRight = 0.0f; + _camera.moveBackForward = 0.0f; + + camTarget = camPosition + camTarget; + + XMStoreFloat4x4(&_View, XMMatrixLookAtLH(camPosition, camTarget, camUp)); + } + + LRESULT CALLBACK d3d_display::_wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + PAINTSTRUCT ps; + HDC hdc; + + switch (message) { + case WM_INPUT: { + UINT dwSize; + if (GetActiveWindow() != _hWnd) { + return DefWindowProc(hWnd, message, wParam, lParam); + } + GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, + sizeof(RAWINPUTHEADER)); + LPBYTE lpb = new BYTE[dwSize]; + if (lpb == NULL) { + return 0; + } + + int readSize = GetRawInputData((HRAWINPUT)lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)); + + if (readSize != dwSize) + break; + + RAWINPUT* raw = (RAWINPUT*)lpb; + + float speed = 0.5f; + + if (raw->header.dwType == RIM_TYPEKEYBOARD) { + switch (raw->data.keyboard.VKey) { + case VK_SPACE: { + XMStoreFloat4(&_camera.camPosition, XMVectorSet(0, 0, 0, 0)); + break; + } + // Camera Movement + case 0x57: case VK_NUMPAD8: + case VK_UP: { + _camera.moveBackForward += speed; + break; + } + case 0x53: case VK_NUMPAD2: + case VK_DOWN: { + _camera.moveBackForward -= speed; + break; + } + case 0x41: case VK_NUMPAD4: + case VK_LEFT: { + _camera.moveLeftRight -= speed; + break; + } + case 0x44: case VK_NUMPAD6: + case VK_RIGHT: { + _camera.moveLeftRight += speed; + break; + } + // Numpad Movement + case VK_NUMPAD5: { + XMStoreFloat4(&_camera.camPosition, XMVectorSet(0, 0, 0, 0)); + break; + } + } + } + else if (raw->header.dwType == RIM_TYPEMOUSE) { + RAWMOUSE mouseCurrState = raw->data.mouse; + + if ((mouseCurrState.lLastX != _last_mouse_state.lLastY) || (mouseCurrState.lLastX != _last_mouse_state.lLastY)) + { + _camera.camYaw += mouseCurrState.lLastX * 0.005f; + _camera.camPitch += mouseCurrState.lLastY * 0.005f; + _last_mouse_state = mouseCurrState; + } + + } + + delete[] lpb; + return 0; + } + + case WM_PAINT: + hdc = BeginPaint(hWnd, &ps); + EndPaint(hWnd, &ps); + break; + + case WM_DESTROY: + PostQuitMessage(0); + + break; + default: + return DefWindowProc(hWnd, message, wParam, lParam); + } + + return 0; + } + LRESULT CALLBACK d3d_display::wndproc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + LONG data; + data = GetWindowLongPtr(hWnd, GWLP_USERDATA); + if (data) { + return ((d3d_display*)data)->_wndproc(hWnd, message, wParam, lParam); + } else { + return DefWindowProc(hWnd, message, wParam, lParam); + } + } + }; + + +}; + +#endif \ No newline at end of file diff --git a/extensions/common/directx/d3d_display.hpp b/extensions/common/directx/d3d_display.hpp new file mode 100644 index 0000000000..b10e8ef070 --- /dev/null +++ b/extensions/common/directx/d3d_display.hpp @@ -0,0 +1,130 @@ +#pragma once + +#ifdef USE_DIRECTX + +#include <windows.h> +#include <d3d11_1.h> +#include <directxcolors.h> +#include <DirectXMath.h> + +#include <thread> +#include <memory> +#include <mutex> + +#include "singleton.hpp" +#include "vector.hpp" + +#define IDI_ACE_DEBUG 666 + +namespace ace { + namespace debug { + + __declspec(align(16)) + struct camera_movement { + camera_movement() { + XMStoreFloat4(&DefaultForward, DirectX::XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f)); + XMStoreFloat4(&DefaultRight, DirectX::XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f)); + XMStoreFloat4(&camForward, DirectX::XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f)); + XMStoreFloat4(&camRight, DirectX::XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f)); + + camYaw = 0.0f; + camPitch = 0.0f; + + moveLeftRight = 0.0f; + moveBackForward = 0.0f; + + XMStoreFloat4(&camPosition, DirectX::XMVectorSet(0.0f, 12.0f, 6.0f, 0.0f)); + XMStoreFloat4(&camTarget, DirectX::XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f)); + XMStoreFloat4(&camUp, DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f)); + } + + DirectX::XMFLOAT4 DefaultForward; + DirectX::XMFLOAT4 DefaultRight; + DirectX::XMFLOAT4 camForward; + DirectX::XMFLOAT4 camRight; + + DirectX::XMFLOAT4X4 camRotationMatrix; + DirectX::XMFLOAT4X4 groundWorld; + + float moveLeftRight; + float moveBackForward; + + float camYaw; + float camPitch; + + DirectX::XMFLOAT4 camPosition; + DirectX::XMFLOAT4 camTarget; + DirectX::XMFLOAT4 camUp; + }; + + struct d3d_display_worker; + struct d3d_display_worker_args; + __declspec(align(16)) + class d3d_display { + public: + d3d_display(); + ~d3d_display(); + + virtual bool run(); + virtual bool render(); + virtual bool render_thread(uint32_t, uint32_t, bool); + + virtual void update_camera(); + virtual bool step(); + + virtual bool create(uint32_t, uint32_t, bool); + virtual bool init(); + virtual bool init_input(); + + virtual bool destroy(); + + void render_worker(d3d_display_worker_args); + + static LRESULT CALLBACK wndproc(HWND, UINT, WPARAM, LPARAM); + LRESULT CALLBACK _wndproc(HWND, UINT, WPARAM, LPARAM); + protected: + void _move_camera(ace::vector3<float>); + void _rotate_camera(ace::vector3<float>); + + std::unique_ptr<d3d_display_worker> _render_thread; + std::mutex _render_lock; + + bool _fullscreen; + HINSTANCE _hInst = nullptr; + HWND _hWnd = nullptr; + D3D_DRIVER_TYPE _driverType = D3D_DRIVER_TYPE_NULL; + D3D_FEATURE_LEVEL _featureLevel = D3D_FEATURE_LEVEL_11_0; + ID3D11Device* _pd3dDevice = nullptr; + ID3D11DeviceContext* _pImmediateContext = nullptr; + IDXGISwapChain* _pSwapChain = nullptr; + ID3D11RenderTargetView* _pRenderTargetView = nullptr; + ID3D11Texture2D* _pDepthStencil = nullptr; + ID3D11DepthStencilView* _pDepthStencilView = nullptr; + + ID3D11ShaderResourceView* _pTextureRV1 = nullptr; + ID3D11ShaderResourceView* _pTextureRV2 = nullptr; + ID3D11InputLayout* _pBatchInputLayout = nullptr; + + DirectX::XMFLOAT4X4 _World; + DirectX::XMFLOAT4X4 _View; + DirectX::XMFLOAT4X4 _Projection; + + RAWMOUSE _last_mouse_state; + camera_movement _camera; + + }; + struct d3d_display_worker_args { + d3d_display_worker_args(uint32_t w, uint32_t h, bool f) : width(w), height(h), fullscreen(f) {} + uint32_t width; + uint32_t height; + bool fullscreen; + }; + struct d3d_display_worker { + d3d_display_worker(d3d_display * obj, d3d_display_worker_args args) : thread(&ace::debug::d3d_display::render_worker, obj, args) {} + ~d3d_display_worker() { thread.join(); } + std::thread thread; + }; + }; +}; + +#endif \ No newline at end of file diff --git a/extensions/common/dispatch.hpp b/extensions/common/dispatch.hpp new file mode 100644 index 0000000000..0a37824b83 --- /dev/null +++ b/extensions/common/dispatch.hpp @@ -0,0 +1,153 @@ +#pragma once + +#include <thread> +#include <mutex> +#include <atomic> +#include <queue> + +#include "shared.hpp" +#include "arguments.hpp" +#include "singleton.hpp" + +namespace ace { + class dispatcher { + public: + dispatcher() : _ready(true) {} + + virtual bool call(const std::string & name_, const arguments & args_, std::string & result_) { + if (_methods.find(name_) == _methods.end()) { + // @TODO: Exceptions + return false; + } + return _methods[name_](args_, result_); + } + + bool add(const std::string & name_, std::function<bool(const arguments &, std::string &)> func_) { + if (_methods.find(name_) != _methods.end()) { + // @TODO: Exceptions + return false; + } + _methods[name_] = func_; + + return true; + } + + bool ready() const { return _ready; } + void ready(bool r) { _ready.exchange(r); } + protected: + std::unordered_map < std::string, std::function<bool(const arguments &, std::string &)> > _methods; + std::atomic_bool _ready; + }; + class dispatch : public dispatcher, public singleton<dispatch> { }; + + struct dispatch_message { + dispatch_message(const std::string & command_, const arguments & args_, const uint64_t id_) : command(command_), args(args_), id(id_) {} + std::string command; + arguments args; + uint64_t id; + }; + struct dispatch_result { + dispatch_result() {} + dispatch_result(const std::string &res, const uint64_t id_) : message(res), id(id_) {} + std::string message; + uint64_t id; + }; + + class threaded_dispatcher : public dispatcher { + public: + threaded_dispatcher() : _stop(false), _worker(&ace::threaded_dispatcher::monitor, this) { + + } + ~threaded_dispatcher() {} + + bool call(const std::string & name_, const arguments & args_, std::string & result_, bool threaded) { + if (_methods.find(name_) == _methods.end()) { + // @TODO: Exceptions + return false; + } + if (threaded) { + std::lock_guard<std::mutex> lock(_messages_lock); + _messages.push(dispatch_message(name_, args_, _message_id)); + + // @TODO: We should provide an interface for this serialization. + std::stringstream ss; + ss << "[\"result_id\", \"" << _message_id << "\" ]"; + result_ = ss.str(); + + _message_id = _message_id + 1; + } else { +#ifdef _DEBUG + if (name_ != "fetch_result") { + LOG(TRACE) << "dispatch[immediate]:\t[" << name_ << "] { " << args_.get() << " }"; + } +#endif + return dispatcher::call(name_, args_, result_); + } + + return true; + } + bool call(const std::string & name_, const arguments & args_, std::string & result_) override { + return call(name_, args_, result_, false); + } + + void push_result(const dispatch_result & result) { + { + std::lock_guard<std::mutex> lock(_results_lock); + _results.push(result); + } + } + void push_result(const std::string & result) { + push_result(dispatch_result(result, -1)); + } + void stop() { + std::lock_guard<std::mutex> lock(_messages_lock); + _stop = true; + } + protected: + void monitor() { + _ready = false; + while (!_stop) { + { + std::lock_guard<std::mutex> lock(_messages_lock); + while (!_messages.empty()) { + if (_ready) { + dispatch_result result; + dispatch_message _message = std::move(_messages.front()); + _messages.pop(); + + result.id = _message.id; + result.message.resize(4096); +#ifdef _DEBUG + if (_message.command != "fetch_result") { + LOG(TRACE) << "dispatch[threaded]:\t[" << _message.command << "]"; + if (_message.args.size() > 0) { + // LOG(TRACE) << "\t{ " << _messages.front().args.get() << " }"; + } + } +#endif + dispatcher::call(_message.command, _message.args, result.message); + { + std::lock_guard<std::mutex> lock(_results_lock); + _results.push(result); + } + + + } + } + } + sleep(5); + } + } + std::atomic_bool _stop; + std::queue<dispatch_result> _results; + std::mutex _results_lock; + + std::queue<dispatch_message> _messages; + std::mutex _messages_lock; + + std::thread _worker; + + uint64_t _message_id; + }; + class threaded_dispatch : public threaded_dispatcher, public singleton<dispatch> { }; +}; \ No newline at end of file diff --git a/extensions/common/easyloggingc++.hpp b/extensions/common/easyloggingc++.hpp new file mode 100644 index 0000000000..3a5455c4d0 --- /dev/null +++ b/extensions/common/easyloggingc++.hpp @@ -0,0 +1,6718 @@ +// +// Easylogging++ v9.80 +// Single-header only, cross-platform logging library for C++ applications +// +// Copyright (c) 2015 muflihun.com +// +// This library is released under the MIT Licence. +// http://easylogging.muflihun.com/licence.php +// +// easylogging@muflihun.com +// +// https://github.com/easylogging/easyloggingpp +// http://easylogging.muflihun.com +// http://muflihun.com +// +#ifndef EASYLOGGINGPP_H +#define EASYLOGGINGPP_H +// Compilers and C++0x/C++11 Evaluation +#if defined(__GNUC__) +# define ELPP_COMPILER_GCC 1 +# define ELPP_GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) +# define ELPP_CXX0X 1 +# elif(ELPP_GCC_VERSION >= 40801) +# define ELPP_CXX11 1 +# endif // defined(__GXX_EXPERIMENTAL_CXX0X__) +#endif // defined(__GNUC__) +// Visual C++ +#if defined(_MSC_VER) +# define ELPP_COMPILER_MSVC 1 +# define ELPP_CRT_DBG_WARNINGS 1 +# if (_MSC_VER == 1600) +# define ELPP_CXX0X 1 +# elif(_MSC_VER >= 1700) +# define ELPP_CXX11 1 +# endif // (_MSC_VER == 1600) +#endif // defined(_MSC_VER) +// Clang++ +#if defined(__clang__) && (__clang__ == 1) +# define ELPP_COMPILER_CLANG 1 +# define ELPP_CLANG_VERSION (__clang_major__ * 10000 \ + + __clang_minor__ * 100 \ + + __clang_patchlevel__) +# if (ELPP_CLANG_VERSION >= 30300) +# define ELPP_CXX11 1 +# endif // (ELPP_CLANG_VERSION >= 30300) +#endif // defined(__clang__) && (__clang__ == 1) +// MinGW +#if defined(__MINGW32__) || defined(__MINGW64__) +# define ELPP_MINGW 1 +#endif // defined(__MINGW32__) || defined(__MINGW64__) +// Cygwin +#if defined(__CYGWIN__) && (__CYGWIN__ == 1) +# define ELPP_CYGWIN 1 +#endif // defined(__CYGWIN__) && (__CYGWIN__ == 1) +// Intel C++ +#if defined(__INTEL_COMPILER) +# define ELPP_COMPILER_INTEL 1 +#endif +// Operating System Evaluation +// Windows +#if defined(_WIN32) || defined(_WIN64) +# define ELPP_OS_WINDOWS 1 +#endif // defined(_WIN32) || defined(_WIN64) +// Linux +#if (defined(__linux) || defined(__linux__)) +# define ELPP_OS_LINUX 1 +#endif // (defined(__linux) || defined(__linux__)) +// Mac +#if defined(__APPLE__) +# define ELPP_OS_MAC 1 +#endif // defined(__APPLE__) +// FreeBSD +#if defined(__FreeBSD__) +# define ELPP_OS_FREEBSD 1 +#endif +// Solaris +#if defined(__sun) +# define ELPP_OS_SOLARIS 1 +#endif +// Unix +#if ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_SOLARIS) && (!ELPP_OS_WINDOWS)) +# define ELPP_OS_UNIX 1 +#endif // ((ELPP_OS_LINUX || ELPP_OS_MAC || ELPP_OS_FREEBSD || ELPP_OS_SOLARIS) && (!ELPP_OS_WINDOWS)) +// Android +#if defined(__ANDROID__) +# define ELPP_OS_ANDROID 1 +#endif // defined(__ANDROID__) +// Evaluating Cygwin as *nix OS +#if !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN +# undef ELPP_OS_UNIX +# undef ELPP_OS_LINUX +# define ELPP_OS_UNIX 1 +# define ELPP_OS_LINUX 1 +#endif // !ELPP_OS_UNIX && !ELPP_OS_WINDOWS && ELPP_CYGWIN +#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_INFO) +# define ELPP_INTERNAL_DEBUGGING_OUT_INFO std::cout +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +#if !defined(ELPP_INTERNAL_DEBUGGING_OUT_ERROR) +# define ELPP_INTERNAL_DEBUGGING_OUT_ERROR std::cerr +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +#if !defined(ELPP_INTERNAL_DEBUGGING_ENDL) +# define ELPP_INTERNAL_DEBUGGING_ENDL std::endl +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +#if !defined(ELPP_INTERNAL_DEBUGGING_MSG) +# define ELPP_INTERNAL_DEBUGGING_MSG(msg) msg +#endif // !defined(ELPP_INTERNAL_DEBUGGING_OUT) +// Internal Assertions and errors +#if !defined(ELPP_DISABLE_ASSERT) +# if (defined(ELPP_DEBUG_ASSERT_FAILURE)) +# define ELPP_ASSERT(expr, msg) if (!(expr)) { \ + std::stringstream internalInfoStream; internalInfoStream << msg; \ + ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ + << "EASYLOGGING++ ASSERTION FAILED (LINE: " << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" \ + << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" << ELPP_INTERNAL_DEBUGGING_ENDL; base::utils::abort(1, \ + "ELPP Assertion failure, please define ELPP_DEBUG_ASSERT_FAILURE"); } +# else +# define ELPP_ASSERT(expr, msg) if (!(expr)) { \ + std::stringstream internalInfoStream; internalInfoStream << msg; \ + ELPP_INTERNAL_DEBUGGING_OUT_ERROR\ + << "ASSERTION FAILURE FROM EASYLOGGING++ (LINE: " \ + << __LINE__ << ") [" #expr << "] WITH MESSAGE \"" << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << "\"" \ + << ELPP_INTERNAL_DEBUGGING_ENDL; } +# endif // (defined(ELPP_DEBUG_ASSERT_FAILURE)) +#else +# define ELPP_ASSERT(x, y) +#endif //(!defined(ELPP_DISABLE_ASSERT) +#if ELPP_COMPILER_MSVC +# define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ + { char buff[256]; strerror_s(buff, 256, errno); \ + ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << buff << " [" << errno << "]";} (void)0 +#else +# define ELPP_INTERNAL_DEBUGGING_WRITE_PERROR \ + ELPP_INTERNAL_DEBUGGING_OUT_ERROR << ": " << strerror(errno) << " [" << errno << "]"; (void)0 +#endif // ELPP_COMPILER_MSVC +#if defined(ELPP_DEBUG_ERRORS) +# if !defined(ELPP_INTERNAL_ERROR) +# define ELPP_INTERNAL_ERROR(msg, pe) { \ + std::stringstream internalInfoStream; internalInfoStream << "<ERROR> " << msg; \ + ELPP_INTERNAL_DEBUGGING_OUT_ERROR \ + << "ERROR FROM EASYLOGGING++ (LINE: " << __LINE__ << ") " \ + << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) << ELPP_INTERNAL_DEBUGGING_ENDL; \ + if (pe) { ELPP_INTERNAL_DEBUGGING_OUT_ERROR << " "; ELPP_INTERNAL_DEBUGGING_WRITE_PERROR; }} (void)0 +# endif +#else +# undef ELPP_INTERNAL_INFO +# define ELPP_INTERNAL_ERROR(msg, pe) +#endif // defined(ELPP_DEBUG_ERRORS) +#if (defined(ELPP_DEBUG_INFO)) +# if !(defined(ELPP_INTERNAL_INFO_LEVEL)) +# define ELPP_INTERNAL_INFO_LEVEL 9 +# endif // !(defined(ELPP_INTERNAL_INFO_LEVEL)) +# if !defined(ELPP_INTERNAL_INFO) +# define ELPP_INTERNAL_INFO(lvl, msg) { if (lvl <= ELPP_INTERNAL_INFO_LEVEL) { \ + std::stringstream internalInfoStream; internalInfoStream << "<INFO> " << msg; \ + ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStream.str()) \ + << ELPP_INTERNAL_DEBUGGING_ENDL; }} +# endif +#else +# undef ELPP_INTERNAL_INFO +# define ELPP_INTERNAL_INFO(lvl, msg) +#endif // (defined(ELPP_DEBUG_INFO)) +#if defined(ELPP_STACKTRACE_ON_CRASH) +# if (ELPP_COMPILER_GCC && !ELPP_MINGW) +# define ELPP_STACKTRACE 1 +# else +# if ELPP_COMPILER_MSVC +# pragma message("Stack trace not available for this compiler") +# else +# warning "Stack trace not available for this compiler"; +# endif // ELPP_COMPILER_MSVC +# endif // ELPP_COMPILER_GCC +#endif // (defined(ELPP_STACKTRACE_ON_CRASH)) +// Miscellaneous macros +#define ELPP_UNUSED(x) (void)x +#if ELPP_OS_UNIX +// Log file permissions for unix-based systems +# define ELPP_LOG_PERMS S_IRUSR | S_IWUSR | S_IXUSR | S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IXOTH +#endif // ELPP_OS_UNIX +#if defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC +# if defined(ELPP_EXPORT_SYMBOLS) +# define ELPP_EXPORT __declspec(dllexport) +# else +# define ELPP_EXPORT __declspec(dllimport) +# endif // defined(ELPP_EXPORT_SYMBOLS) +#else +# define ELPP_EXPORT +#endif // defined(ELPP_AS_DLL) && ELPP_COMPILER_MSVC +// Some special functions that are VC++ specific +#undef STRTOK +#undef STRERROR +#undef STRCAT +#undef STRCPY +#if ELPP_CRT_DBG_WARNINGS +# define STRTOK(a, b, c) strtok_s(a, b, c) +# define STRERROR(a, b, c) strerror_s(a, b, c) +# define STRCAT(a, b, len) strcat_s(a, len, b) +# define STRCPY(a, b, len) strcpy_s(a, len, b) +#else +# define STRTOK(a, b, c) strtok(a, b) +# define STRERROR(a, b, c) strerror(c) +# define STRCAT(a, b, len) strcat(a, b) +# define STRCPY(a, b, len) strcpy(a, b) +#endif +// Compiler specific support evaluations +#if (!ELPP_MINGW && !ELPP_COMPILER_CLANG) || defined(ELPP_FORCE_USE_STD_THREAD) +# define ELPP_USE_STD_THREADING 1 +#endif // (!ELPP_MINGW && !ELPP_COMPILER_CLANG) || defined(ELPP_FORCE_USE_STD_THREAD) +#undef ELPP_FINAL +#if ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) +# define ELPP_FINAL +#else +# define ELPP_FINAL final +#endif // ELPP_COMPILER_INTEL || (ELPP_GCC_VERSION < 40702) +#if defined(ELPP_EXPERIMENTAL_ASYNC) +# define ELPP_ASYNC_LOGGING 1 +#else +# define ELPP_ASYNC_LOGGING 0 +#endif // defined(ELPP_EXPERIMENTAL_ASYNC) +#if defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING +# define ELPP_THREADING_ENABLED 1 +#endif // defined(ELPP_THREAD_SAFE) || ELPP_ASYNC_LOGGING +// Function macro ELPP_FUNC +#undef ELPP_FUNC +#if ELPP_COMPILER_MSVC // Visual C++ +# define ELPP_FUNC __FUNCSIG__ +#elif ELPP_COMPILER_GCC // GCC +# define ELPP_FUNC __PRETTY_FUNCTION__ +#elif ELPP_COMPILER_INTEL // Intel C++ +# define ELPP_FUNC __PRETTY_FUNCTION__ +#elif ELPP_COMPILER_CLANG // Clang++ +# define ELPP_FUNC __PRETTY_FUNCTION__ +#else +# if defined(__func__) +# define ELPP_FUNC __func__ +# else +# define ELPP_FUNC "" +# endif // defined(__func__) +#endif // defined(_MSC_VER) +#undef ELPP_VARIADIC_TEMPLATES_SUPPORTED +// Keep following line commented until features are fixed +#if ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800) +# define ELPP_VARIADIC_TEMPLATES_SUPPORTED 1 +#endif // ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800) +// Logging Enable/Disable macros +#if (!defined(ELPP_DISABLE_LOGS)) +# define ELPP_LOGGING_ENABLED 1 +#endif // (!defined(ELPP_DISABLE_LOGS)) +#if (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG)))) +# define ELPP_DEBUG_LOG 1 +#else +# define ELPP_DEBUG_LOG 0 +#endif // (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG)))) +#if (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_INFO_LOG 1 +#else +# define ELPP_INFO_LOG 0 +#endif // (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_WARNING_LOG 1 +#else +# define ELPP_WARNING_LOG 0 +#endif // (!defined(ELPP_DISABLE_WARNING_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_ERROR_LOG 1 +#else +# define ELPP_ERROR_LOG 0 +#endif // (!defined(ELPP_DISABLE_ERROR_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_FATAL_LOG 1 +#else +# define ELPP_FATAL_LOG 0 +#endif // (!defined(ELPP_DISABLE_FATAL_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_TRACE_LOG 1 +#else +# define ELPP_TRACE_LOG 0 +#endif // (!defined(ELPP_DISABLE_TRACE_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) +# define ELPP_VERBOSE_LOG 1 +#else +# define ELPP_VERBOSE_LOG 0 +#endif // (!defined(ELPP_DISABLE_VERBOSE_LOGS) && (ELPP_LOGGING_ENABLED)) +#if (!(ELPP_CXX0X || ELPP_CXX11)) +# error "Easylogging++ 9.0+ is only compatible with C++0x (or higher) compliant compiler" +#endif // (!(ELPP_CXX0X || ELPP_CXX11)) +// Headers +#if defined(ELPP_SYSLOG) +# include <syslog.h> +#endif // defined(ELPP_SYSLOG) +#include <ctime> +#include <cstring> +#include <cstdlib> +#include <cctype> +#include <cwchar> +#include <csignal> +#include <cerrno> +#include <cstdarg> +#if defined(ELPP_UNICODE) +# include <locale> +# if ELPP_OS_WINDOWS +# include <codecvt> +# endif // ELPP_OS_WINDOWS +#endif // defined(ELPP_UNICODE) +#if ELPP_STACKTRACE +# include <cxxabi.h> +# include <execinfo.h> +#endif // ELPP_STACKTRACE +#if ELPP_OS_ANDROID +# include <sys/system_properties.h> +#endif // ELPP_OS_ANDROID +#if ELPP_OS_UNIX +# include <sys/stat.h> +# include <sys/time.h> +#elif ELPP_OS_WINDOWS +# include <direct.h> +# include <windows.h> +# if defined(WIN32_LEAN_AND_MEAN) +# if defined(ELPP_WINSOCK2) +# include <winsock2.h> +# else +# include <winsock.h> +# endif // defined(ELPP_WINSOCK2) +# endif // defined(WIN32_LEAN_AND_MEAN) +#endif // ELPP_OS_UNIX +#include <string> +#include <vector> +#include <map> +#include <utility> +#include <functional> +#include <algorithm> +#include <fstream> +#include <iostream> +#include <sstream> +#include <memory> +#include <type_traits> +#if ELPP_THREADING_ENABLED +# if ELPP_USE_STD_THREADING +# include <mutex> +# include <thread> +# else +# if ELPP_OS_UNIX +# include <pthread.h> +# endif // ELPP_OS_UNIX +# endif // ELPP_USE_STD_THREADING +#endif // ELPP_THREADING_ENABLED +#if ELPP_ASYNC_LOGGING +# include <thread> +# include <queue> +# include <condition_variable> +#endif // ELPP_ASYNC_LOGGING +#if defined(ELPP_STL_LOGGING) +// For logging STL based templates +# include <list> +# include <queue> +# include <deque> +# include <set> +# include <bitset> +# include <stack> +# if defined(ELPP_LOG_STD_ARRAY) +# include <array> +# endif // defined(ELPP_LOG_STD_ARRAY) +# if defined(ELPP_LOG_UNORDERED_MAP) +# include <unordered_map> +# endif // defined(ELPP_LOG_UNORDERED_MAP) +# if defined(ELPP_LOG_UNORDERED_SET) +# include <unordered_set> +# endif // defined(ELPP_UNORDERED_SET) +#endif // defined(ELPP_STL_LOGGING) +#if defined(ELPP_QT_LOGGING) +// For logging Qt based classes & templates +# include <QString> +# include <QByteArray> +# include <QVector> +# include <QList> +# include <QPair> +# include <QMap> +# include <QQueue> +# include <QSet> +# include <QLinkedList> +# include <QHash> +# include <QMultiHash> +# include <QStack> +#endif // defined(ELPP_QT_LOGGING) +#if defined(ELPP_BOOST_LOGGING) +// For logging boost based classes & templates +# include <boost/container/vector.hpp> +# include <boost/container/stable_vector.hpp> +# include <boost/container/list.hpp> +# include <boost/container/deque.hpp> +# include <boost/container/map.hpp> +# include <boost/container/flat_map.hpp> +# include <boost/container/set.hpp> +# include <boost/container/flat_set.hpp> +#endif // defined(ELPP_BOOST_LOGGING) +#if defined(ELPP_WXWIDGETS_LOGGING) +// For logging wxWidgets based classes & templates +# include <wx/vector.h> +#endif // defined(ELPP_WXWIDGETS_LOGGING) +// Forward declarations +namespace el { + class Logger; + class LogMessage; + class PerformanceTrackingData; + class Loggers; + class Helpers; + template <typename T> class Callback; + class LogDispatchCallback; + class PerformanceTrackingCallback; + class LogDispatchData; + namespace base { + class Storage; + class RegisteredLoggers; + class PerformanceTracker; + class MessageBuilder; + class Writer; + class PErrorWriter; + class LogDispatcher; + class DefaultLogBuilder; + class DefaultLogDispatchCallback; +#if ELPP_ASYNC_LOGGING + class AsyncLogDispatchCallback; + class AsyncDispatchWorker; +#endif // ELPP_ASYNC_LOGGING + class DefaultPerformanceTrackingCallback; + } // namespace base +} // namespace el + /// @brief Easylogging++ entry namespace +namespace el { + /// @brief Namespace containing base/internal functionality used by Easylogging++ + namespace base { + /// @brief Data types used by Easylogging++ + namespace type { +#undef ELPP_LITERAL +#undef ELPP_STRLEN +#undef ELPP_COUT +#if defined(ELPP_UNICODE) +# define ELPP_LITERAL(txt) L##txt +# define ELPP_STRLEN wcslen +# if defined ELPP_CUSTOM_COUT +# define ELPP_COUT ELPP_CUSTOM_COUT +# else +# define ELPP_COUT std::wcout +# endif // defined ELPP_CUSTOM_COUT + typedef wchar_t char_t; + typedef std::wstring string_t; + typedef std::wstringstream stringstream_t; + typedef std::wfstream fstream_t; + typedef std::wostream ostream_t; +#else +# define ELPP_LITERAL(txt) txt +# define ELPP_STRLEN strlen +# if defined ELPP_CUSTOM_COUT +# define ELPP_COUT ELPP_CUSTOM_COUT +# else +# define ELPP_COUT std::cout +# endif // defined ELPP_CUSTOM_COUT + typedef char char_t; + typedef std::string string_t; + typedef std::stringstream stringstream_t; + typedef std::fstream fstream_t; + typedef std::ostream ostream_t; +#endif // defined(ELPP_UNICODE) +#if defined(ELPP_CUSTOM_COUT_LINE) +# define ELPP_COUT_LINE(logLine) ELPP_CUSTOM_COUT_LINE(logLine) +#else +# define ELPP_COUT_LINE(logLine) logLine << std::flush +#endif // defined(ELPP_CUSTOM_COUT_LINE) + typedef unsigned short EnumType; + typedef std::shared_ptr<base::Storage> StoragePointer; + typedef int VerboseLevel; + typedef std::shared_ptr<LogDispatchCallback> LogDispatchCallbackPtr; + typedef std::shared_ptr<PerformanceTrackingCallback> PerformanceTrackingCallbackPtr; + } // namespace type + /// @brief Internal helper class that prevent copy constructor for class + /// + /// @detail When using this class simply inherit it privately + class NoCopy { + protected: + NoCopy(void) {} + private: + NoCopy(const NoCopy&); + NoCopy& operator=(const NoCopy&); + }; + /// @brief Internal helper class that makes all default constructors private. + /// + /// @detail This prevents initializing class making it static unless an explicit constructor is declared. + /// When using this class simply inherit it privately + class StaticClass { + private: + StaticClass(void); + StaticClass(const StaticClass&); + StaticClass& operator=(const StaticClass&); + }; + } // namespace base + /// @brief Represents enumeration for severity level used to determine level of logging + /// + /// @detail With Easylogging++, developers may disable or enable any level regardless of + /// what the severity is. Or they can choose to log using hierarchical logging flag + enum class Level : base::type::EnumType { + /// @brief Generic level that represents all the levels. Useful when setting global configuration for all levels + Global = 1, + /// @brief Information that can be useful to back-trace certain events - mostly useful than debug logs. + Trace = 2, + /// @brief Informational events most useful for developers to debug application + Debug = 4, + /// @brief Severe error information that will presumably abort application + Fatal = 8, + /// @brief Information representing errors in application but application will keep running + Error = 16, + /// @brief Useful when application has potentially harmful situtaions + Warning = 32, + /// @brief Information that can be highly useful and vary with verbose logging level. + Verbose = 64, + /// @brief Mainly useful to represent current progress of application + Info = 128, + /// @brief Represents unknown level + Unknown = 1010 + }; + /// @brief Static class that contains helper functions for el::Level + class LevelHelper : base::StaticClass { + public: + /// @brief Represents minimum valid level. Useful when iterating through enum. + static const base::type::EnumType kMinValid = static_cast<base::type::EnumType>(Level::Trace); + /// @brief Represents maximum valid level. This is used internally and you should not need it. + static const base::type::EnumType kMaxValid = static_cast<base::type::EnumType>(Level::Info); + /// @brief Casts level to int, useful for iterating through enum. + static base::type::EnumType castToInt(Level level) { + return static_cast<base::type::EnumType>(level); + } + /// @brief Casts int(ushort) to level, useful for iterating through enum. + static Level castFromInt(base::type::EnumType l) { + return static_cast<Level>(l); + } + /// @brief Converts level to associated const char* + /// @return Upper case string based level. + static const char* convertToString(Level level) { + // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. + if (level == Level::Global) return "GLOBAL"; + if (level == Level::Debug) return "DEBUG"; + if (level == Level::Info) return "INFO"; + if (level == Level::Warning) return "WARNING"; + if (level == Level::Error) return "ERROR"; + if (level == Level::Fatal) return "FATAL"; + if (level == Level::Verbose) return "VERBOSE"; + if (level == Level::Trace) return "TRACE"; + return "UNKNOWN"; + } + /// @brief Converts from levelStr to Level + /// @param levelStr Upper case string based level. + /// Lower case is also valid but providing upper case is recommended. + static Level convertFromString(const char* levelStr) { + if ((strcmp(levelStr, "GLOBAL") == 0) || (strcmp(levelStr, "global") == 0)) + return Level::Global; + if ((strcmp(levelStr, "DEBUG") == 0) || (strcmp(levelStr, "debug") == 0)) + return Level::Debug; + if ((strcmp(levelStr, "INFO") == 0) || (strcmp(levelStr, "info") == 0)) + return Level::Info; + if ((strcmp(levelStr, "WARNING") == 0) || (strcmp(levelStr, "warning") == 0)) + return Level::Warning; + if ((strcmp(levelStr, "ERROR") == 0) || (strcmp(levelStr, "error") == 0)) + return Level::Error; + if ((strcmp(levelStr, "FATAL") == 0) || (strcmp(levelStr, "fatal") == 0)) + return Level::Fatal; + if ((strcmp(levelStr, "VERBOSE") == 0) || (strcmp(levelStr, "verbose") == 0)) + return Level::Verbose; + if ((strcmp(levelStr, "TRACE") == 0) || (strcmp(levelStr, "trace") == 0)) + return Level::Trace; + return Level::Unknown; + } + /// @brief Applies specified function to each level starting from startIndex + /// @param startIndex initial value to start the iteration from. This is passed as pointer and + /// is left-shifted so this can be used inside function (fn) to represent current level. + /// @param fn function to apply with each level. This bool represent whether or not to stop iterating through levels. + static inline void forEachLevel(base::type::EnumType* startIndex, const std::function<bool(void)>& fn) { + base::type::EnumType lIndexMax = LevelHelper::kMaxValid; + do { + if (fn()) { + break; + } + *startIndex = static_cast<base::type::EnumType>(*startIndex << 1); + } while (*startIndex <= lIndexMax); + } + }; + /// @brief Represents enumeration of ConfigurationType used to configure or access certain aspect + /// of logging + enum class ConfigurationType : base::type::EnumType { + /// @brief Determines whether or not corresponding level and logger of logging is enabled + /// You may disable all logs by using el::Level::Global + Enabled = 1, + /// @brief Whether or not to write corresponding log to log file + ToFile = 2, + /// @brief Whether or not to write corresponding level and logger log to standard output. + /// By standard output meaning termnal, command prompt etc + ToStandardOutput = 4, + /// @brief Determines format of logging corresponding level and logger. + Format = 8, + /// @brief Determines log file (full path) to write logs to for correponding level and logger + Filename = 16, + /// @brief Specifies milliseconds width. Width can be within range (1-6) + MillisecondsWidth = 32, + /// @brief Determines whether or not performance tracking is enabled. + /// + /// @detail This does not depend on logger or level. Performance tracking always uses 'performance' logger + PerformanceTracking = 64, + /// @brief Specifies log file max size. + /// + /// @detail If file size of corresponding log file (for corresponding level) is >= specified size, log file will + /// be truncated and re-initiated. + MaxLogFileSize = 128, + /// @brief Specifies number of log entries to hold until we flush pending log data + LogFlushThreshold = 256, + /// @brief Represents unknown configuration + Unknown = 1010 + }; + /// @brief Static class that contains helper functions for el::ConfigurationType + class ConfigurationTypeHelper : base::StaticClass { + public: + /// @brief Represents minimum valid configuration type. Useful when iterating through enum. + static const base::type::EnumType kMinValid = static_cast<base::type::EnumType>(ConfigurationType::Enabled); + /// @brief Represents maximum valid configuration type. This is used internally and you should not need it. + static const base::type::EnumType kMaxValid = static_cast<base::type::EnumType>(ConfigurationType::MaxLogFileSize); + /// @brief Casts configuration type to int, useful for iterating through enum. + static base::type::EnumType castToInt(ConfigurationType configurationType) { + return static_cast<base::type::EnumType>(configurationType); + } + /// @brief Casts int(ushort) to configurationt type, useful for iterating through enum. + static ConfigurationType castFromInt(base::type::EnumType c) { + return static_cast<ConfigurationType>(c); + } + /// @brief Converts configuration type to associated const char* + /// @returns Upper case string based configuration type. + static const char* convertToString(ConfigurationType configurationType) { + // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. + if (configurationType == ConfigurationType::Enabled) return "ENABLED"; + if (configurationType == ConfigurationType::Filename) return "FILENAME"; + if (configurationType == ConfigurationType::Format) return "FORMAT"; + if (configurationType == ConfigurationType::ToFile) return "TO_FILE"; + if (configurationType == ConfigurationType::ToStandardOutput) return "TO_STANDARD_OUTPUT"; + if (configurationType == ConfigurationType::MillisecondsWidth) return "MILLISECONDS_WIDTH"; + if (configurationType == ConfigurationType::PerformanceTracking) return "PERFORMANCE_TRACKING"; + if (configurationType == ConfigurationType::MaxLogFileSize) return "MAX_LOG_FILE_SIZE"; + if (configurationType == ConfigurationType::LogFlushThreshold) return "LOG_FLUSH_THRESHOLD"; + return "UNKNOWN"; + } + /// @brief Converts from configStr to ConfigurationType + /// @param configStr Upper case string based configuration type. + /// Lower case is also valid but providing upper case is recommended. + static ConfigurationType convertFromString(const char* configStr) { + if ((strcmp(configStr, "ENABLED") == 0) || (strcmp(configStr, "enabled") == 0)) + return ConfigurationType::Enabled; + if ((strcmp(configStr, "TO_FILE") == 0) || (strcmp(configStr, "to_file") == 0)) + return ConfigurationType::ToFile; + if ((strcmp(configStr, "TO_STANDARD_OUTPUT") == 0) || (strcmp(configStr, "to_standard_output") == 0)) + return ConfigurationType::ToStandardOutput; + if ((strcmp(configStr, "FORMAT") == 0) || (strcmp(configStr, "format") == 0)) + return ConfigurationType::Format; + if ((strcmp(configStr, "FILENAME") == 0) || (strcmp(configStr, "filename") == 0)) + return ConfigurationType::Filename; + if ((strcmp(configStr, "MILLISECONDS_WIDTH") == 0) || (strcmp(configStr, "milliseconds_width") == 0)) + return ConfigurationType::MillisecondsWidth; + if ((strcmp(configStr, "PERFORMANCE_TRACKING") == 0) || (strcmp(configStr, "performance_tracking") == 0)) + return ConfigurationType::PerformanceTracking; + if ((strcmp(configStr, "MAX_LOG_FILE_SIZE") == 0) || (strcmp(configStr, "max_log_file_size") == 0)) + return ConfigurationType::MaxLogFileSize; + if ((strcmp(configStr, "LOG_FLUSH_THRESHOLD") == 0) || (strcmp(configStr, "log_flush_threshold") == 0)) + return ConfigurationType::LogFlushThreshold; + return ConfigurationType::Unknown; + } + /// @brief Applies specified function to each configuration type starting from startIndex + /// @param startIndex initial value to start the iteration from. This is passed by pointer and is left-shifted + /// so this can be used inside function (fn) to represent current configuration type. + /// @param fn function to apply with each configuration type. + /// This bool represent whether or not to stop iterating through configurations. + static inline void forEachConfigType(base::type::EnumType* startIndex, const std::function<bool(void)>& fn) { + base::type::EnumType cIndexMax = ConfigurationTypeHelper::kMaxValid; + do { + if (fn()) { + break; + } + *startIndex = static_cast<base::type::EnumType>(*startIndex << 1); + } while (*startIndex <= cIndexMax); + } + }; + /// @brief Flags used while writing logs. This flags are set by user + enum class LoggingFlag : base::type::EnumType { + /// @brief Makes sure we have new line for each container log entry + NewLineForContainer = 1, + /// @brief Makes sure if -vmodule is used and does not specifies a module, then verbose + /// logging is allowed via that module. + AllowVerboseIfModuleNotSpecified = 2, + /// @brief When handling crashes by default, detailed crash reason will be logged as well + LogDetailedCrashReason = 4, + /// @brief Allows to disable application abortion when logged using FATAL level + DisableApplicationAbortOnFatalLog = 8, + /// @brief Flushes log with every log-entry (performance sensative) - Disabled by default + ImmediateFlush = 16, + /// @brief Enables strict file rolling + StrictLogFileSizeCheck = 32, + /// @brief Make terminal output colorful for supported terminals + ColoredTerminalOutput = 64, + /// @brief Supports use of multiple logging in same macro, e.g, CLOG(INFO, "default", "network") + MultiLoggerSupport = 128, + /// @brief Disables comparing performance tracker's checkpoints + DisablePerformanceTrackingCheckpointComparison = 256, + /// @brief Disable VModules + DisableVModules = 512, + /// @brief Disable VModules extensions + DisableVModulesExtensions = 1024, + /// @brief Enables hierarchical logging + HierarchicalLogging = 2048, + /// @brief Creates logger automatically when not available + CreateLoggerAutomatically = 4096, + /// @brief Adds spaces b/w logs that separated by left-shift operator + AutoSpacing = 8192, + /// @brief Preserves time format and does not convert it to sec, hour etc (performance tracking only) + FixedTimeFormat = 16384 + }; + namespace base { + /// @brief Namespace containing constants used internally. + namespace consts { + // Level log values - These are values that are replaced in place of %level format specifier + static const base::type::char_t* kInfoLevelLogValue = ELPP_LITERAL("INFO "); + static const base::type::char_t* kDebugLevelLogValue = ELPP_LITERAL("DEBUG"); + static const base::type::char_t* kWarningLevelLogValue = ELPP_LITERAL("WARN "); + static const base::type::char_t* kErrorLevelLogValue = ELPP_LITERAL("ERROR"); + static const base::type::char_t* kFatalLevelLogValue = ELPP_LITERAL("FATAL"); + static const base::type::char_t* kVerboseLevelLogValue = ELPP_LITERAL("VER"); + static const base::type::char_t* kTraceLevelLogValue = ELPP_LITERAL("TRACE"); + static const base::type::char_t* kInfoLevelShortLogValue = ELPP_LITERAL("I"); + static const base::type::char_t* kDebugLevelShortLogValue = ELPP_LITERAL("D"); + static const base::type::char_t* kWarningLevelShortLogValue = ELPP_LITERAL("W"); + static const base::type::char_t* kErrorLevelShortLogValue = ELPP_LITERAL("E"); + static const base::type::char_t* kFatalLevelShortLogValue = ELPP_LITERAL("F"); + static const base::type::char_t* kVerboseLevelShortLogValue = ELPP_LITERAL("V"); + static const base::type::char_t* kTraceLevelShortLogValue = ELPP_LITERAL("T"); + // Format specifiers - These are used to define log format + static const base::type::char_t* kAppNameFormatSpecifier = ELPP_LITERAL("%app"); + static const base::type::char_t* kLoggerIdFormatSpecifier = ELPP_LITERAL("%logger"); + static const base::type::char_t* kThreadIdFormatSpecifier = ELPP_LITERAL("%thread"); + static const base::type::char_t* kSeverityLevelFormatSpecifier = ELPP_LITERAL("%level"); + static const base::type::char_t* kSeverityLevelShortFormatSpecifier = ELPP_LITERAL("%levshort"); + static const base::type::char_t* kDateTimeFormatSpecifier = ELPP_LITERAL("%datetime"); + static const base::type::char_t* kLogFileFormatSpecifier = ELPP_LITERAL("%file"); + static const base::type::char_t* kLogFileBaseFormatSpecifier = ELPP_LITERAL("%fbase"); + static const base::type::char_t* kLogLineFormatSpecifier = ELPP_LITERAL("%line"); + static const base::type::char_t* kLogLocationFormatSpecifier = ELPP_LITERAL("%loc"); + static const base::type::char_t* kLogFunctionFormatSpecifier = ELPP_LITERAL("%func"); + static const base::type::char_t* kCurrentUserFormatSpecifier = ELPP_LITERAL("%user"); + static const base::type::char_t* kCurrentHostFormatSpecifier = ELPP_LITERAL("%host"); + static const base::type::char_t* kMessageFormatSpecifier = ELPP_LITERAL("%msg"); + static const base::type::char_t* kVerboseLevelFormatSpecifier = ELPP_LITERAL("%vlevel"); + static const char* kDateTimeFormatSpecifierForFilename = "%datetime"; + // Date/time + static const char* kDays[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; + static const char* kDaysAbbrev[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + static const char* kMonths[12] = { "January", "February", "March", "Apri", "May", "June", "July", "August", + "September", "October", "November", "December" }; + static const char* kMonthsAbbrev[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + static const char* kDefaultDateTimeFormat = "%Y-%M-%d %H:%m:%s,%g"; + static const char* kDefaultDateTimeFormatInFilename = "%Y-%M-%d_%H-%m"; + static const int kYearBase = 1900; + static const char* kAm = "AM"; + static const char* kPm = "PM"; + // Miscellaneous constants + static const char* kDefaultLoggerId = "default"; + static const char* kPerformanceLoggerId = "performance"; + static const char* kSysLogLoggerId = "syslog"; + static const char* kNullPointer = "nullptr"; + static const char kFormatSpecifierChar = '%'; +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED + static const char kFormatSpecifierCharValue = 'v'; +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED + static const unsigned int kMaxLogPerContainer = 100; + static const unsigned int kMaxLogPerCounter = 100000; + static const unsigned int kDefaultMillisecondsWidth = 3; + static const base::type::VerboseLevel kMaxVerboseLevel = 9; + static const char* kUnknownUser = "user"; + static const char* kUnknownHost = "unknown-host"; +#if defined(ELPP_DEFAULT_LOG_FILE) + static const char* kDefaultLogFile = ELPP_DEFAULT_LOG_FILE; +#else +# if ELPP_OS_UNIX +# if ELPP_OS_ANDROID + static const char* kDefaultLogFile = "logs/ace.log"; +# else + static const char* kDefaultLogFile = "logs/ace.log"; +# endif // ELPP_OS_ANDROID +# elif ELPP_OS_WINDOWS + static const char* kDefaultLogFile = "logs\\ace.log"; +# endif // ELPP_OS_UNIX +#endif // defined(ELPP_DEFAULT_LOG_FILE) +#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) + static const char* kDefaultLogFileParam = "--default-log-file"; +#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) +#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) + static const char* kLoggingFlagsParam = "--logging-flags"; +#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) +#if ELPP_OS_WINDOWS + static const char* kFilePathSeperator = "\\"; +#else + static const char* kFilePathSeperator = "/"; +#endif // ELPP_OS_WINDOWS + static const char* kValidLoggerIdSymbols = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._"; + static const char* kConfigurationComment = "##"; + static const char* kConfigurationLevel = "*"; + static const char* kConfigurationLoggerId = "--"; + static const std::size_t kSourceFilenameMaxLength = 100; + static const std::size_t kSourceLineMaxLength = 10; + static const Level kPerformanceTrackerDefaultLevel = Level::Info; + const struct { + double value; + const base::type::char_t* unit; + } kTimeFormats[] = { + { 1000.0f, ELPP_LITERAL("mis") }, + { 1000.0f, ELPP_LITERAL("ms") }, + { 60.0f, ELPP_LITERAL("seconds") }, + { 60.0f, ELPP_LITERAL("minutes") }, + { 24.0f, ELPP_LITERAL("hours") }, + { 7.0f, ELPP_LITERAL("days") } + }; + static const int kTimeFormatsCount = sizeof(kTimeFormats) / sizeof(kTimeFormats[0]); + const struct { + int numb; + const char* name; + const char* brief; + const char* detail; + } kCrashSignals[] = { + // NOTE: Do not re-order, if you do please check CrashHandler(bool) constructor and CrashHandler::setHandler(..) + { SIGABRT, "SIGABRT", "Abnormal termination", + "Program was abnormally terminated." }, + { SIGFPE, "SIGFPE", "Erroneous arithmetic operation", + "Arithemetic operation issue such as division by zero or operation resulting in overflow." }, + { SIGILL, "SIGILL", "Illegal instruction", + "Generally due to a corruption in the code or to an attempt to execute data." }, + { SIGSEGV, "SIGSEGV", "Invalid access to memory", + "Program is trying to read an invalid (unallocated, deleted or corrupted) or inaccessible memory." }, + { SIGINT, "SIGINT", "Interactive attention signal", + "Interruption generated (generally) by user or operating system." }, + }; + static const int kCrashSignalsCount = sizeof(kCrashSignals) / sizeof(kCrashSignals[0]); + } // namespace consts + } // namespace base + typedef std::function<void(const char*, std::size_t)> PreRollOutCallback; + namespace base { + static inline void defaultPreRollOutCallback(const char*, std::size_t) {} + /// @brief Enum to represent timestamp unit + enum class TimestampUnit : base::type::EnumType { + Microsecond = 0, Millisecond = 1, Second = 2, Minute = 3, Hour = 4, Day = 5 + }; + /// @brief Format flags used to determine specifiers that are active for performance improvements. + enum class FormatFlags : base::type::EnumType { + DateTime = 1 << 1, LoggerId = 1 << 2, File = 1 << 3, Line = 1 << 4, Location = 1 << 5, Function = 1 << 6, + User = 1 << 7, Host = 1 << 8, LogMessage = 1 << 9, VerboseLevel = 1 << 10, AppName = 1 << 11, ThreadId = 1 << 12, + Level = 1 << 13, FileBase = 1 << 14, LevelShort = 1 << 15 + }; + /// @brief A milliseconds width class containing actual width and offset for date/time + class MillisecondsWidth { + public: + MillisecondsWidth(void) { init(base::consts::kDefaultMillisecondsWidth); } + explicit MillisecondsWidth(int width) { init(width); } + bool operator==(const MillisecondsWidth& msWidth) { return m_width == msWidth.m_width && m_offset == msWidth.m_offset; } + int m_width; unsigned int m_offset; + private: + void init(int width) { + if (width < 1 || width > 6) { + width = base::consts::kDefaultMillisecondsWidth; + } + m_width = width; + switch (m_width) { + case 3: m_offset = 1000; break; + case 4: m_offset = 100; break; + case 5: m_offset = 10; break; + case 6: m_offset = 1; break; + default: m_offset = 1000; break; + } + } + }; + /// @brief Namespace containing utility functions/static classes used internally + namespace utils { + /// @brief Deletes memory safely and points to null + template <typename T> + static inline + typename std::enable_if<std::is_pointer<T*>::value, void>::type + safeDelete(T*& pointer) { + if (pointer == nullptr) + return; + delete pointer; + pointer = nullptr; + } + /// @brief Gets value of const char* but if it is nullptr, a string nullptr is returned + static inline const char* charPtrVal(const char* pointer) { + return pointer == nullptr ? base::consts::kNullPointer : pointer; + } + /// @brief Aborts application due with user-defined status + static inline void abort(int status, const std::string& reason = std::string()) { + // Both status and reason params are there for debugging with tools like gdb etc + ELPP_UNUSED(status); + ELPP_UNUSED(reason); +#if defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) + // Ignore msvc critical error dialog - break instead (on debug mode) + _asm int 3 +#else + ::abort(); +#endif // defined(ELPP_COMPILER_MSVC) && defined(_M_IX86) && defined(_DEBUG) + } + /// @brief Bitwise operations for C++11 strong enum class. This casts e into Flag_T and returns value after bitwise operation + /// Use these function as <pre>flag = bitwise::Or<MyEnum>(MyEnum::val1, flag);</pre> + namespace bitwise { + template <typename Enum> + static inline base::type::EnumType And(Enum e, base::type::EnumType flag) { + return static_cast<base::type::EnumType>(flag) & static_cast<base::type::EnumType>(e); + } + template <typename Enum> + static inline base::type::EnumType Not(Enum e, base::type::EnumType flag) { + return static_cast<base::type::EnumType>(flag) & ~(static_cast<base::type::EnumType>(e)); + } + template <typename Enum> + static inline base::type::EnumType Or(Enum e, base::type::EnumType flag) { + return static_cast<base::type::EnumType>(flag) | static_cast<base::type::EnumType>(e); + } + } // namespace bitwise + template <typename Enum> + static inline void addFlag(Enum e, base::type::EnumType* flag) { + *flag = base::utils::bitwise::Or<Enum>(e, *flag); + } + template <typename Enum> + static inline void removeFlag(Enum e, base::type::EnumType* flag) { + *flag = base::utils::bitwise::Not<Enum>(e, *flag); + } + template <typename Enum> + static inline bool hasFlag(Enum e, base::type::EnumType flag) { + return base::utils::bitwise::And<Enum>(e, flag) > 0x0; + } + } // namespace utils + namespace threading { +#if ELPP_THREADING_ENABLED +# if !ELPP_USE_STD_THREADING + namespace internal { + /// @brief A mutex wrapper for compiler that dont yet support std::mutex + class Mutex : base::NoCopy { + public: + Mutex(void) { +# if ELPP_OS_UNIX + pthread_mutex_init(&m_underlyingMutex, nullptr); +# elif ELPP_OS_WINDOWS + InitializeCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + virtual ~Mutex(void) { +# if ELPP_OS_UNIX + pthread_mutex_destroy(&m_underlyingMutex); +# elif ELPP_OS_WINDOWS + DeleteCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + inline void lock(void) { +# if ELPP_OS_UNIX + pthread_mutex_lock(&m_underlyingMutex); +# elif ELPP_OS_WINDOWS + EnterCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + inline bool try_lock(void) { +# if ELPP_OS_UNIX + return (pthread_mutex_trylock(&m_underlyingMutex) == 0); +# elif ELPP_OS_WINDOWS + return TryEnterCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + inline void unlock(void) { +# if ELPP_OS_UNIX + pthread_mutex_unlock(&m_underlyingMutex); +# elif ELPP_OS_WINDOWS + LeaveCriticalSection(&m_underlyingMutex); +# endif // ELPP_OS_UNIX + } + + private: +# if ELPP_OS_UNIX + pthread_mutex_t m_underlyingMutex; +# elif ELPP_OS_WINDOWS + CRITICAL_SECTION m_underlyingMutex; +# endif // ELPP_OS_UNIX + }; + /// @brief Scoped lock for compiler that dont yet support std::lock_guard + template <typename M> + class ScopedLock : base::NoCopy { + public: + explicit ScopedLock(M& mutex) { + m_mutex = &mutex; + m_mutex->lock(); + } + + virtual ~ScopedLock(void) { + m_mutex->unlock(); + } + private: + M* m_mutex; + ScopedLock(void); + }; + } // namespace internal + /// @brief Gets ID of currently running threading in windows systems. On unix, nothing is returned. + static inline std::string getCurrentThreadId(void) { + std::stringstream ss; +# if (ELPP_OS_WINDOWS) + ss << GetCurrentThreadId(); +# endif // (ELPP_OS_WINDOWS) + return ss.str(); + } + static inline void msleep(int) { + // No implementation for non std::thread version + } + typedef base::threading::internal::Mutex Mutex; + typedef base::threading::internal::ScopedLock<base::threading::Mutex> ScopedLock; +# else + /// @brief Gets ID of currently running threading using std::this_thread::get_id() + static inline std::string getCurrentThreadId(void) { + std::stringstream ss; + ss << std::this_thread::get_id(); + return ss.str(); + } + static inline void msleep(int ms) { + // Only when async logging enabled - this is because async is strict on compiler +#if ELPP_ASYNC_LOGGING + std::this_thread::sleep_for(std::chrono::milliseconds(ms)); +#endif // ELPP_ASYNC_LOGGING + } + typedef std::mutex Mutex; + typedef std::lock_guard<std::mutex> ScopedLock; +# endif // !ELPP_USE_STD_THREADING +#else + namespace internal { + /// @brief Mutex wrapper used when multi-threading is disabled. + class NoMutex : base::NoCopy { + public: + NoMutex(void) {} + inline void lock(void) {} + inline bool try_lock(void) { return true; } + inline void unlock(void) {} + }; + /// @brief Lock guard wrapper used when multi-threading is disabled. + template <typename Mutex> + class NoScopedLock : base::NoCopy { + public: + explicit NoScopedLock(Mutex&) { + } + virtual ~NoScopedLock(void) { + } + private: + NoScopedLock(void); + }; + } // namespace internal + static inline std::string getCurrentThreadId(void) { + return std::string(); + } + static inline void msleep(int) { + // No custom implementation + } + typedef base::threading::internal::NoMutex Mutex; + typedef base::threading::internal::NoScopedLock<base::threading::Mutex> ScopedLock; +#endif // ELPP_THREADING_ENABLED + /// @brief Base of thread safe class, this class is inheritable-only + class ThreadSafe { + public: + virtual inline void acquireLock(void) ELPP_FINAL { m_mutex.lock(); } + virtual inline void releaseLock(void) ELPP_FINAL { m_mutex.unlock(); } + virtual inline base::threading::Mutex& lock(void) ELPP_FINAL { return m_mutex; } + protected: + ThreadSafe(void) {} + virtual ~ThreadSafe(void) {} + private: + base::threading::Mutex m_mutex; + }; + } // namespace threading + namespace utils { + class File : base::StaticClass { + public: + /// @brief Creates new out file stream for specified filename. + /// @return Pointer to newly created fstream or nullptr + static base::type::fstream_t* newFileStream(const std::string& filename) { + base::type::fstream_t *fs = new base::type::fstream_t(filename.c_str(), + base::type::fstream_t::out | base::type::fstream_t::app); +#if defined(ELPP_UNICODE) + std::locale elppUnicodeLocale(""); +#if ELPP_OS_WINDOWS + std::locale elppUnicodeLocaleWindows(elppUnicodeLocale, new std::codecvt_utf8_utf16<wchar_t>); + elppUnicodeLocale = elppUnicodeLocaleWindows; +#endif + fs->imbue(elppUnicodeLocale); +#endif // defined(ELPP_UNICODE) + if (fs->is_open()) { + fs->flush(); + } + else { + base::utils::safeDelete(fs); + ELPP_INTERNAL_ERROR("Bad file [" << filename << "]", true); + } + return fs; + } + + /// @brief Gets size of file provided in stream + static std::size_t getSizeOfFile(base::type::fstream_t* fs) { + if (fs == nullptr) { + return 0; + } + std::streampos currPos = fs->tellg(); + fs->seekg(0, fs->end); + std::size_t size = static_cast<std::size_t>(fs->tellg()); + fs->seekg(currPos); + return size; + } + + /// @brief Determines whether or not provided path exist in current file system + static inline bool pathExists(const char* path, bool considerFile = false) { + if (path == nullptr) { + return false; + } +#if ELPP_OS_UNIX + ELPP_UNUSED(considerFile); + struct stat st; + return (stat(path, &st) == 0); +#elif ELPP_OS_WINDOWS + DWORD fileType = GetFileAttributesA(path); + if (fileType == INVALID_FILE_ATTRIBUTES) { + return false; + } + return considerFile ? true : ((fileType & FILE_ATTRIBUTE_DIRECTORY) == 0 ? false : true); +#endif // ELPP_OS_UNIX + } + + /// @brief Creates specified path on file system + /// @param path Path to create. + static bool createPath(const std::string& path) { + if (path.empty()) { + return false; + } + if (base::utils::File::pathExists(path.c_str())) { + return true; + } + int status = -1; + + char* currPath = const_cast<char*>(path.c_str()); + std::string builtPath = std::string(); +#if ELPP_OS_UNIX + if (path[0] == '/') { + builtPath = "/"; + } + currPath = STRTOK(currPath, base::consts::kFilePathSeperator, 0); +#elif ELPP_OS_WINDOWS + // Use secure functions API + char* nextTok_ = nullptr; + currPath = STRTOK(currPath, base::consts::kFilePathSeperator, &nextTok_); + ELPP_UNUSED(nextTok_); +#endif // ELPP_OS_UNIX + while (currPath != nullptr) { + builtPath.append(currPath); + builtPath.append(base::consts::kFilePathSeperator); +#if ELPP_OS_UNIX + status = mkdir(builtPath.c_str(), ELPP_LOG_PERMS); + currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, 0); +#elif ELPP_OS_WINDOWS + status = _mkdir(builtPath.c_str()); + currPath = STRTOK(nullptr, base::consts::kFilePathSeperator, &nextTok_); +#endif // ELPP_OS_UNIX + } + if (status == -1) { + ELPP_INTERNAL_ERROR("Error while creating path [" << path << "]", true); + return false; + } + return true; + } + /// @brief Extracts path of filename with leading slash + static std::string extractPathFromFilename(const std::string& fullPath, + const char* seperator = base::consts::kFilePathSeperator) { + if ((fullPath == "") || (fullPath.find(seperator) == std::string::npos)) { + return fullPath; + } + std::size_t lastSlashAt = fullPath.find_last_of(seperator); + if (lastSlashAt == 0) { + return std::string(seperator); + } + return fullPath.substr(0, lastSlashAt + 1); + } + /// @brief builds stripped filename and puts it in buff + static void buildStrippedFilename(const char* filename, char buff[], + std::size_t limit = base::consts::kSourceFilenameMaxLength) { + std::size_t sizeOfFilename = strlen(filename); + if (sizeOfFilename >= limit) { + filename += (sizeOfFilename - limit); + if (filename[0] != '.' && filename[1] != '.') { // prepend if not already + filename += 3; // 3 = '..' + STRCAT(buff, "..", limit); + } + } + STRCAT(buff, filename, limit); + } + /// @brief builds base filename and puts it in buff + static void buildBaseFilename(const std::string& fullPath, char buff[], + std::size_t limit = base::consts::kSourceFilenameMaxLength, + const char* seperator = base::consts::kFilePathSeperator) { + const char *filename = fullPath.c_str(); + std::size_t lastSlashAt = fullPath.find_last_of(seperator); + filename += lastSlashAt ? lastSlashAt + 1 : 0; + std::size_t sizeOfFilename = strlen(filename); + if (sizeOfFilename >= limit) { + filename += (sizeOfFilename - limit); + if (filename[0] != '.' && filename[1] != '.') { // prepend if not already + filename += 3; // 3 = '..' + STRCAT(buff, "..", limit); + } + } + STRCAT(buff, filename, limit); + } + }; + /// @brief String utilities helper class used internally. You should not use it. + class Str : base::StaticClass { + public: + /// @brief Checks if character is digit. Dont use libc implementation of it to prevent locale issues. + static inline bool isDigit(char c) { + return c >= '0' && c <= '9'; + } + + /// @brief Matches wildcards, '*' and '?' only supported. + static bool wildCardMatch(const char* str, const char* pattern) { + while (*pattern) { + switch (*pattern) { + case '?': + if (!*str) + return false; + ++str; + ++pattern; + break; + case '*': + if (wildCardMatch(str, pattern + 1)) + return true; + if (*str && wildCardMatch(str + 1, pattern)) + return true; + return false; + break; + default: + if (*str++ != *pattern++) + return false; + break; + } + } + return !*str && !*pattern; + } + + /// @brief Trims string from start + /// @param [in,out] str String to trim + static inline std::string& ltrim(std::string& str) { + str.erase(str.begin(), std::find_if(str.begin(), str.end(), std::not1(std::ptr_fun<int, int>(&std::isspace)))); + return str; + } + + /// @brief Trim string from end + /// @param [in,out] str String to trim + static inline std::string& rtrim(std::string& str) { + str.erase(std::find_if(str.rbegin(), str.rend(), std::not1(std::ptr_fun<int, int>(&std::isspace))).base(), str.end()); + return str; + } + + /// @brief Trims string from left and right + /// @param [in,out] str String to trim + static inline std::string& trim(std::string& str) { + return ltrim(rtrim(str)); + } + + /// @brief Determines whether or not str starts with specified string + /// @param str String to check + /// @param start String to check against + /// @return Returns true if starts with specified string, false otherwise + static inline bool startsWith(const std::string& str, const std::string& start) { + return (str.length() >= start.length()) && (str.compare(0, start.length(), start) == 0); + } + + /// @brief Determines whether or not str ends with specified string + /// @param str String to check + /// @param end String to check against + /// @return Returns true if ends with specified string, false otherwise + static inline bool endsWith(const std::string& str, const std::string& end) { + return (str.length() >= end.length()) && (str.compare(str.length() - end.length(), end.length(), end) == 0); + } + + /// @brief Replaces all instances of replaceWhat with 'replaceWith'. Original variable is changed for performance. + /// @param [in,out] str String to replace from + /// @param replaceWhat Character to replace + /// @param replaceWith Character to replace with + /// @return Modified version of str + static inline std::string& replaceAll(std::string& str, char replaceWhat, char replaceWith) { + std::replace(str.begin(), str.end(), replaceWhat, replaceWith); + return str; + } + + /// @brief Replaces all instances of 'replaceWhat' with 'replaceWith'. (String version) Replaces in place + /// @param str String to replace from + /// @param replaceWhat Character to replace + /// @param replaceWith Character to replace with + /// @return Modified (original) str + static inline std::string& replaceAll(std::string& str, const std::string& replaceWhat, // NOLINT + const std::string& replaceWith) { + if (replaceWhat == replaceWith) + return str; + std::size_t foundAt = std::string::npos; + while ((foundAt = str.find(replaceWhat, foundAt + 1)) != std::string::npos) { + str.replace(foundAt, replaceWhat.length(), replaceWith); + } + return str; + } + + static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, // NOLINT + const base::type::string_t& replaceWith) { + std::size_t foundAt = base::type::string_t::npos; + while ((foundAt = str.find(replaceWhat, foundAt + 1)) != base::type::string_t::npos) { + if (foundAt > 0 && str[foundAt - 1] == base::consts::kFormatSpecifierChar) { + str.erase(foundAt > 0 ? foundAt - 1 : 0, 1); + ++foundAt; + } + else { + str.replace(foundAt, replaceWhat.length(), replaceWith); + return; + } + } + } +#if defined(ELPP_UNICODE) + static void replaceFirstWithEscape(base::type::string_t& str, const base::type::string_t& replaceWhat, // NOLINT + const std::string& replaceWith) { + replaceFirstWithEscape(str, replaceWhat, base::type::string_t(replaceWith.begin(), replaceWith.end())); + } +#endif // defined(ELPP_UNICODE) + /// @brief Converts string to uppercase + /// @param str String to convert + /// @return Uppercase string + static inline std::string& toUpper(std::string& str) { + std::transform(str.begin(), str.end(), str.begin(), ::toupper); + return str; + } + + /// @brief Compares cstring equality - uses strcmp + static inline bool cStringEq(const char* s1, const char* s2) { + if (s1 == nullptr && s2 == nullptr) return true; + if (s1 == nullptr || s2 == nullptr) return false; + return strcmp(s1, s2) == 0; + } + + /// @brief Compares cstring equality (case-insensitive) - uses toupper(char) + /// Dont use strcasecmp because of CRT (VC++) + static bool cStringCaseEq(const char* s1, const char* s2) { + if (s1 == nullptr && s2 == nullptr) return true; + if (s1 == nullptr || s2 == nullptr) return false; + if (strlen(s1) != strlen(s2)) return false; + while (*s1 != '\0' && *s2 != '\0') { + if (::toupper(*s1) != ::toupper(*s2)) return false; + ++s1; + ++s2; + } + return true; + } + + /// @brief Returns true if c exist in str + static inline bool contains(const char* str, char c) { + for (; *str; ++str) { + if (*str == c) + return true; + } + return false; + } + + static inline char* convertAndAddToBuff(std::size_t n, int len, char* buf, const char* bufLim, bool zeroPadded = true) { + char localBuff[10] = ""; + char* p = localBuff + sizeof(localBuff) - 2; + if (n > 0) { + for (; n > 0 && p > localBuff && len > 0; n /= 10, --len) + *--p = static_cast<char>(n % 10 + '0'); + } + else { + *--p = '0'; + --len; + } + if (zeroPadded) + while (p > localBuff && len-- > 0) *--p = static_cast<char>('0'); + return addToBuff(p, buf, bufLim); + } + + static inline char* addToBuff(const char* str, char* buf, const char* bufLim) { + while ((buf < bufLim) && ((*buf = *str++) != '\0')) + ++buf; + return buf; + } + + static inline char* clearBuff(char buff[], std::size_t lim) { + STRCPY(buff, "", lim); + ELPP_UNUSED(lim); // For *nix we dont have anything using lim in above STRCPY macro + return buff; + } + + /// @brief Converst wchar* to char* + /// NOTE: Need to free return value after use! + static char* wcharPtrToCharPtr(const wchar_t* line) { + std::size_t len_ = wcslen(line) + 1; + char* buff_ = static_cast<char*>(malloc(len_ + 1)); +# if ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) + std::wcstombs(buff_, line, len_); +# elif ELPP_OS_WINDOWS + std::size_t convCount_ = 0; + mbstate_t mbState_; + ::memset(static_cast<void*>(&mbState_), 0, sizeof(mbState_)); + wcsrtombs_s(&convCount_, buff_, len_, &line, len_, &mbState_); +# endif // ELPP_OS_UNIX || (ELPP_OS_WINDOWS && !ELPP_CRT_DBG_WARNINGS) + return buff_; + } + }; + /// @brief Operating System helper static class used internally. You should not use it. + class OS : base::StaticClass { + public: +#if ELPP_OS_WINDOWS + /// @brief Gets environment variables for Windows based OS. + /// We are not using <code>getenv(const char*)</code> because of CRT deprecation + /// @param varname Variable name to get environment variable value for + /// @return If variable exist the value of it otherwise nullptr + static const char* getWindowsEnvironmentVariable(const char* varname) { + const DWORD bufferLen = 50; + static char buffer[bufferLen]; + if (GetEnvironmentVariableA(varname, buffer, bufferLen)) { + return buffer; + } + return nullptr; + } +#endif // ELPP_OS_WINDOWS +#if ELPP_OS_ANDROID + /// @brief Reads android property value + static inline std::string getProperty(const char* prop) { + char propVal[PROP_VALUE_MAX + 1]; + int ret = __system_property_get(prop, propVal); + return ret == 0 ? std::string() : std::string(propVal); + } + + /// @brief Reads android device name + static std::string getDeviceName(void) { + std::stringstream ss; + std::string manufacturer = getProperty("ro.product.manufacturer"); + std::string model = getProperty("ro.product.model"); + if (manufacturer.empty() || model.empty()) { + return std::string(); + } + ss << manufacturer << "-" << model; + return ss.str(); + } +#endif // ELPP_OS_ANDROID + + /// @brief Runs command on terminal and returns the output. + /// + /// @detail This is applicable only on unix based systems, for all other OS, an empty string is returned. + /// @param command Bash command + /// @return Result of bash output or empty string if no result found. + static const std::string getBashOutput(const char* command) { +#if (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) + if (command == nullptr) { + return std::string(); + } + FILE* proc = nullptr; + if ((proc = popen(command, "r")) == nullptr) { + ELPP_INTERNAL_ERROR("\nUnable to run command [" << command << "]", true); + return std::string(); + } + char hBuff[4096]; + if (fgets(hBuff, sizeof(hBuff), proc) != nullptr) { + pclose(proc); + if (hBuff[strlen(hBuff) - 1] == '\n') { + hBuff[strlen(hBuff) - 1] = '\0'; + } + return std::string(hBuff); + } + return std::string(); +#else + ELPP_UNUSED(command); + return std::string(); +#endif // (ELPP_OS_UNIX && !ELPP_OS_ANDROID && !ELPP_CYGWIN) + } + + /// @brief Gets environment variable. This is cross-platform and CRT safe (for VC++) + /// @param variableName Environment variable name + /// @param defaultVal If no environment variable or value found the value to return by default + /// @param alternativeBashCommand If environment variable not found what would be alternative bash command + /// in order to look for value user is looking for. E.g, for 'user' alternative command will 'whoami' + static std::string getEnvironmentVariable(const char* variableName, const char* defaultVal, const char* alternativeBashCommand = nullptr) { +#if ELPP_OS_UNIX + const char* val = getenv(variableName); +#elif ELPP_OS_WINDOWS + const char* val = getWindowsEnvironmentVariable(variableName); +#endif // ELPP_OS_UNIX + if ((val == nullptr) || ((strcmp(val, "") == 0))) { +#if ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) + // Try harder on unix-based systems + std::string valBash = base::utils::OS::getBashOutput(alternativeBashCommand); + if (valBash.empty()) { + return std::string(defaultVal); + } + else { + return valBash; + } +#elif ELPP_OS_WINDOWS || ELPP_OS_UNIX + ELPP_UNUSED(alternativeBashCommand); + return std::string(defaultVal); +#endif // ELPP_OS_UNIX && defined(ELPP_FORCE_ENV_VAR_FROM_BASH) + } + return std::string(val); + } + /// @brief Gets current username. + static inline std::string currentUser(void) { +#if ELPP_OS_UNIX && !ELPP_OS_ANDROID + return getEnvironmentVariable("USER", base::consts::kUnknownUser, "whoami"); +#elif ELPP_OS_WINDOWS + return getEnvironmentVariable("USERNAME", base::consts::kUnknownUser); +#elif ELPP_OS_ANDROID + ELPP_UNUSED(base::consts::kUnknownUser); + return std::string("android"); +#else + return std::string(); +#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID + } + + /// @brief Gets current host name or computer name. + /// + /// @detail For android systems this is device name with its manufacturer and model seperated by hyphen + static inline std::string currentHost(void) { +#if ELPP_OS_UNIX && !ELPP_OS_ANDROID + return getEnvironmentVariable("HOSTNAME", base::consts::kUnknownHost, "hostname"); +#elif ELPP_OS_WINDOWS + return getEnvironmentVariable("COMPUTERNAME", base::consts::kUnknownHost); +#elif ELPP_OS_ANDROID + ELPP_UNUSED(base::consts::kUnknownHost); + return getDeviceName(); +#else + return std::string(); +#endif // ELPP_OS_UNIX && !ELPP_OS_ANDROID + } + /// @brief Whether or not terminal supports colors + static inline bool termSupportsColor(void) { + std::string term = getEnvironmentVariable("TERM", ""); + return term == "xterm" || term == "xterm-color" || term == "xterm-256color" || + term == "screen" || term == "linux" || term == "cygwin"; + } + }; + extern std::string s_currentUser; + extern std::string s_currentHost; + extern bool s_termSupportsColor; +#define ELPP_INITI_BASIC_DECLR \ + namespace el {\ + namespace base {\ + namespace utils {\ + std::string s_currentUser = el::base::utils::OS::currentUser(); \ + std::string s_currentHost = el::base::utils::OS::currentHost(); \ + bool s_termSupportsColor = el::base::utils::OS::termSupportsColor(); \ + }\ + }\ + } + /// @brief Contains utilities for cross-platform date/time. This class make use of el::base::utils::Str + class DateTime : base::StaticClass { + public: + /// @brief Cross platform gettimeofday for Windows and unix platform. This can be used to determine current millisecond. + /// + /// @detail For unix system it uses gettimeofday(timeval*, timezone*) and for Windows, a seperate implementation is provided + /// @param [in,out] tv Pointer that gets updated + static void gettimeofday(struct timeval* tv) { +#if ELPP_OS_WINDOWS + if (tv != nullptr) { +# if ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) + const unsigned __int64 delta_ = 11644473600000000Ui64; +# else + const unsigned __int64 delta_ = 11644473600000000ULL; +# endif // ELPP_COMPILER_MSVC || defined(_MSC_EXTENSIONS) + const double secOffSet = 0.000001; + const unsigned long usecOffSet = 1000000; + FILETIME fileTime; + GetSystemTimeAsFileTime(&fileTime); + unsigned __int64 present = 0; + present |= fileTime.dwHighDateTime; + present = present << 32; + present |= fileTime.dwLowDateTime; + present /= 10; // mic-sec + // Subtract the difference + present -= delta_; + tv->tv_sec = static_cast<long>(present * secOffSet); + tv->tv_usec = static_cast<long>(present % usecOffSet); + } +#else + ::gettimeofday(tv, nullptr); +#endif // ELPP_OS_WINDOWS + } + + /// @brief Gets current date and time with milliseconds. + /// @param format User provided date/time format + /// @param msWidth A pointer to base::MillisecondsWidth from configuration (non-null) + /// @returns string based date time in specified format. + static inline std::string getDateTime(const char* format, const base::MillisecondsWidth* msWidth) { + struct timeval currTime; + gettimeofday(&currTime); + struct ::tm timeInfo; + buildTimeInfo(&currTime, &timeInfo); + const int kBuffSize = 30; + char buff_[kBuffSize] = ""; + parseFormat(buff_, kBuffSize, format, &timeInfo, static_cast<std::size_t>(currTime.tv_usec / msWidth->m_offset), msWidth); + return std::string(buff_); + } + + /// @brief Formats time to get unit accordingly, units like second if > 1000 or minutes if > 60000 etc + static base::type::string_t formatTime(unsigned long long time, base::TimestampUnit timestampUnit) { + double result = static_cast<double>(time); + base::type::EnumType start = static_cast<base::type::EnumType>(timestampUnit); + const base::type::char_t* unit = base::consts::kTimeFormats[start].unit; + for (base::type::EnumType i = start; i < base::consts::kTimeFormatsCount - 1; ++i) { + if (result <= base::consts::kTimeFormats[i].value) { + break; + } + result /= base::consts::kTimeFormats[i].value; + unit = base::consts::kTimeFormats[i + 1].unit; + } + base::type::stringstream_t ss; + ss << result << " " << unit; + return ss.str(); + } + + /// @brief Gets time difference in milli/micro second depending on timestampUnit + static inline unsigned long long getTimeDifference(const struct timeval& endTime, const struct timeval& startTime, base::TimestampUnit timestampUnit) { + if (timestampUnit == base::TimestampUnit::Microsecond) { + return static_cast<unsigned long long>(static_cast<unsigned long long>(1000000 * endTime.tv_sec + endTime.tv_usec) - + static_cast<unsigned long long>(1000000 * startTime.tv_sec + startTime.tv_usec)); + } + else { + return static_cast<unsigned long long>((((endTime.tv_sec - startTime.tv_sec) * 1000000) + (endTime.tv_usec - startTime.tv_usec)) / 1000); + } + } + + private: + static inline struct ::tm* buildTimeInfo(struct timeval* currTime, struct ::tm* timeInfo) { +#if ELPP_OS_UNIX + time_t rawTime = currTime->tv_sec; + ::localtime_r(&rawTime, timeInfo); + return timeInfo; +#else +# if ELPP_COMPILER_MSVC + ELPP_UNUSED(currTime); + time_t t; + _time64(&t); + localtime_s(timeInfo, &t); + return timeInfo; +# else + // For any other compilers that don't have CRT warnings issue e.g, MinGW or TDM GCC- we use different method + time_t rawTime = currTime->tv_sec; + struct tm* tmInf = localtime(&rawTime); + *timeInfo = *tmInf; + return timeInfo; +# endif // ELPP_COMPILER_MSVC +#endif // ELPP_OS_UNIX + } + static char* parseFormat(char* buf, std::size_t bufSz, const char* format, const struct tm* tInfo, + std::size_t msec, const base::MillisecondsWidth* msWidth) { + const char* bufLim = buf + bufSz; + for (; *format; ++format) { + if (*format == base::consts::kFormatSpecifierChar) { + switch (*++format) { + case base::consts::kFormatSpecifierChar: // Escape + break; + case '\0': // End + --format; + break; + case 'd': // Day + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mday, 2, buf, bufLim); + continue; + case 'a': // Day of week (short) + buf = base::utils::Str::addToBuff(base::consts::kDaysAbbrev[tInfo->tm_wday], buf, bufLim); + continue; + case 'A': // Day of week (long) + buf = base::utils::Str::addToBuff(base::consts::kDays[tInfo->tm_wday], buf, bufLim); + continue; + case 'M': // month + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_mon + 1, 2, buf, bufLim); + continue; + case 'b': // month (short) + buf = base::utils::Str::addToBuff(base::consts::kMonthsAbbrev[tInfo->tm_mon], buf, bufLim); + continue; + case 'B': // month (long) + buf = base::utils::Str::addToBuff(base::consts::kMonths[tInfo->tm_mon], buf, bufLim); + continue; + case 'y': // year (two digits) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 2, buf, bufLim); + continue; + case 'Y': // year (four digits) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_year + base::consts::kYearBase, 4, buf, bufLim); + continue; + case 'h': // hour (12-hour) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour % 12, 2, buf, bufLim); + continue; + case 'H': // hour (24-hour) + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_hour, 2, buf, bufLim); + continue; + case 'm': // minute + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_min, 2, buf, bufLim); + continue; + case 's': // second + buf = base::utils::Str::convertAndAddToBuff(tInfo->tm_sec, 2, buf, bufLim); + continue; + case 'z': // milliseconds + case 'g': + buf = base::utils::Str::convertAndAddToBuff(msec, msWidth->m_width, buf, bufLim); + continue; + case 'F': // AM/PM + buf = base::utils::Str::addToBuff((tInfo->tm_hour >= 12) ? base::consts::kPm : base::consts::kAm, buf, bufLim); + continue; + default: + continue; + } + } + if (buf == bufLim) break; + *buf++ = *format; + } + return buf; + } + }; + /// @brief Command line arguments for application if specified using el::Helpers::setArgs(..) or START_EASYLOGGINGPP(..) + class CommandLineArgs { + public: + CommandLineArgs(void) { + setArgs(0, static_cast<char**>(nullptr)); + } + CommandLineArgs(int argc, const char** argv) { + setArgs(argc, argv); + } + CommandLineArgs(int argc, char** argv) { + setArgs(argc, argv); + } + virtual ~CommandLineArgs(void) {} + /// @brief Sets arguments and parses them + inline void setArgs(int argc, const char** argv) { + setArgs(argc, const_cast<char**>(argv)); + } + /// @brief Sets arguments and parses them + inline void setArgs(int argc, char** argv) { + m_params.clear(); + m_paramsWithValue.clear(); + if (argc == 0 || argv == nullptr) { + return; + } + m_argc = argc; + m_argv = argv; + for (int i = 1; i < m_argc; ++i) { + const char* v = (strstr(m_argv[i], "=")); + if (v != nullptr && strlen(v) > 0) { + std::string key = std::string(m_argv[i]); + key = key.substr(0, key.find_first_of('=')); + if (hasParamWithValue(key.c_str())) { + ELPP_INTERNAL_INFO(1, "Skipping [" << key << "] arg since it already has value [" + << getParamValue(key.c_str()) << "]"); + } + else { + m_paramsWithValue.insert(std::make_pair(key, std::string(v + 1))); + } + } + if (v == nullptr) { + if (hasParam(m_argv[i])) { + ELPP_INTERNAL_INFO(1, "Skipping [" << m_argv[i] << "] arg since it already exists"); + } + else { + m_params.push_back(std::string(m_argv[i])); + } + } + } + } + /// @brief Returns true if arguments contain paramKey with a value (seperated by '=') + inline bool hasParamWithValue(const char* paramKey) const { + return m_paramsWithValue.find(std::string(paramKey)) != m_paramsWithValue.end(); + } + /// @brief Returns value of arguments + /// @see hasParamWithValue(const char*) + inline const char* getParamValue(const char* paramKey) const { + return m_paramsWithValue.find(std::string(paramKey))->second.c_str(); + } + /// @brief Return true if arguments has a param (not having a value) i,e without '=' + inline bool hasParam(const char* paramKey) const { + return std::find(m_params.begin(), m_params.end(), std::string(paramKey)) != m_params.end(); + } + /// @brief Returns true if no params available. This exclude argv[0] + inline bool empty(void) const { + return m_params.empty() && m_paramsWithValue.empty(); + } + /// @brief Returns total number of arguments. This exclude argv[0] + inline std::size_t size(void) const { + return m_params.size() + m_paramsWithValue.size(); + } + inline friend base::type::ostream_t& operator<<(base::type::ostream_t& os, const CommandLineArgs& c) { + for (int i = 1; i < c.m_argc; ++i) { + os << ELPP_LITERAL("[") << c.m_argv[i] << ELPP_LITERAL("]"); + if (i < c.m_argc - 1) { + os << ELPP_LITERAL(" "); + } + } + return os; + } + + private: + int m_argc; + char** m_argv; + std::map<std::string, std::string> m_paramsWithValue; + std::vector<std::string> m_params; + }; + /// @brief Abstract registry (aka repository) that provides basic interface for pointer repository specified by T_Ptr type. + /// + /// @detail Most of the functions are virtual final methods but anything implementing this abstract class should implement + /// unregisterAll() and deepCopy(const AbstractRegistry<T_Ptr, Container>&) and write registerNew() method according to container + /// and few more methods; get() to find element, unregister() to unregister single entry. + /// Please note that this is thread-unsafe and should also implement thread-safety mechanisms in implementation. + template <typename T_Ptr, typename Container> + class AbstractRegistry : public base::threading::ThreadSafe { + public: + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + + /// @brief Default constructor + AbstractRegistry(void) {} + + /// @brief Move constructor that is useful for base classes + AbstractRegistry(AbstractRegistry&& sr) { + if (this == &sr) { + return; + } + unregisterAll(); + m_list = std::move(sr.m_list); + } + + bool operator==(const AbstractRegistry<T_Ptr, Container>& other) { + if (size() != other.size()) { + return false; + } + for (std::size_t i = 0; i < m_list.size(); ++i) { + if (m_list.at(i) != other.m_list.at(i)) { + return false; + } + } + return true; + } + + bool operator!=(const AbstractRegistry<T_Ptr, Container>& other) { + if (size() != other.size()) { + return true; + } + for (std::size_t i = 0; i < m_list.size(); ++i) { + if (m_list.at(i) != other.m_list.at(i)) { + return true; + } + } + return false; + } + + /// @brief Assignment move operator + AbstractRegistry& operator=(AbstractRegistry&& sr) { + if (this == &sr) { + return *this; + } + unregisterAll(); + m_list = std::move(sr.m_list); + return *this; + } + + virtual ~AbstractRegistry(void) { + } + + /// @return Iterator pointer from start of repository + virtual inline iterator begin(void) ELPP_FINAL { + return m_list.begin(); + } + + /// @return Iterator pointer from end of repository + virtual inline iterator end(void) ELPP_FINAL { + return m_list.end(); + } + + + /// @return Constant iterator pointer from start of repository + virtual inline const_iterator cbegin(void) const ELPP_FINAL { + return m_list.cbegin(); + } + + /// @return End of repository + virtual inline const_iterator cend(void) const ELPP_FINAL { + return m_list.cend(); + } + + /// @return Whether or not repository is empty + virtual inline bool empty(void) const ELPP_FINAL { + return m_list.empty(); + } + + /// @return Size of repository + virtual inline std::size_t size(void) const ELPP_FINAL { + return m_list.size(); + } + + /// @brief Returns underlying container by reference + virtual inline Container& list(void) ELPP_FINAL { + return m_list; + } + + /// @brief Returns underlying container by constant reference. + virtual inline const Container& list(void) const ELPP_FINAL { + return m_list; + } + + /// @brief Unregisters all the pointers from current repository. + virtual void unregisterAll(void) = 0; + + protected: + virtual void deepCopy(const AbstractRegistry<T_Ptr, Container>&) = 0; + void reinitDeepCopy(const AbstractRegistry<T_Ptr, Container>& sr) { + unregisterAll(); + deepCopy(sr); + } + + private: + Container m_list; + }; + + /// @brief A pointer registry mechanism to manage memory and provide search functionalities. (non-predicate version) + /// + /// @detail NOTE: This is thread-unsafe implementation (although it contains lock function, it does not use these functions) + /// of AbstractRegistry<T_Ptr, Container>. Any implementation of this class should be + /// explicitly (by using lock functions) + template <typename T_Ptr, typename T_Key = const char*> + class Registry : public AbstractRegistry<T_Ptr, std::map<T_Key, T_Ptr*>> { + public: + typedef typename Registry<T_Ptr, T_Key>::iterator iterator; + typedef typename Registry<T_Ptr, T_Key>::const_iterator const_iterator; + + Registry(void) {} + + /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. + Registry(const Registry& sr) : AbstractRegistry<T_Ptr, std::vector<T_Ptr*>>() { + if (this == &sr) { + return; + } + this->reinitDeepCopy(sr); + } + + /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element + /// @see unregisterAll() + /// @see deepCopy(const AbstractRegistry&) + Registry& operator=(const Registry& sr) { + if (this == &sr) { + return *this; + } + this->reinitDeepCopy(sr); + return *this; + } + + virtual ~Registry(void) { + unregisterAll(); + } + + protected: + virtual inline void unregisterAll(void) ELPP_FINAL { + if (!this->empty()) { + for (auto&& curr : this->list()) { + base::utils::safeDelete(curr.second); + } + this->list().clear(); + } + } + + /// @brief Registers new registry to repository. + virtual inline void registerNew(const T_Key& uniqKey, T_Ptr* ptr) ELPP_FINAL { + unregister(uniqKey); + this->list().insert(std::make_pair(uniqKey, ptr)); + } + + /// @brief Unregisters single entry mapped to specified unique key + inline void unregister(const T_Key& uniqKey) { + T_Ptr* existing = get(uniqKey); + if (existing != nullptr) { + base::utils::safeDelete(existing); + this->list().erase(uniqKey); + } + } + + /// @brief Gets pointer from repository. If none found, nullptr is returned. + inline T_Ptr* get(const T_Key& uniqKey) { + iterator it = this->list().find(uniqKey); + return it == this->list().end() + ? nullptr + : it->second; + } + + private: + virtual inline void deepCopy(const AbstractRegistry<T_Ptr, std::map<T_Key, T_Ptr*>>& sr) ELPP_FINAL { + for (const_iterator it = sr.cbegin(); it != sr.cend(); ++it) { + registerNew(it->first, new T_Ptr(*it->second)); + } + } + }; + + /// @brief A pointer registry mechanism to manage memory and provide search functionalities. (predicate version) + /// + /// @detail NOTE: This is thread-unsafe implementation of AbstractRegistry<T_Ptr, Container>. Any implementation of this class + /// should be made thread-safe explicitly + template <typename T_Ptr, typename Pred> + class RegistryWithPred : public AbstractRegistry<T_Ptr, std::vector<T_Ptr*>> { + public: + typedef typename RegistryWithPred<T_Ptr, Pred>::iterator iterator; + typedef typename RegistryWithPred<T_Ptr, Pred>::const_iterator const_iterator; + + RegistryWithPred(void) { + } + + virtual ~RegistryWithPred(void) { + unregisterAll(); + } + + /// @brief Copy constructor that is useful for base classes. Try to avoid this constructor, use move constructor. + RegistryWithPred(const RegistryWithPred& sr) : AbstractRegistry<T_Ptr, std::vector<T_Ptr*>>() { + if (this == &sr) { + return; + } + this->reinitDeepCopy(sr); + } + + /// @brief Assignment operator that unregisters all the existing registeries and deeply copies each of repo element + /// @see unregisterAll() + /// @see deepCopy(const AbstractRegistry&) + RegistryWithPred& operator=(const RegistryWithPred& sr) { + if (this == &sr) { + return *this; + } + this->reinitDeepCopy(sr); + return *this; + } + + friend inline base::type::ostream_t& operator<<(base::type::ostream_t& os, const RegistryWithPred& sr) { + for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { + os << ELPP_LITERAL(" ") << **it << ELPP_LITERAL("\n"); + } + return os; + } + + protected: + virtual inline void unregisterAll(void) ELPP_FINAL { + if (!this->empty()) { + for (auto&& curr : this->list()) { + base::utils::safeDelete(curr); + } + this->list().clear(); + } + } + + virtual void unregister(T_Ptr*& ptr) ELPP_FINAL { + if (ptr) { + iterator iter = this->begin(); + for (; iter != this->end(); ++iter) { + if (ptr == *iter) { + break; + } + } + if (iter != this->end() && *iter != nullptr) { + this->list().erase(iter); + base::utils::safeDelete(*iter); + } + } + } + + virtual inline void registerNew(T_Ptr* ptr) ELPP_FINAL { + this->list().push_back(ptr); + } + + /// @brief Gets pointer from repository with speicifed arguments. Arguments are passed to predicate + /// in order to validate pointer. + template <typename T, typename T2> + inline T_Ptr* get(const T& arg1, const T2 arg2) { + iterator iter = std::find_if(this->list().begin(), this->list().end(), Pred(arg1, arg2)); + if (iter != this->list().end() && *iter != nullptr) { + return *iter; + } + return nullptr; + } + + private: + virtual inline void deepCopy(const AbstractRegistry<T_Ptr, std::vector<T_Ptr*>>& sr) { + for (const_iterator it = sr.list().begin(); it != sr.list().end(); ++it) { + registerNew(new T_Ptr(**it)); + } + } + }; + + } // namespace utils + } // namespace base + /// @brief Base of Easylogging++ friendly class + /// + /// @detail After inheriting this class publicly, implement pure-virtual function `void log(std::ostream&) const` + class Loggable { + public: + virtual ~Loggable(void) {} + virtual void log(el::base::type::ostream_t&) const = 0; + private: + friend inline el::base::type::ostream_t& operator<<(el::base::type::ostream_t& os, const Loggable& loggable) { + loggable.log(os); + return os; + } + }; + namespace base { + /// @brief Represents log format containing flags and date format. This is used internally to start initial log + class LogFormat : public Loggable { + public: + LogFormat(void) : + m_level(Level::Unknown), + m_userFormat(base::type::string_t()), + m_format(base::type::string_t()), + m_dateTimeFormat(std::string()), + m_flags(0x0) { + } + + LogFormat(Level level, const base::type::string_t& format) + : m_level(level), m_userFormat(format) { + parseFromFormat(m_userFormat); + } + + LogFormat(const LogFormat& logFormat) { + m_level = logFormat.m_level; + m_userFormat = logFormat.m_userFormat; + m_format = logFormat.m_format; + m_dateTimeFormat = logFormat.m_dateTimeFormat; + m_flags = logFormat.m_flags; + } + + LogFormat(LogFormat&& logFormat) { + m_level = std::move(logFormat.m_level); + m_userFormat = std::move(logFormat.m_userFormat); + m_format = std::move(logFormat.m_format); + m_dateTimeFormat = std::move(logFormat.m_dateTimeFormat); + m_flags = std::move(logFormat.m_flags); + } + + LogFormat& operator=(const LogFormat& logFormat) { + m_level = logFormat.m_level; + m_userFormat = logFormat.m_userFormat; + m_dateTimeFormat = logFormat.m_dateTimeFormat; + m_flags = logFormat.m_flags; + return *this; + } + + virtual ~LogFormat(void) { + } + + inline bool operator==(const LogFormat& other) { + return m_level == other.m_level && m_userFormat == other.m_userFormat && m_format == other.m_format && + m_dateTimeFormat == other.m_dateTimeFormat && m_flags == other.m_flags; + } + + /// @brief Updates format to be used while logging. + /// @param userFormat User provided format + void parseFromFormat(const base::type::string_t& userFormat) { + // We make copy because we will be changing the format + // i.e, removing user provided date format from original format + // and then storing it. + base::type::string_t formatCopy = userFormat; + m_flags = 0x0; + auto conditionalAddFlag = [&](const base::type::char_t* specifier, base::FormatFlags flag) { + std::size_t foundAt = base::type::string_t::npos; + while ((foundAt = formatCopy.find(specifier, foundAt + 1)) != base::type::string_t::npos) { + if (foundAt > 0 && formatCopy[foundAt - 1] == base::consts::kFormatSpecifierChar) { + if (hasFlag(flag)) { + // If we already have flag we remove the escape chars so that '%%' is turned to '%' + // even after specifier resolution - this is because we only replaceFirst specifier + formatCopy.erase(foundAt > 0 ? foundAt - 1 : 0, 1); + ++foundAt; + } + } + else { + if (!hasFlag(flag)) addFlag(flag); + } + } + }; + conditionalAddFlag(base::consts::kAppNameFormatSpecifier, base::FormatFlags::AppName); + conditionalAddFlag(base::consts::kSeverityLevelFormatSpecifier, base::FormatFlags::Level); + conditionalAddFlag(base::consts::kSeverityLevelShortFormatSpecifier, base::FormatFlags::LevelShort); + conditionalAddFlag(base::consts::kLoggerIdFormatSpecifier, base::FormatFlags::LoggerId); + conditionalAddFlag(base::consts::kThreadIdFormatSpecifier, base::FormatFlags::ThreadId); + conditionalAddFlag(base::consts::kLogFileFormatSpecifier, base::FormatFlags::File); + conditionalAddFlag(base::consts::kLogFileBaseFormatSpecifier, base::FormatFlags::FileBase); + conditionalAddFlag(base::consts::kLogLineFormatSpecifier, base::FormatFlags::Line); + conditionalAddFlag(base::consts::kLogLocationFormatSpecifier, base::FormatFlags::Location); + conditionalAddFlag(base::consts::kLogFunctionFormatSpecifier, base::FormatFlags::Function); + conditionalAddFlag(base::consts::kCurrentUserFormatSpecifier, base::FormatFlags::User); + conditionalAddFlag(base::consts::kCurrentHostFormatSpecifier, base::FormatFlags::Host); + conditionalAddFlag(base::consts::kMessageFormatSpecifier, base::FormatFlags::LogMessage); + conditionalAddFlag(base::consts::kVerboseLevelFormatSpecifier, base::FormatFlags::VerboseLevel); + // For date/time we need to extract user's date format first + std::size_t dateIndex = std::string::npos; + if ((dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier)) != std::string::npos) { + while (dateIndex > 0 && formatCopy[dateIndex - 1] == base::consts::kFormatSpecifierChar) { + dateIndex = formatCopy.find(base::consts::kDateTimeFormatSpecifier, dateIndex + 1); + } + if (dateIndex != std::string::npos) { + addFlag(base::FormatFlags::DateTime); + updateDateFormat(dateIndex, formatCopy); + } + } + m_format = formatCopy; + updateFormatSpec(); + } + + inline Level level(void) const { + return m_level; + } + + inline const base::type::string_t& userFormat(void) const { + return m_userFormat; + } + + inline const base::type::string_t& format(void) const { + return m_format; + } + + inline const std::string& dateTimeFormat(void) const { + return m_dateTimeFormat; + } + + inline base::type::EnumType flags(void) const { + return m_flags; + } + + inline bool hasFlag(base::FormatFlags flag) const { + return base::utils::hasFlag(flag, m_flags); + } + + virtual void log(el::base::type::ostream_t& os) const { + os << m_format; + } + + protected: + /// @brief Updates date time format if available in currFormat. + /// @param index Index where %datetime, %date or %time was found + /// @param [in,out] currFormat current format that is being used to format + virtual void updateDateFormat(std::size_t index, base::type::string_t& currFormat) ELPP_FINAL { + if (hasFlag(base::FormatFlags::DateTime)) { + index += ELPP_STRLEN(base::consts::kDateTimeFormatSpecifier); + } + const base::type::char_t* ptr = currFormat.c_str() + index; + if ((currFormat.size() > index) && (ptr[0] == '{')) { + // User has provided format for date/time + ++ptr; + int count = 1; // Start by 1 in order to remove starting brace + std::stringstream ss; + for (; *ptr; ++ptr, ++count) { + if (*ptr == '}') { + ++count; // In order to remove ending brace + break; + } + ss << *ptr; + } + currFormat.erase(index, count); + m_dateTimeFormat = ss.str(); + } + else { + // No format provided, use default + if (hasFlag(base::FormatFlags::DateTime)) { + m_dateTimeFormat = std::string(base::consts::kDefaultDateTimeFormat); + } + } + } + + /// @brief Updates %level from format. This is so that we dont have to do it at log-writing-time. It uses m_format and m_level + virtual void updateFormatSpec(void) ELPP_FINAL { + // Do not use switch over strongly typed enums because Intel C++ compilers dont support them yet. + if (m_level == Level::Debug) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kDebugLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kDebugLevelShortLogValue); + } + else if (m_level == Level::Info) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kInfoLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kInfoLevelShortLogValue); + } + else if (m_level == Level::Warning) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kWarningLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kWarningLevelShortLogValue); + } + else if (m_level == Level::Error) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kErrorLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kErrorLevelShortLogValue); + } + else if (m_level == Level::Fatal) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kFatalLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kFatalLevelShortLogValue); + } + else if (m_level == Level::Verbose) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kVerboseLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kVerboseLevelShortLogValue); + } + else if (m_level == Level::Trace) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelFormatSpecifier, + base::consts::kTraceLevelLogValue); + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kSeverityLevelShortFormatSpecifier, + base::consts::kTraceLevelShortLogValue); + } + if (hasFlag(base::FormatFlags::User)) { + std::string s = base::utils::s_currentUser; + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentUserFormatSpecifier, + base::utils::s_currentUser); + } + if (hasFlag(base::FormatFlags::Host)) { + base::utils::Str::replaceFirstWithEscape(m_format, base::consts::kCurrentHostFormatSpecifier, + base::utils::s_currentHost); + } + // Ignore Level::Global and Level::Unknown + } + + inline void addFlag(base::FormatFlags flag) { + base::utils::addFlag(flag, &m_flags); + } + + private: + Level m_level; + base::type::string_t m_userFormat; + base::type::string_t m_format; + std::string m_dateTimeFormat; + base::type::EnumType m_flags; + friend class el::Logger; // To resolve loggerId format specifier easily + }; + } // namespace base + /// @brief Resolving function for format specifier + typedef std::function<const char*(void)> FormatSpecifierValueResolver; + /// @brief User-provided custom format specifier + /// @see el::Helpers::installCustomFormatSpecifier + /// @see FormatSpecifierValueResolver + class CustomFormatSpecifier { + public: + CustomFormatSpecifier(const char* formatSpecifier, const FormatSpecifierValueResolver& resolver) : + m_formatSpecifier(formatSpecifier), m_resolver(resolver) {} + inline const char* formatSpecifier(void) const { return m_formatSpecifier; } + inline const FormatSpecifierValueResolver& resolver(void) const { return m_resolver; } + inline bool operator==(const char* formatSpecifier) { + return strcmp(m_formatSpecifier, formatSpecifier) == 0; + } + + private: + const char* m_formatSpecifier; + FormatSpecifierValueResolver m_resolver; + }; + /// @brief Represents single configuration that has representing level, configuration type and a string based value. + /// + /// @detail String based value means any value either its boolean, integer or string itself, it will be embedded inside quotes + /// and will be parsed later. + /// + /// Consider some examples below: + /// * el::Configuration confEnabledInfo(el::Level::Info, el::ConfigurationType::Enabled, "true"); + /// * el::Configuration confMaxLogFileSizeInfo(el::Level::Info, el::ConfigurationType::MaxLogFileSize, "2048"); + /// * el::Configuration confFilenameInfo(el::Level::Info, el::ConfigurationType::Filename, "/var/log/my.log"); + class Configuration : public Loggable { + public: + Configuration(const Configuration& c) : + m_level(c.m_level), + m_configurationType(c.m_configurationType), + m_value(c.m_value) { + } + + Configuration& operator=(const Configuration& c) { + m_level = c.m_level; + m_configurationType = c.m_configurationType; + m_value = c.m_value; + return *this; + } + + virtual ~Configuration(void) { + } + + /// @brief Full constructor used to sets value of configuration + Configuration(Level level, ConfigurationType configurationType, const std::string& value) : + m_level(level), + m_configurationType(configurationType), + m_value(value) { + } + + /// @brief Gets level of current configuration + inline Level level(void) const { + return m_level; + } + + /// @brief Gets configuration type of current configuration + inline ConfigurationType configurationType(void) const { + return m_configurationType; + } + + /// @brief Gets string based configuration value + inline const std::string& value(void) const { + return m_value; + } + + /// @brief Set string based configuration value + /// @param value Value to set. Values have to be std::string; For boolean values use "true", "false", for any integral values + /// use them in quotes. They will be parsed when configuring + inline void setValue(const std::string& value) { + m_value = value; + } + + virtual inline void log(el::base::type::ostream_t& os) const { + os << LevelHelper::convertToString(m_level) + << ELPP_LITERAL(" ") << ConfigurationTypeHelper::convertToString(m_configurationType) + << ELPP_LITERAL(" = ") << m_value.c_str(); + } + + /// @brief Used to find configuration from configuration (pointers) repository. Avoid using it. + class Predicate { + public: + Predicate(Level level, ConfigurationType configurationType) : + m_level(level), + m_configurationType(configurationType) { + } + + inline bool operator()(const Configuration* conf) const { + return ((conf != nullptr) && (conf->level() == m_level) && (conf->configurationType() == m_configurationType)); + } + + private: + Level m_level; + ConfigurationType m_configurationType; + }; + + private: + Level m_level; + ConfigurationType m_configurationType; + std::string m_value; + }; + + /// @brief Thread-safe Configuration repository + /// + /// @detail This repository represents configurations for all the levels and configuration type mapped to a value. + class Configurations : public base::utils::RegistryWithPred<Configuration, Configuration::Predicate> { + public: + /// @brief Default constructor with empty repository + Configurations(void) : + m_configurationFile(std::string()), + m_isFromFile(false) { + } + + /// @brief Constructor used to set configurations using configuration file. + /// @param configurationFile Full path to configuration file + /// @param useDefaultsForRemaining Lets you set the remaining configurations to default. + /// @param base If provided, this configuration will be based off existing repository that this argument is pointing to. + /// @see parseFromFile(const std::string&, Configurations* base) + /// @see setRemainingToDefault() + Configurations(const std::string& configurationFile, bool useDefaultsForRemaining = true, Configurations* base = nullptr) : + m_configurationFile(configurationFile), + m_isFromFile(false) { + parseFromFile(configurationFile, base); + if (useDefaultsForRemaining) { + setRemainingToDefault(); + } + } + + virtual ~Configurations(void) { + } + + /// @brief Parses configuration from file. + /// @param configurationFile Full path to configuration file + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration file. + /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you + /// do not proceed without successful parse. + inline bool parseFromFile(const std::string& configurationFile, Configurations* base = nullptr) { + // We initial assertion with true because if we have assertion diabled, we want to pass this + // check and if assertion is enabled we will have values re-assigned any way. + bool assertionPassed = true; + ELPP_ASSERT((assertionPassed = base::utils::File::pathExists(configurationFile.c_str(), true)), + "Configuration file [" << configurationFile << "] does not exist!"); + if (!assertionPassed) { + return false; + } + bool success = Parser::parseFromFile(configurationFile, this, base); + m_isFromFile = success; + return success; + } + + /// @brief Parse configurations from configuration string. + /// + /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary + /// new line characters are provided. + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration text. + /// @return True if successfully parsed, false otherwise. You may define 'ELPP_DEBUG_ASSERT_FAILURE' to make sure you + /// do not proceed without successful parse. + inline bool parseFromText(const std::string& configurationsString, Configurations* base = nullptr) { + bool success = Parser::parseFromText(configurationsString, this, base); + if (success) { + m_isFromFile = false; + } + return success; + } + + /// @brief Sets configuration based-off an existing configurations. + /// @param base Pointer to existing configurations. + inline void setFromBase(Configurations* base) { + if (base == nullptr || base == this) { + return; + } + base::threading::ScopedLock scopedLock(base->lock()); + for (Configuration*& conf : base->list()) { + set(conf); + } + } + + /// @brief Determines whether or not specified configuration type exists in the repository. + /// + /// @detail Returns as soon as first level is found. + /// @param configurationType Type of configuration to check existence for. + bool hasConfiguration(ConfigurationType configurationType) { + base::type::EnumType lIndex = LevelHelper::kMinValid; + bool result = false; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + if (hasConfiguration(LevelHelper::castFromInt(lIndex), configurationType)) { + result = true; + } + return result; + }); + return result; + } + + /// @brief Determines whether or not specified configuration type exists for specified level + /// @param level Level to check + /// @param configurationType Type of configuration to check existence for. + inline bool hasConfiguration(Level level, ConfigurationType configurationType) { + base::threading::ScopedLock scopedLock(lock()); +#if ELPP_COMPILER_INTEL + // We cant specify template types here, Intel C++ throws compilation error + // "error: type name is not allowed" + return RegistryWithPred::get(level, configurationType) != nullptr; +#else + return RegistryWithPred<Configuration, Configuration::Predicate>::get(level, configurationType) != nullptr; +#endif // ELPP_COMPILER_INTEL + } + + /// @brief Sets value of configuration for specified level. + /// + /// @detail Any existing configuration for specified level will be replaced. Also note that configuration types + /// ConfigurationType::MillisecondsWidth and ConfigurationType::PerformanceTracking will be ignored if not set for + /// Level::Global because these configurations are not dependant on level. + /// @param level Level to set configuration for (el::Level). + /// @param configurationType Type of configuration (el::ConfigurationType) + /// @param value A string based value. Regardless of what the data type of configuration is, it will always be string + /// from users' point of view. This is then parsed later to be used internally. + /// @see Configuration::setValue(const std::string& value) + /// @see el::Level + /// @see el::ConfigurationType + inline void set(Level level, ConfigurationType configurationType, const std::string& value) { + base::threading::ScopedLock scopedLock(lock()); + unsafeSet(level, configurationType, value); // This is not unsafe anymore as we have locked mutex + if (level == Level::Global) { + unsafeSetGlobally(configurationType, value, false); // Again this is not unsafe either + } + } + + /// @brief Sets single configuration based on other single configuration. + /// @see set(Level level, ConfigurationType configurationType, const std::string& value) + inline void set(Configuration* conf) { + if (conf == nullptr) { + return; + } + set(conf->level(), conf->configurationType(), conf->value()); + } + + inline Configuration* get(Level level, ConfigurationType configurationType) { + base::threading::ScopedLock scopedLock(lock()); + return RegistryWithPred<Configuration, Configuration::Predicate>::get(level, configurationType); + } + + /// @brief Sets configuration for all levels. + /// @param configurationType Type of configuration + /// @param value String based value + /// @see Configurations::set(Level level, ConfigurationType configurationType, const std::string& value) + inline void setGlobally(ConfigurationType configurationType, const std::string& value) { + setGlobally(configurationType, value, false); + } + + /// @brief Clears repository so that all the configurations are unset + inline void clear(void) { + base::threading::ScopedLock scopedLock(lock()); + unregisterAll(); + } + + /// @brief Gets configuration file used in parsing this configurations. + /// + /// @detail If this repository was set manually or by text this returns empty string. + inline const std::string& configurationFile(void) const { + return m_configurationFile; + } + + /// @brief Sets configurations to "factory based" configurations. + void setToDefault(void) { + setGlobally(ConfigurationType::Enabled, std::string("true"), true); +#if !defined(ELPP_NO_DEFAULT_LOG_FILE) + setGlobally(ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile), true); +#else + ELPP_UNUSED(base::consts::kDefaultLogFile); +#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) + setGlobally(ConfigurationType::ToFile, std::string("true"), true); + setGlobally(ConfigurationType::ToStandardOutput, std::string("true"), true); + setGlobally(ConfigurationType::MillisecondsWidth, std::string("3"), true); + setGlobally(ConfigurationType::PerformanceTracking, std::string("true"), true); + setGlobally(ConfigurationType::MaxLogFileSize, std::string("0"), true); + setGlobally(ConfigurationType::LogFlushThreshold, std::string("0"), true); + + setGlobally(ConfigurationType::Format, std::string("%datetime %level [%logger] %msg"), true); + set(Level::Debug, ConfigurationType::Format, std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); + // INFO and WARNING are set to default by Level::Global + set(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + set(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + set(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); + set(Level::Trace, ConfigurationType::Format, std::string("%datetime %level [%logger] [%func] [%loc] %msg")); + } + + /// @brief Lets you set the remaining configurations to default. + /// + /// @detail By remaining, it means that the level/type a configuration does not exist for. + /// This function is useful when you want to minimize chances of failures, e.g, if you have a configuration file that sets + /// configuration for all the configurations except for Enabled or not, we use this so that ENABLED is set to default i.e, + /// true. If you dont do this explicitley (either by calling this function or by using second param in Constructor + /// and try to access a value, an error is thrown + void setRemainingToDefault(void) { + base::threading::ScopedLock scopedLock(lock()); + unsafeSetIfNotExist(Level::Global, ConfigurationType::Enabled, std::string("true")); +#if !defined(ELPP_NO_DEFAULT_LOG_FILE) + unsafeSetIfNotExist(Level::Global, ConfigurationType::Filename, std::string(base::consts::kDefaultLogFile)); +#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) + unsafeSetIfNotExist(Level::Global, ConfigurationType::ToFile, std::string("true")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::ToStandardOutput, std::string("true")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::MillisecondsWidth, std::string("3")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::PerformanceTracking, std::string("true")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::MaxLogFileSize, std::string("0")); + unsafeSetIfNotExist(Level::Global, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + unsafeSetIfNotExist(Level::Debug, ConfigurationType::Format, + std::string("%datetime %level [%logger] [%user@%host] [%func] [%loc] %msg")); + // INFO and WARNING are set to default by Level::Global + unsafeSetIfNotExist(Level::Error, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + unsafeSetIfNotExist(Level::Fatal, ConfigurationType::Format, std::string("%datetime %level [%logger] %msg")); + unsafeSetIfNotExist(Level::Verbose, ConfigurationType::Format, std::string("%datetime %level-%vlevel [%logger] %msg")); + unsafeSetIfNotExist(Level::Trace, ConfigurationType::Format, std::string("%datetime %level [%logger] [%func] [%loc] %msg")); + } + + /// @brief Parser used internally to parse configurations from file or text. + /// + /// @detail This class makes use of base::utils::Str. + /// You should not need this unless you are working on some tool for Easylogging++ + class Parser : base::StaticClass { + public: + /// @brief Parses configuration from file. + /// @param configurationFile Full path to configuration file + /// @param sender Sender configurations pointer. Usually 'this' is used from calling class + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration file. + /// @return True if successfully parsed, false otherwise. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you + /// do not proceed without successful parse. + static bool parseFromFile(const std::string& configurationFile, Configurations* sender, Configurations* base = nullptr) { + sender->setFromBase(base); + std::ifstream fileStream_(configurationFile.c_str(), std::ifstream::in); + ELPP_ASSERT(fileStream_.is_open(), "Unable to open configuration file [" << configurationFile << "] for parsing."); + bool parsedSuccessfully = false; + std::string line = std::string(); + Level currLevel = Level::Unknown; + std::string currConfigStr = std::string(); + std::string currLevelStr = std::string(); + while (fileStream_.good()) { + std::getline(fileStream_, line); + parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); + ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); + } + return parsedSuccessfully; + } + + /// @brief Parse configurations from configuration string. + /// + /// @detail This configuration string has same syntax as configuration file contents. Make sure all the necessary + /// new line characters are provided. You may define '_STOP_ON_FIRSTELPP_ASSERTION' to make sure you + /// do not proceed without successful parse (This is recommended) + /// @param configurationsString + /// @param sender Sender configurations pointer. Usually 'this' is used from calling class + /// @param base Configurations to base new configuration repository off. This value is used when you want to use + /// existing Configurations to base all the values and then set rest of configuration via configuration text. + /// @return True if successfully parsed, false otherwise. + static bool parseFromText(const std::string& configurationsString, Configurations* sender, Configurations* base = nullptr) { + sender->setFromBase(base); + bool parsedSuccessfully = false; + std::stringstream ss(configurationsString); + std::string line = std::string(); + Level currLevel = Level::Unknown; + std::string currConfigStr = std::string(); + std::string currLevelStr = std::string(); + while (std::getline(ss, line)) { + parsedSuccessfully = parseLine(&line, &currConfigStr, &currLevelStr, &currLevel, sender); + ELPP_ASSERT(parsedSuccessfully, "Unable to parse configuration line: " << line); + } + return parsedSuccessfully; + } + + private: + friend class el::Loggers; + static void ignoreComments(std::string* line) { + std::size_t foundAt = 0; + std::size_t quotesStart = line->find("\""); + std::size_t quotesEnd = std::string::npos; + if (quotesStart != std::string::npos) { + quotesEnd = line->find("\"", quotesStart + 1); + while (quotesEnd != std::string::npos && line->at(quotesEnd - 1) == '\\') { + // Do not erase slash yet - we will erase it in parseLine(..) while loop + quotesEnd = line->find("\"", quotesEnd + 2); + } + } + if ((foundAt = line->find(base::consts::kConfigurationComment)) != std::string::npos) { + if (foundAt < quotesEnd) { + foundAt = line->find(base::consts::kConfigurationComment, quotesEnd + 1); + } + *line = line->substr(0, foundAt); + } + } + static inline bool isLevel(const std::string& line) { + return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLevel)); + } + + static inline bool isComment(const std::string& line) { + return base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationComment)); + } + + static inline bool isConfig(const std::string& line) { + std::size_t assignment = line.find('='); + return line != "" && + (line[0] >= 65 || line[0] <= 90 || line[0] >= 97 || line[0] <= 122) && + (assignment != std::string::npos) && + (line.size() > assignment); + } + + static bool parseLine(std::string* line, std::string* currConfigStr, std::string* currLevelStr, Level* currLevel, Configurations* conf) { + ConfigurationType currConfig = ConfigurationType::Unknown; + std::string currValue = std::string(); + *line = base::utils::Str::trim(*line); + if (isComment(*line)) return true; + ignoreComments(line); + *line = base::utils::Str::trim(*line); + if (line->empty()) { + // Comment ignored + return true; + } + if (isLevel(*line)) { + if (line->size() <= 2) { + return true; + } + *currLevelStr = line->substr(1, line->size() - 2); + *currLevelStr = base::utils::Str::toUpper(*currLevelStr); + *currLevelStr = base::utils::Str::trim(*currLevelStr); + *currLevel = LevelHelper::convertFromString(currLevelStr->c_str()); + return true; + } + if (isConfig(*line)) { + std::size_t assignment = line->find('='); + *currConfigStr = line->substr(0, assignment); + *currConfigStr = base::utils::Str::toUpper(*currConfigStr); + *currConfigStr = base::utils::Str::trim(*currConfigStr); + currConfig = ConfigurationTypeHelper::convertFromString(currConfigStr->c_str()); + currValue = line->substr(assignment + 1); + currValue = base::utils::Str::trim(currValue); + std::size_t quotesStart = currValue.find("\"", 0); + std::size_t quotesEnd = std::string::npos; + if (quotesStart != std::string::npos) { + quotesEnd = currValue.find("\"", quotesStart + 1); + while (quotesEnd != std::string::npos && currValue.at(quotesEnd - 1) == '\\') { + currValue = currValue.erase(quotesEnd - 1, 1); + quotesEnd = currValue.find("\"", quotesEnd + 2); + } + } + if (quotesStart != std::string::npos && quotesEnd != std::string::npos) { + // Quote provided - check and strip if valid + ELPP_ASSERT((quotesStart < quotesEnd), "Configuration error - No ending quote found in [" + << currConfigStr << "]"); + ELPP_ASSERT((quotesStart + 1 != quotesEnd), "Empty configuration value for [" << currConfigStr << "]"); + if ((quotesStart != quotesEnd) && (quotesStart + 1 != quotesEnd)) { + // Explicit check in case if assertion is disabled + currValue = currValue.substr(quotesStart + 1, quotesEnd - 1); + } + } + } + ELPP_ASSERT(*currLevel != Level::Unknown, "Unrecognized severity level [" << *currLevelStr << "]"); + ELPP_ASSERT(currConfig != ConfigurationType::Unknown, "Unrecognized configuration [" << *currConfigStr << "]"); + if (*currLevel == Level::Unknown || currConfig == ConfigurationType::Unknown) { + return false; // unrecognizable level or config + } + conf->set(*currLevel, currConfig, currValue); + return true; + } + }; + + private: + std::string m_configurationFile; + bool m_isFromFile; + friend class el::Loggers; + + /// @brief Unsafely sets configuration if does not already exist + void unsafeSetIfNotExist(Level level, ConfigurationType configurationType, const std::string& value) { + Configuration* conf = RegistryWithPred<Configuration, Configuration::Predicate>::get(level, configurationType); + if (conf == nullptr) { + unsafeSet(level, configurationType, value); + } + } + + /// @brief Thread unsafe set + void unsafeSet(Level level, ConfigurationType configurationType, const std::string& value) { + Configuration* conf = RegistryWithPred<Configuration, Configuration::Predicate>::get(level, configurationType); + if (conf == nullptr) { + registerNew(new Configuration(level, configurationType, value)); + } + else { + conf->setValue(value); + } + if (level == Level::Global) { + unsafeSetGlobally(configurationType, value, false); + } + } + + /// @brief Sets configurations for all levels including Level::Global if includeGlobalLevel is true + /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) + void setGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel) { + if (includeGlobalLevel) { + set(Level::Global, configurationType, value); + } + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + set(LevelHelper::castFromInt(lIndex), configurationType, value); + return false; // Do not break lambda function yet as we need to set all levels regardless + }); + } + + /// @brief Sets configurations (Unsafely) for all levels including Level::Global if includeGlobalLevel is true + /// @see Configurations::setGlobally(ConfigurationType configurationType, const std::string& value) + void unsafeSetGlobally(ConfigurationType configurationType, const std::string& value, bool includeGlobalLevel) { + if (includeGlobalLevel) { + unsafeSet(Level::Global, configurationType, value); + } + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + unsafeSet(LevelHelper::castFromInt(lIndex), configurationType, value); + return false; // Do not break lambda function yet as we need to set all levels regardless + }); + } + }; + + namespace base { + typedef std::shared_ptr<base::type::fstream_t> FileStreamPtr; + typedef std::map<std::string, FileStreamPtr> LogStreamsReferenceMap; + /// @brief Configurations with data types. + /// + /// @detail el::Configurations have string based values. This is whats used internally in order to read correct configurations. + /// This is to perform faster while writing logs using correct configurations. + /// + /// This is thread safe and final class containing non-virtual destructor (means nothing should inherit this class) + class TypedConfigurations : public base::threading::ThreadSafe { + public: + /// @brief Constructor to initialize (construct) the object off el::Configurations + /// @param configurations Configurations pointer/reference to base this typed configurations off. + /// @param logStreamsReference Use ELPP->registeredLoggers()->logStreamsReference() + TypedConfigurations(Configurations* configurations, base::LogStreamsReferenceMap* logStreamsReference) { + m_configurations = configurations; + m_logStreamsReference = logStreamsReference; + build(m_configurations); + } + + TypedConfigurations(const TypedConfigurations& other) { + this->m_configurations = other.m_configurations; + this->m_logStreamsReference = other.m_logStreamsReference; + build(m_configurations); + } + + virtual ~TypedConfigurations(void) { + } + + const Configurations* configurations(void) const { + return m_configurations; + } + + inline bool enabled(Level level) { + return getConfigByVal<bool>(level, &m_enabledMap, "enabled"); + } + + inline bool toFile(Level level) { + return getConfigByVal<bool>(level, &m_toFileMap, "toFile"); + } + + inline const std::string& filename(Level level) { + return getConfigByRef<std::string>(level, &m_filenameMap, "filename"); + } + + inline bool toStandardOutput(Level level) { + return getConfigByVal<bool>(level, &m_toStandardOutputMap, "toStandardOutput"); + } + + inline const base::LogFormat& logFormat(Level level) { + return getConfigByRef<base::LogFormat>(level, &m_logFormatMap, "logFormat"); + } + + inline const base::MillisecondsWidth& millisecondsWidth(Level level = Level::Global) { + return getConfigByRef<base::MillisecondsWidth>(level, &m_millisecondsWidthMap, "millisecondsWidth"); + } + + inline bool performanceTracking(Level level = Level::Global) { + return getConfigByVal<bool>(level, &m_performanceTrackingMap, "performanceTracking"); + } + + inline base::type::fstream_t* fileStream(Level level) { + return getConfigByRef<base::FileStreamPtr>(level, &m_fileStreamMap, "fileStream").get(); + } + + inline std::size_t maxLogFileSize(Level level) { + return getConfigByVal<std::size_t>(level, &m_maxLogFileSizeMap, "maxLogFileSize"); + } + + inline std::size_t logFlushThreshold(Level level) { + return getConfigByVal<std::size_t>(level, &m_logFlushThresholdMap, "logFlushThreshold"); + } + + private: + Configurations* m_configurations; + std::map<Level, bool> m_enabledMap; + std::map<Level, bool> m_toFileMap; + std::map<Level, std::string> m_filenameMap; + std::map<Level, bool> m_toStandardOutputMap; + std::map<Level, base::LogFormat> m_logFormatMap; + std::map<Level, base::MillisecondsWidth> m_millisecondsWidthMap; + std::map<Level, bool> m_performanceTrackingMap; + std::map<Level, base::FileStreamPtr> m_fileStreamMap; + std::map<Level, std::size_t> m_maxLogFileSizeMap; + std::map<Level, std::size_t> m_logFlushThresholdMap; + base::LogStreamsReferenceMap* m_logStreamsReference; + + friend class el::Helpers; + friend class el::base::MessageBuilder; + friend class el::base::Writer; + friend class el::base::DefaultLogDispatchCallback; + friend class el::base::LogDispatcher; + + template <typename Conf_T> + inline Conf_T getConfigByVal(Level level, const std::map<Level, Conf_T>* confMap, const char* confName) { + base::threading::ScopedLock scopedLock(lock()); + return unsafeGetConfigByVal(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope + } + + template <typename Conf_T> + inline Conf_T& getConfigByRef(Level level, std::map<Level, Conf_T>* confMap, const char* confName) { + base::threading::ScopedLock scopedLock(lock()); + return unsafeGetConfigByRef(level, confMap, confName); // This is not unsafe anymore - mutex locked in scope + } + + template <typename Conf_T> + inline Conf_T unsafeGetConfigByVal(Level level, const std::map<Level, Conf_T>* confMap, const char* confName) { + ELPP_UNUSED(confName); + typename std::map<Level, Conf_T>::const_iterator it = confMap->find(level); + if (it == confMap->end()) { + try { + return confMap->at(Level::Global); + } + catch (...) { + ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" + << LevelHelper::convertToString(level) << "]" + << std::endl << "Please ensure you have properly configured logger.", false); + return Conf_T(); + } + } + return it->second; + } + + template <typename Conf_T> + inline Conf_T& unsafeGetConfigByRef(Level level, std::map<Level, Conf_T>* confMap, const char* confName) { + ELPP_UNUSED(confName); + typename std::map<Level, Conf_T>::iterator it = confMap->find(level); + if (it == confMap->end()) { + try { + return confMap->at(Level::Global); + } + catch (...) { + ELPP_INTERNAL_ERROR("Unable to get configuration [" << confName << "] for level [" + << LevelHelper::convertToString(level) << "]" + << std::endl << "Please ensure you have properly configured logger.", false); + } + } + return it->second; + } + + template <typename Conf_T> + void setValue(Level level, const Conf_T& value, std::map<Level, Conf_T>* confMap, bool includeGlobalLevel = true) { + // If map is empty and we are allowed to add into generic level (Level::Global), do it! + if (confMap->empty() && includeGlobalLevel) { + confMap->insert(std::make_pair(Level::Global, value)); + return; + } + // If same value exist in generic level already, dont add it to explicit level + typename std::map<Level, Conf_T>::iterator it = confMap->find(Level::Global); + if (it != confMap->end() && it->second == value) { + return; + } + // Now make sure we dont double up values if we really need to add it to explicit level + it = confMap->find(level); + if (it == confMap->end()) { + // Value not found for level, add new + confMap->insert(std::make_pair(level, value)); + } + else { + // Value found, just update value + confMap->at(level) = value; + } + } + + void build(Configurations* configurations) { + base::threading::ScopedLock scopedLock(lock()); + auto getBool = [](std::string boolStr) -> bool { // Pass by value for trimming + base::utils::Str::trim(boolStr); + return (boolStr == "TRUE" || boolStr == "true" || boolStr == "1"); + }; + std::vector<Configuration*> withFileSizeLimit; + for (Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) { + Configuration* conf = *it; + // We cannot use switch on strong enums because Intel C++ dont support them yet + if (conf->configurationType() == ConfigurationType::Enabled) { + setValue(conf->level(), getBool(conf->value()), &m_enabledMap); + } + else if (conf->configurationType() == ConfigurationType::ToFile) { + setValue(conf->level(), getBool(conf->value()), &m_toFileMap); + } + else if (conf->configurationType() == ConfigurationType::ToStandardOutput) { + setValue(conf->level(), getBool(conf->value()), &m_toStandardOutputMap); + } + else if (conf->configurationType() == ConfigurationType::Filename) { + // We do not yet configure filename but we will configure in another + // loop. This is because if file cannot be created, we will force ToFile + // to be false. Because configuring logger is not necessarily performance + // sensative operation, we can live with another loop; (by the way this loop + // is not very heavy either) + } + else if (conf->configurationType() == ConfigurationType::Format) { + setValue(conf->level(), base::LogFormat(conf->level(), + base::type::string_t(conf->value().begin(), conf->value().end())), &m_logFormatMap); + } + else if (conf->configurationType() == ConfigurationType::MillisecondsWidth) { + setValue(Level::Global, + base::MillisecondsWidth(static_cast<int>(getULong(conf->value()))), &m_millisecondsWidthMap); + } + else if (conf->configurationType() == ConfigurationType::PerformanceTracking) { + setValue(Level::Global, getBool(conf->value()), &m_performanceTrackingMap); + } + else if (conf->configurationType() == ConfigurationType::MaxLogFileSize) { + setValue(conf->level(), static_cast<std::size_t>(getULong(conf->value())), &m_maxLogFileSizeMap); +#if !defined(ELPP_NO_DEFAULT_LOG_FILE) + withFileSizeLimit.push_back(conf); +#endif // !defined(ELPP_NO_DEFAULT_LOG_FILE) + } + else if (conf->configurationType() == ConfigurationType::LogFlushThreshold) { + setValue(conf->level(), static_cast<std::size_t>(getULong(conf->value())), &m_logFlushThresholdMap); + } + } + // As mentioned early, we will now set filename configuration in separate loop to deal with non-existent files + for (Configurations::const_iterator it = configurations->begin(); it != configurations->end(); ++it) { + Configuration* conf = *it; + if (conf->configurationType() == ConfigurationType::Filename) { + insertFile(conf->level(), conf->value()); + } + } + for (std::vector<Configuration*>::iterator conf = withFileSizeLimit.begin(); + conf != withFileSizeLimit.end(); ++conf) { + // This is not unsafe as mutex is locked in currect scope + unsafeValidateFileRolling((*conf)->level(), base::defaultPreRollOutCallback); + } + } + + unsigned long getULong(std::string confVal) { + bool valid = true; + base::utils::Str::trim(confVal); + valid = !confVal.empty() && std::find_if(confVal.begin(), confVal.end(), + [](char c) { return !base::utils::Str::isDigit(c); }) == confVal.end(); + if (!valid) { + valid = false; + ELPP_ASSERT(valid, "Configuration value not a valid integer [" << confVal << "]"); + return 0; + } + return atol(confVal.c_str()); + } + + std::string resolveFilename(const std::string& filename) { + std::string resultingFilename = filename; + std::size_t dateIndex = std::string::npos; + std::string dateTimeFormatSpecifierStr = std::string(base::consts::kDateTimeFormatSpecifierForFilename); + if ((dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str())) != std::string::npos) { + while (dateIndex > 0 && resultingFilename[dateIndex - 1] == base::consts::kFormatSpecifierChar) { + dateIndex = resultingFilename.find(dateTimeFormatSpecifierStr.c_str(), dateIndex + 1); + } + if (dateIndex != std::string::npos) { + const char* ptr = resultingFilename.c_str() + dateIndex; + // Goto end of specifier + ptr += dateTimeFormatSpecifierStr.size(); + std::string fmt; + if ((resultingFilename.size() > dateIndex) && (ptr[0] == '{')) { + // User has provided format for date/time + ++ptr; + int count = 1; // Start by 1 in order to remove starting brace + std::stringstream ss; + for (; *ptr; ++ptr, ++count) { + if (*ptr == '}') { + ++count; // In order to remove ending brace + break; + } + ss << *ptr; + } + resultingFilename.erase(dateIndex + dateTimeFormatSpecifierStr.size(), count); + fmt = ss.str(); + } + else { + fmt = std::string(base::consts::kDefaultDateTimeFormatInFilename); + } + base::MillisecondsWidth msWidth(3); + std::string now = base::utils::DateTime::getDateTime(fmt.c_str(), &msWidth); + base::utils::Str::replaceAll(now, '/', '-'); // Replace path element since we are dealing with filename + base::utils::Str::replaceAll(resultingFilename, dateTimeFormatSpecifierStr, now); + } + } + return resultingFilename; + } + + void insertFile(Level level, const std::string& fullFilename) { + std::string resolvedFilename = resolveFilename(fullFilename); + if (resolvedFilename.empty()) { + std::cerr << "Could not load empty file for logging, please re-check your configurations for level [" + << LevelHelper::convertToString(level) << "]"; + } + std::string filePath = base::utils::File::extractPathFromFilename(resolvedFilename, base::consts::kFilePathSeperator); + if (filePath.size() < resolvedFilename.size()) { + base::utils::File::createPath(filePath); + } + auto create = [&](Level level) { + base::LogStreamsReferenceMap::iterator filestreamIter = m_logStreamsReference->find(resolvedFilename); + base::type::fstream_t* fs = nullptr; + if (filestreamIter == m_logStreamsReference->end()) { + // We need a completely new stream, nothing to share with + fs = base::utils::File::newFileStream(resolvedFilename); + m_filenameMap.insert(std::make_pair(level, resolvedFilename)); + m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(fs))); + m_logStreamsReference->insert(std::make_pair(resolvedFilename, base::FileStreamPtr(m_fileStreamMap.at(level)))); + } + else { + // Woops! we have an existing one, share it! + m_filenameMap.insert(std::make_pair(level, filestreamIter->first)); + m_fileStreamMap.insert(std::make_pair(level, base::FileStreamPtr(filestreamIter->second))); + fs = filestreamIter->second.get(); + } + if (fs == nullptr) { + // We display bad file error from newFileStream() + ELPP_INTERNAL_ERROR("Setting [TO_FILE] of [" + << LevelHelper::convertToString(level) << "] to FALSE", false); + setValue(level, false, &m_toFileMap); + } + }; + // If we dont have file conf for any level, create it for Level::Global first + // otherwise create for specified level + create(m_filenameMap.empty() && m_fileStreamMap.empty() ? Level::Global : level); + } + + bool unsafeValidateFileRolling(Level level, const PreRollOutCallback& PreRollOutCallback) { + base::type::fstream_t* fs = unsafeGetConfigByRef(level, &m_fileStreamMap, "fileStream").get(); + if (fs == nullptr) { + return true; + } + std::size_t maxLogFileSize = unsafeGetConfigByVal(level, &m_maxLogFileSizeMap, "maxLogFileSize"); + std::size_t currFileSize = base::utils::File::getSizeOfFile(fs); + if (maxLogFileSize != 0 && currFileSize >= maxLogFileSize) { + std::string fname = unsafeGetConfigByRef(level, &m_filenameMap, "filename"); + ELPP_INTERNAL_INFO(1, "Truncating log file [" << fname << "] as a result of configurations for level [" + << LevelHelper::convertToString(level) << "]"); + fs->close(); + PreRollOutCallback(fname.c_str(), currFileSize); + fs->open(fname, std::fstream::out | std::fstream::trunc); + return true; + } + return false; + } + + bool validateFileRolling(Level level, const PreRollOutCallback& PreRollOutCallback) { + base::threading::ScopedLock scopedLock(lock()); + return unsafeValidateFileRolling(level, PreRollOutCallback); + } + }; + /// @brief Class that keeps record of current line hit for occasional logging + class HitCounter { + public: + HitCounter(void) : + m_filename(""), + m_lineNumber(0), + m_hitCounts(0) { + } + + HitCounter(const char* filename, unsigned long int lineNumber) : + m_filename(filename), + m_lineNumber(lineNumber), + m_hitCounts(0) { + } + + HitCounter(const HitCounter& hitCounter) : + m_filename(hitCounter.m_filename), + m_lineNumber(hitCounter.m_lineNumber), + m_hitCounts(hitCounter.m_hitCounts) { + } + + HitCounter& operator=(const HitCounter& hitCounter) { + m_filename = hitCounter.m_filename; + m_lineNumber = hitCounter.m_lineNumber; + m_hitCounts = hitCounter.m_hitCounts; + return *this; + } + + virtual ~HitCounter(void) { + } + + /// @brief Resets location of current hit counter + inline void resetLocation(const char* filename, unsigned long int lineNumber) { + m_filename = filename; + m_lineNumber = lineNumber; + } + + /// @brief Validates hit counts and resets it if necessary + inline void validateHitCounts(std::size_t n) { + if (m_hitCounts >= base::consts::kMaxLogPerCounter) { + m_hitCounts = (n >= 1 ? base::consts::kMaxLogPerCounter % n : 0); + } + ++m_hitCounts; + } + + inline const char* filename(void) const { + return m_filename; + } + + inline unsigned long int lineNumber(void) const { + return m_lineNumber; + } + + inline std::size_t hitCounts(void) const { + return m_hitCounts; + } + + inline void increment(void) { + ++m_hitCounts; + } + + class Predicate { + public: + Predicate(const char* filename, unsigned long int lineNumber) + : m_filename(filename), + m_lineNumber(lineNumber) { + } + inline bool operator()(const HitCounter* counter) { + return ((counter != nullptr) && + (strcmp(counter->m_filename, m_filename) == 0) && + (counter->m_lineNumber == m_lineNumber)); + } + + private: + const char* m_filename; + unsigned long int m_lineNumber; + }; + + private: + const char* m_filename; + unsigned long int m_lineNumber; + std::size_t m_hitCounts; + }; + /// @brief Repository for hit counters used across the application + class RegisteredHitCounters : public base::utils::RegistryWithPred<base::HitCounter, base::HitCounter::Predicate> { + public: + /// @brief Validates counter for every N, i.e, registers new if does not exist otherwise updates original one + /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned + bool validateEveryN(const char* filename, unsigned long int lineNumber, std::size_t n) { + base::threading::ScopedLock scopedLock(lock()); + base::HitCounter* counter = get(filename, lineNumber); + if (counter == nullptr) { + registerNew(counter = new base::HitCounter(filename, lineNumber)); + } + counter->validateHitCounts(n); + bool result = (n >= 1 && counter->hitCounts() != 0 && counter->hitCounts() % n == 0); + return result; + } + + /// @brief Validates counter for hits >= N, i.e, registers new if does not exist otherwise updates original one + /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned + bool validateAfterN(const char* filename, unsigned long int lineNumber, std::size_t n) { + base::threading::ScopedLock scopedLock(lock()); + base::HitCounter* counter = get(filename, lineNumber); + if (counter == nullptr) { + registerNew(counter = new base::HitCounter(filename, lineNumber)); + } + // Do not use validateHitCounts here since we do not want to reset counter here + // Note the >= instead of > because we are incrementing + // after this check + if (counter->hitCounts() >= n) + return true; + counter->increment(); + return false; + } + + /// @brief Validates counter for hits are <= n, i.e, registers new if does not exist otherwise updates original one + /// @return True if validation resulted in triggering hit. Meaning logs should be written everytime true is returned + bool validateNTimes(const char* filename, unsigned long int lineNumber, std::size_t n) { + base::threading::ScopedLock scopedLock(lock()); + base::HitCounter* counter = get(filename, lineNumber); + if (counter == nullptr) { + registerNew(counter = new base::HitCounter(filename, lineNumber)); + } + counter->increment(); + // Do not use validateHitCounts here since we do not want to reset counter here + if (counter->hitCounts() <= n) + return true; + return false; + } + + /// @brief Gets hit counter registered at specified position + inline const base::HitCounter* getCounter(const char* filename, unsigned long int lineNumber) { + base::threading::ScopedLock scopedLock(lock()); + return get(filename, lineNumber); + } + }; + /// @brief Action to be taken for dispatching + enum class DispatchAction : base::type::EnumType { + None = 1, NormalLog = 2, SysLog = 4 + }; + } // namespace base + template <typename T> + class Callback : protected base::threading::ThreadSafe { + public: + Callback(void) : m_enabled(true) {} + inline bool enabled(void) const { return m_enabled; } + inline void setEnabled(bool enabled) { + base::threading::ScopedLock scopedLock(lock()); + m_enabled = enabled; + } + protected: + virtual void handle(const T* handlePtr) = 0; + private: + bool m_enabled; + }; + class LogDispatchData { + public: + LogDispatchData() : m_logMessage(nullptr), m_dispatchAction(base::DispatchAction::None) {} + inline const LogMessage* logMessage(void) const { return m_logMessage; } + inline base::DispatchAction dispatchAction(void) const { return m_dispatchAction; } + private: + LogMessage* m_logMessage; + base::DispatchAction m_dispatchAction; + friend class base::LogDispatcher; + + inline void setLogMessage(LogMessage* logMessage) { m_logMessage = logMessage; } + inline void setDispatchAction(base::DispatchAction dispatchAction) { m_dispatchAction = dispatchAction; } + }; + class LogDispatchCallback : public Callback<LogDispatchData> { + private: + friend class base::LogDispatcher; + }; + class PerformanceTrackingCallback : public Callback<PerformanceTrackingData> { + private: + friend class base::PerformanceTracker; + }; + class LogBuilder : base::NoCopy { + public: + virtual ~LogBuilder(void) { ELPP_INTERNAL_INFO(3, "Destroying log builder...") } + virtual base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const = 0; + void convertToColoredOutput(base::type::string_t* logLine, Level level) { + if (!base::utils::s_termSupportsColor) return; + const base::type::char_t* resetColor = ELPP_LITERAL("\x1b[0m"); + if (level == Level::Error || level == Level::Fatal) + *logLine = ELPP_LITERAL("\x1b[31m") + *logLine + resetColor; + else if (level == Level::Warning) + *logLine = ELPP_LITERAL("\x1b[33m") + *logLine + resetColor; + } + private: + friend class el::base::DefaultLogDispatchCallback; + }; + typedef std::shared_ptr<LogBuilder> LogBuilderPtr; + /// @brief Represents a logger holding ID and configurations we need to write logs + /// + /// @detail This class does not write logs itself instead its used by writer to read configuations from. + class Logger : public base::threading::ThreadSafe, public Loggable { + public: + Logger(const std::string& id, base::LogStreamsReferenceMap* logStreamsReference) : + m_id(id), + m_typedConfigurations(nullptr), + m_parentApplicationName(std::string()), + m_isConfigured(false), + m_logStreamsReference(logStreamsReference) { + initUnflushedCount(); + } + + Logger(const std::string& id, const Configurations& configurations, base::LogStreamsReferenceMap* logStreamsReference) : + m_id(id), + m_typedConfigurations(nullptr), + m_parentApplicationName(std::string()), + m_isConfigured(false), + m_logStreamsReference(logStreamsReference) { + initUnflushedCount(); + configure(configurations); + } + + Logger(const Logger& logger) { + base::utils::safeDelete(m_typedConfigurations); + m_id = logger.m_id; + m_typedConfigurations = logger.m_typedConfigurations; + m_parentApplicationName = logger.m_parentApplicationName; + m_isConfigured = logger.m_isConfigured; + m_configurations = logger.m_configurations; + m_unflushedCount = logger.m_unflushedCount; + m_logStreamsReference = logger.m_logStreamsReference; + } + + Logger& operator=(const Logger& logger) { + base::utils::safeDelete(m_typedConfigurations); + m_id = logger.m_id; + m_typedConfigurations = logger.m_typedConfigurations; + m_parentApplicationName = logger.m_parentApplicationName; + m_isConfigured = logger.m_isConfigured; + m_configurations = logger.m_configurations; + m_unflushedCount = logger.m_unflushedCount; + m_logStreamsReference = logger.m_logStreamsReference; + return *this; + } + + virtual ~Logger(void) { + base::utils::safeDelete(m_typedConfigurations); + } + + virtual inline void log(el::base::type::ostream_t& os) const { + os << m_id.c_str(); + } + + /// @brief Configures the logger using specified configurations. + void configure(const Configurations& configurations) { + m_isConfigured = false; // we set it to false in case if we fail + initUnflushedCount(); + if (m_typedConfigurations != nullptr) { + Configurations* c = const_cast<Configurations*>(m_typedConfigurations->configurations()); + if (c->hasConfiguration(Level::Global, ConfigurationType::Filename)) { + // This check is definitely needed for cases like ELPP_NO_DEFAULT_LOG_FILE + flush(); + } + } + base::threading::ScopedLock scopedLock(lock()); + if (m_configurations != configurations) { + m_configurations.setFromBase(const_cast<Configurations*>(&configurations)); + } + base::utils::safeDelete(m_typedConfigurations); + m_typedConfigurations = new base::TypedConfigurations(&m_configurations, m_logStreamsReference); + resolveLoggerFormatSpec(); + m_isConfigured = true; + } + + /// @brief Reconfigures logger using existing configurations + inline void reconfigure(void) { + ELPP_INTERNAL_INFO(1, "Reconfiguring logger [" << m_id << "]"); + configure(m_configurations); + } + + inline const std::string& id(void) const { + return m_id; + } + + inline const std::string& parentApplicationName(void) const { + return m_parentApplicationName; + } + + inline void setParentApplicationName(const std::string& parentApplicationName) { + m_parentApplicationName = parentApplicationName; + } + + inline Configurations* configurations(void) { + return &m_configurations; + } + + inline base::TypedConfigurations* typedConfigurations(void) { + return m_typedConfigurations; + } + + static inline bool isValidId(const std::string& id) { + for (std::string::const_iterator it = id.begin(); it != id.end(); ++it) { + if (!base::utils::Str::contains(base::consts::kValidLoggerIdSymbols, *it)) { + return false; + } + } + return true; + } + /// @brief Flushes logger to sync all log files for all levels + inline void flush(void) { + ELPP_INTERNAL_INFO(3, "Flushing logger [" << m_id << "] all levels"); + base::threading::ScopedLock scopedLock(lock()); + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + flush(LevelHelper::castFromInt(lIndex), nullptr); + return false; + }); + } + + inline void flush(Level level, base::type::fstream_t* fs) { + if (fs == nullptr && m_typedConfigurations->toFile(level)) { + fs = m_typedConfigurations->fileStream(level); + } + if (fs != nullptr) { + fs->flush(); + m_unflushedCount.find(level)->second = 0; + } + } + + inline bool isFlushNeeded(Level level) { + return ++m_unflushedCount.find(level)->second >= m_typedConfigurations->logFlushThreshold(level); + } + + inline LogBuilder* logBuilder(void) const { + return m_logBuilder.get(); + } + + inline void setLogBuilder(const LogBuilderPtr& logBuilder) { + m_logBuilder = logBuilder; + } + + inline bool enabled(Level level) const { + return m_typedConfigurations->enabled(level); + } + +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED +# define LOGGER_LEVEL_WRITERS_SIGNATURES(FUNCTION_NAME)\ + template <typename T, typename... Args>\ + inline void FUNCTION_NAME(const char*, const T&, const Args&...);\ + template <typename T>\ + inline void FUNCTION_NAME(const T&); + + template <typename T, typename... Args> + inline void verbose(int, const char*, const T&, const Args&...); + + template <typename T> + inline void verbose(int, const T&); + + LOGGER_LEVEL_WRITERS_SIGNATURES(info) + LOGGER_LEVEL_WRITERS_SIGNATURES(debug) + LOGGER_LEVEL_WRITERS_SIGNATURES(warn) + LOGGER_LEVEL_WRITERS_SIGNATURES(error) + LOGGER_LEVEL_WRITERS_SIGNATURES(fatal) + LOGGER_LEVEL_WRITERS_SIGNATURES(trace) +# undef LOGGER_LEVEL_WRITERS_SIGNATURES +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED + private: + std::string m_id; + base::TypedConfigurations* m_typedConfigurations; + base::type::stringstream_t m_stream; + std::string m_parentApplicationName; + bool m_isConfigured; + Configurations m_configurations; + std::map<Level, unsigned int> m_unflushedCount; + base::LogStreamsReferenceMap* m_logStreamsReference; + LogBuilderPtr m_logBuilder; + + friend class el::LogMessage; + friend class el::Loggers; + friend class el::Helpers; + friend class el::base::RegisteredLoggers; + friend class el::base::DefaultLogDispatchCallback; + friend class el::base::MessageBuilder; + friend class el::base::Writer; + friend class el::base::PErrorWriter; + friend class el::base::Storage; + friend class el::base::PerformanceTracker; + friend class el::base::LogDispatcher; + + Logger(void); + +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED + template <typename T, typename... Args> + void log_(Level, int, const char*, const T&, const Args&...); + + template <typename T> + inline void log_(Level, int, const T&); + + template <typename T, typename... Args> + void log(Level, const char*, const T&, const Args&...); + + template <typename T> + inline void log(Level, const T&); +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED + + void initUnflushedCount(void) { + m_unflushedCount.clear(); + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + m_unflushedCount.insert(std::make_pair(LevelHelper::castFromInt(lIndex), 0)); + return false; + }); + } + + inline base::type::stringstream_t& stream(void) { + return m_stream; + } + + void resolveLoggerFormatSpec(void) const { + base::type::EnumType lIndex = LevelHelper::kMinValid; + LevelHelper::forEachLevel(&lIndex, [&](void) -> bool { + base::LogFormat* logFormat = + const_cast<base::LogFormat*>(&m_typedConfigurations->logFormat(LevelHelper::castFromInt(lIndex))); + base::utils::Str::replaceFirstWithEscape(logFormat->m_format, base::consts::kLoggerIdFormatSpecifier, m_id); + return false; + }); + } + }; + namespace base { + /// @brief Loggers repository + class RegisteredLoggers : public base::utils::Registry<Logger, std::string> { + public: + explicit RegisteredLoggers(const LogBuilderPtr& defaultLogBuilder) : + m_defaultLogBuilder(defaultLogBuilder) { + m_defaultConfigurations.setToDefault(); + } + + virtual ~RegisteredLoggers(void) { + flushAll(); + } + + inline void setDefaultConfigurations(const Configurations& configurations) { + base::threading::ScopedLock scopedLock(lock()); + m_defaultConfigurations.setFromBase(const_cast<Configurations*>(&configurations)); + } + + inline Configurations* defaultConfigurations(void) { + return &m_defaultConfigurations; + } + + Logger* get(const std::string& id, bool forceCreation = true) { + base::threading::ScopedLock scopedLock(lock()); + Logger* logger_ = base::utils::Registry<Logger, std::string>::get(id); + if (logger_ == nullptr && forceCreation) { + bool validId = Logger::isValidId(id); + if (!validId) { + ELPP_ASSERT(validId, "Invalid logger ID [" << id << "]. Not registering this logger."); + return nullptr; + } + logger_ = new Logger(id, m_defaultConfigurations, &m_logStreamsReference); + logger_->m_logBuilder = m_defaultLogBuilder; + registerNew(id, logger_); + } + return logger_; + } + + bool remove(const std::string& id) { + if (id == "default") { + return false; + } + Logger* logger = base::utils::Registry<Logger, std::string>::get(id); + if (logger != nullptr) { + unregister(logger); + } + return true; + } + + inline bool has(const std::string& id) { + return get(id, false) != nullptr; + } + + inline void unregister(Logger*& logger) { + base::threading::ScopedLock scopedLock(lock()); + base::utils::Registry<Logger, std::string>::unregister(logger->id()); + } + + inline base::LogStreamsReferenceMap* logStreamsReference(void) { + return &m_logStreamsReference; + } + + inline void flushAll(void) { + ELPP_INTERNAL_INFO(1, "Flushing all log files"); + base::threading::ScopedLock scopedLock(lock()); + for (base::LogStreamsReferenceMap::iterator it = m_logStreamsReference.begin(); + it != m_logStreamsReference.end(); ++it) { + if (it->second.get() == nullptr) continue; + it->second->flush(); + } + } + + private: + LogBuilderPtr m_defaultLogBuilder; + Configurations m_defaultConfigurations; + base::LogStreamsReferenceMap m_logStreamsReference; + friend class el::base::Storage; + }; + /// @brief Represents registries for verbose logging + class VRegistry : base::NoCopy, public base::threading::ThreadSafe { + public: + explicit VRegistry(base::type::VerboseLevel level, base::type::EnumType* pFlags) : m_level(level), m_pFlags(pFlags) { + } + + /// @brief Sets verbose level. Accepted range is 0-9 + inline void setLevel(base::type::VerboseLevel level) { + base::threading::ScopedLock scopedLock(lock()); + if (level < 0) + m_level = 0; + else if (level > 9) + m_level = base::consts::kMaxVerboseLevel; + else + m_level = level; + } + + inline base::type::VerboseLevel level(void) const { + return m_level; + } + + inline void clearModules(void) { + base::threading::ScopedLock scopedLock(lock()); + m_modules.clear(); + } + + void setModules(const char* modules) { + base::threading::ScopedLock scopedLock(lock()); + auto addSuffix = [](std::stringstream& ss, const char* sfx, const char* prev) { + if (prev != nullptr && base::utils::Str::endsWith(ss.str(), std::string(prev))) { + std::string chr(ss.str().substr(0, ss.str().size() - strlen(prev))); + ss.str(std::string("")); + ss << chr; + } + if (base::utils::Str::endsWith(ss.str(), std::string(sfx))) { + std::string chr(ss.str().substr(0, ss.str().size() - strlen(sfx))); + ss.str(std::string("")); + ss << chr; + } + ss << sfx; + }; + auto insert = [&](std::stringstream& ss, base::type::VerboseLevel level) { + if (!base::utils::hasFlag(LoggingFlag::DisableVModulesExtensions, *m_pFlags)) { + addSuffix(ss, ".h", nullptr); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".c", ".h"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".cpp", ".c"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".cc", ".cpp"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".cxx", ".cc"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".-inl.h", ".cxx"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".hxx", ".-inl.h"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".hpp", ".hxx"); + m_modules.insert(std::make_pair(ss.str(), level)); + addSuffix(ss, ".hh", ".hpp"); + } + m_modules.insert(std::make_pair(ss.str(), level)); + }; + bool isMod = true; + bool isLevel = false; + std::stringstream ss; + int level = -1; + for (; *modules; ++modules) { + switch (*modules) { + case '=': + isLevel = true; + isMod = false; + break; + case ',': + isLevel = false; + isMod = true; + if (!ss.str().empty() && level != -1) { + insert(ss, level); + ss.str(std::string("")); + level = -1; + } + break; + default: + if (isMod) { + ss << *modules; + } + else if (isLevel) { + if (isdigit(*modules)) { + level = static_cast<base::type::VerboseLevel>(*modules) - 48; + } + } + break; + } + } + if (!ss.str().empty() && level != -1) { + insert(ss, level); + } + } + + bool allowed(base::type::VerboseLevel vlevel, const char* file) { + base::threading::ScopedLock scopedLock(lock()); + if (m_modules.empty() || file == nullptr) { + return vlevel <= m_level; + } + else { + std::map<std::string, base::type::VerboseLevel>::iterator it = m_modules.begin(); + for (; it != m_modules.end(); ++it) { + if (base::utils::Str::wildCardMatch(file, it->first.c_str())) { + return vlevel <= it->second; + } + } + if (base::utils::hasFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified, *m_pFlags)) { + return true; + } + return false; + } + } + + inline const std::map<std::string, base::type::VerboseLevel>& modules(void) const { + return m_modules; + } + + void setFromArgs(const base::utils::CommandLineArgs* commandLineArgs) { + if (commandLineArgs->hasParam("-v") || commandLineArgs->hasParam("--verbose") || + commandLineArgs->hasParam("-V") || commandLineArgs->hasParam("--VERBOSE")) { + setLevel(base::consts::kMaxVerboseLevel); + } + else if (commandLineArgs->hasParamWithValue("--v")) { + setLevel(atoi(commandLineArgs->getParamValue("--v"))); + } + else if (commandLineArgs->hasParamWithValue("--V")) { + setLevel(atoi(commandLineArgs->getParamValue("--V"))); + } + else if ((commandLineArgs->hasParamWithValue("-vmodule")) && vModulesEnabled()) { + setModules(commandLineArgs->getParamValue("-vmodule")); + } + else if (commandLineArgs->hasParamWithValue("-VMODULE") && vModulesEnabled()) { + setModules(commandLineArgs->getParamValue("-VMODULE")); + } + } + + /// @brief Whether or not vModules enabled + inline bool vModulesEnabled(void) { + return !base::utils::hasFlag(LoggingFlag::DisableVModules, *m_pFlags); + } + + private: + base::type::VerboseLevel m_level; + base::type::EnumType* m_pFlags; + std::map<std::string, base::type::VerboseLevel> m_modules; + }; + } // namespace base + class LogMessage { + public: + LogMessage(Level level, const std::string& file, unsigned long int line, const std::string& func, + base::type::VerboseLevel verboseLevel, Logger* logger) : + m_level(level), m_file(file), m_line(line), m_func(func), + m_verboseLevel(verboseLevel), m_logger(logger), m_message(std::move(logger->stream().str())) { + } + inline Level level(void) const { return m_level; } + inline const std::string& file(void) const { return m_file; } + inline unsigned long int line(void) const { return m_line; } // NOLINT + inline const std::string& func(void) const { return m_func; } + inline base::type::VerboseLevel verboseLevel(void) const { return m_verboseLevel; } + inline Logger* logger(void) const { return m_logger; } + inline const base::type::string_t& message(void) const { return m_message; } + private: + Level m_level; + std::string m_file; + unsigned long int m_line; + std::string m_func; + base::type::VerboseLevel m_verboseLevel; + Logger* m_logger; + base::type::string_t m_message; + }; + namespace base { +#if ELPP_ASYNC_LOGGING + class AsyncLogItem { + public: + explicit AsyncLogItem(const LogMessage& logMessage, const LogDispatchData& data, const base::type::string_t& logLine) + : m_logMessage(logMessage), m_dispatchData(data), m_logLine(logLine) {} + virtual ~AsyncLogItem() {} + inline LogMessage* logMessage(void) { return &m_logMessage; } + inline LogDispatchData* data(void) { return &m_dispatchData; } + inline base::type::string_t logLine(void) { return m_logLine; } + private: + LogMessage m_logMessage; + LogDispatchData m_dispatchData; + base::type::string_t m_logLine; + }; + class AsyncLogQueue : public base::threading::ThreadSafe { + public: + virtual ~AsyncLogQueue() { + ELPP_INTERNAL_INFO(6, "~AsyncLogQueue"); + } + + inline AsyncLogItem next(void) { + base::threading::ScopedLock scopedLock(lock()); + AsyncLogItem result = m_queue.front(); + m_queue.pop(); + return result; + } + + inline void push(const AsyncLogItem& item) { + base::threading::ScopedLock scopedLock(lock()); + m_queue.push(item); + } + inline void pop(void) { + base::threading::ScopedLock scopedLock(lock()); + m_queue.pop(); + } + inline AsyncLogItem front(void) { + base::threading::ScopedLock scopedLock(lock()); + return m_queue.front(); + } + inline bool empty(void) { + base::threading::ScopedLock scopedLock(lock()); + return m_queue.empty(); + } + private: + std::queue<AsyncLogItem> m_queue; + }; + class IWorker { + public: + virtual ~IWorker() {} + virtual void start() = 0; + }; +#endif // ELPP_ASYNC_LOGGING + /// @brief Easylogging++ management storage + class Storage : base::NoCopy, public base::threading::ThreadSafe { + public: +#if ELPP_ASYNC_LOGGING + Storage(const LogBuilderPtr& defaultLogBuilder, base::IWorker* asyncDispatchWorker) : +#else + explicit Storage(const LogBuilderPtr& defaultLogBuilder) : +#endif // ELPP_ASYNC_LOGGING + m_registeredHitCounters(new base::RegisteredHitCounters()), + m_registeredLoggers(new base::RegisteredLoggers(defaultLogBuilder)), + m_flags(0x0), + m_vRegistry(new base::VRegistry(0, &m_flags)), +#if ELPP_ASYNC_LOGGING + m_asyncLogQueue(new base::AsyncLogQueue()), + m_asyncDispatchWorker(asyncDispatchWorker), +#endif // ELPP_ASYNC_LOGGING + m_preRollOutCallback(base::defaultPreRollOutCallback) { + // Register default logger + m_registeredLoggers->get(std::string(base::consts::kDefaultLoggerId)); + // Register performance logger and reconfigure format + Logger* performanceLogger = m_registeredLoggers->get(std::string(base::consts::kPerformanceLoggerId)); + performanceLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%datetime %level %msg")); + performanceLogger->reconfigure(); +#if defined(ELPP_SYSLOG) + // Register syslog logger and reconfigure format + Logger* sysLogLogger = m_registeredLoggers->get(std::string(base::consts::kSysLogLoggerId)); + sysLogLogger->configurations()->setGlobally(ConfigurationType::Format, std::string("%level: %msg")); + sysLogLogger->reconfigure(); +#else + ELPP_UNUSED(base::consts::kSysLogLoggerId); +#endif // defined(ELPP_SYSLOG) + addFlag(LoggingFlag::AllowVerboseIfModuleNotSpecified); +#if ELPP_ASYNC_LOGGING + installLogDispatchCallback<base::AsyncLogDispatchCallback>(std::string("AsyncLogDispatchCallback")); +#else + installLogDispatchCallback<base::DefaultLogDispatchCallback>(std::string("DefaultLogDispatchCallback")); +#endif // ELPP_ASYNC_LOGGING + installPerformanceTrackingCallback<base::DefaultPerformanceTrackingCallback>(std::string("DefaultPerformanceTrackingCallback")); + ELPP_INTERNAL_INFO(1, "Easylogging++ has been initialized"); +#if ELPP_ASYNC_LOGGING + m_asyncDispatchWorker->start(); +#endif // ELPP_ASYNC_LOGGING + } + + virtual ~Storage(void) { + ELPP_INTERNAL_INFO(4, "Destroying storage"); +#if ELPP_ASYNC_LOGGING + ELPP_INTERNAL_INFO(5, "Replacing log dispatch callback to synchronous"); + uninstallLogDispatchCallback<base::AsyncLogDispatchCallback>(std::string("AsyncLogDispatchCallback")); + installLogDispatchCallback<base::DefaultLogDispatchCallback>(std::string("DefaultLogDispatchCallback")); + ELPP_INTERNAL_INFO(5, "Destroying asyncDispatchWorker"); + base::utils::safeDelete(m_asyncDispatchWorker); + ELPP_INTERNAL_INFO(5, "Destroying asyncLogQueue"); + base::utils::safeDelete(m_asyncLogQueue); +#endif // ELPP_ASYNC_LOGGING + ELPP_INTERNAL_INFO(5, "Destroying registeredHitCounters"); + base::utils::safeDelete(m_registeredHitCounters); + ELPP_INTERNAL_INFO(5, "Destroying registeredLoggers"); + base::utils::safeDelete(m_registeredLoggers); + ELPP_INTERNAL_INFO(5, "Destroying vRegistry"); + base::utils::safeDelete(m_vRegistry); + } + + inline bool validateEveryNCounter(const char* filename, unsigned long int lineNumber, std::size_t occasion) { + return hitCounters()->validateEveryN(filename, lineNumber, occasion); + } + + inline bool validateAfterNCounter(const char* filename, unsigned long int lineNumber, std::size_t n) { // NOLINT + return hitCounters()->validateAfterN(filename, lineNumber, n); + } + + inline bool validateNTimesCounter(const char* filename, unsigned long int lineNumber, std::size_t n) { // NOLINT + return hitCounters()->validateNTimes(filename, lineNumber, n); + } + + inline base::RegisteredHitCounters* hitCounters(void) const { + return m_registeredHitCounters; + } + + inline base::RegisteredLoggers* registeredLoggers(void) const { + return m_registeredLoggers; + } + + inline base::VRegistry* vRegistry(void) const { + return m_vRegistry; + } + +#if ELPP_ASYNC_LOGGING + inline base::AsyncLogQueue* asyncLogQueue(void) const { + return m_asyncLogQueue; + } +#endif // ELPP_ASYNC_LOGGING + + inline const base::utils::CommandLineArgs* commandLineArgs(void) const { + return &m_commandLineArgs; + } + + inline void addFlag(LoggingFlag flag) { + base::utils::addFlag(flag, &m_flags); + } + + inline void removeFlag(LoggingFlag flag) { + base::utils::removeFlag(flag, &m_flags); + } + + inline bool hasFlag(LoggingFlag flag) const { + return base::utils::hasFlag(flag, m_flags); + } + + inline base::type::EnumType flags(void) const { + return m_flags; + } + + inline void setFlags(base::type::EnumType flags) { + m_flags = flags; + } + + inline void setPreRollOutCallback(const PreRollOutCallback& callback) { + m_preRollOutCallback = callback; + } + + inline void unsetPreRollOutCallback(void) { + m_preRollOutCallback = base::defaultPreRollOutCallback; + } + + inline PreRollOutCallback& preRollOutCallback(void) { + return m_preRollOutCallback; + } + + inline bool hasCustomFormatSpecifier(const char* formatSpecifier) { + base::threading::ScopedLock scopedLock(lock()); + return std::find(m_customFormatSpecifiers.begin(), m_customFormatSpecifiers.end(), + formatSpecifier) != m_customFormatSpecifiers.end(); + } + + inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { + if (hasCustomFormatSpecifier(customFormatSpecifier.formatSpecifier())) { + return; + } + base::threading::ScopedLock scopedLock(lock()); + m_customFormatSpecifiers.push_back(customFormatSpecifier); + } + + inline bool uninstallCustomFormatSpecifier(const char* formatSpecifier) { + base::threading::ScopedLock scopedLock(lock()); + std::vector<CustomFormatSpecifier>::iterator it = std::find(m_customFormatSpecifiers.begin(), + m_customFormatSpecifiers.end(), formatSpecifier); + if (it != m_customFormatSpecifiers.end() && strcmp(formatSpecifier, it->formatSpecifier()) == 0) { + m_customFormatSpecifiers.erase(it); + return true; + } + return false; + } + + const std::vector<CustomFormatSpecifier>* customFormatSpecifiers(void) const { + return &m_customFormatSpecifiers; + } + + inline void setLoggingLevel(Level level) { + m_loggingLevel = level; + } + + template <typename T> + inline bool installLogDispatchCallback(const std::string& id) { + return installCallback<T, base::type::LogDispatchCallbackPtr>(id, &m_logDispatchCallbacks); + } + + template <typename T> + inline void uninstallLogDispatchCallback(const std::string& id) { + uninstallCallback<T, base::type::LogDispatchCallbackPtr>(id, &m_logDispatchCallbacks); + } + template <typename T> + inline T* logDispatchCallback(const std::string& id) { + return callback<T, base::type::LogDispatchCallbackPtr>(id, &m_logDispatchCallbacks); + } + + template <typename T> + inline bool installPerformanceTrackingCallback(const std::string& id) { + return installCallback<T, base::type::PerformanceTrackingCallbackPtr>(id, &m_performanceTrackingCallbacks); + } + + template <typename T> + inline void uninstallPerformanceTrackingCallback(const std::string& id) { + uninstallCallback<T, base::type::PerformanceTrackingCallbackPtr>(id, &m_performanceTrackingCallbacks); + } + + template <typename T> + inline T* performanceTrackingCallback(const std::string& id) { + return callback<T, base::type::PerformanceTrackingCallbackPtr>(id, &m_performanceTrackingCallbacks); + } + private: + base::RegisteredHitCounters* m_registeredHitCounters; + base::RegisteredLoggers* m_registeredLoggers; + base::type::EnumType m_flags; + base::VRegistry* m_vRegistry; +#if ELPP_ASYNC_LOGGING + base::AsyncLogQueue* m_asyncLogQueue; + base::IWorker* m_asyncDispatchWorker; +#endif // ELPP_ASYNC_LOGGING + base::utils::CommandLineArgs m_commandLineArgs; + PreRollOutCallback m_preRollOutCallback; + std::map<std::string, base::type::LogDispatchCallbackPtr> m_logDispatchCallbacks; + std::map<std::string, base::type::PerformanceTrackingCallbackPtr> m_performanceTrackingCallbacks; + std::vector<CustomFormatSpecifier> m_customFormatSpecifiers; + Level m_loggingLevel; + + friend class el::Helpers; + friend class el::base::DefaultLogDispatchCallback; + friend class el::LogBuilder; + friend class el::base::MessageBuilder; + friend class el::base::Writer; + friend class el::base::PerformanceTracker; + friend class el::base::LogDispatcher; + + void setApplicationArguments(int argc, char** argv) { + m_commandLineArgs.setArgs(argc, argv); + m_vRegistry->setFromArgs(commandLineArgs()); + // default log file +#if !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) + if (m_commandLineArgs.hasParamWithValue(base::consts::kDefaultLogFileParam)) { + Configurations c; + c.setGlobally(ConfigurationType::Filename, std::string(m_commandLineArgs.getParamValue(base::consts::kDefaultLogFileParam))); + registeredLoggers()->setDefaultConfigurations(c); + for (base::RegisteredLoggers::iterator it = registeredLoggers()->begin(); + it != registeredLoggers()->end(); ++it) { + it->second->configure(c); + } + } +#endif // !defined(ELPP_DISABLE_LOG_FILE_FROM_ARG) +#if defined(ELPP_LOGGING_FLAGS_FROM_ARG) + if (m_commandLineArgs.hasParamWithValue(base::consts::kLoggingFlagsParam)) { + m_flags = atoi(m_commandLineArgs.getParamValue(base::consts::kLoggingFlagsParam)); + } +#endif // defined(ELPP_LOGGING_FLAGS_FROM_ARG) + } + + inline void setApplicationArguments(int argc, const char** argv) { + setApplicationArguments(argc, const_cast<char**>(argv)); + } + + template <typename T, typename TPtr> + inline bool installCallback(const std::string& id, std::map<std::string, TPtr>* mapT) { + if (mapT->find(id) == mapT->end()) { + mapT->insert(std::make_pair(id, TPtr(new T()))); + return true; + } + return false; + } + + template <typename T, typename TPtr> + inline void uninstallCallback(const std::string& id, std::map<std::string, TPtr>* mapT) { + if (mapT->find(id) != mapT->end()) { + mapT->erase(id); + } + } + + template <typename T, typename TPtr> + inline T* callback(const std::string& id, std::map<std::string, TPtr>* mapT) { + typename std::map<std::string, TPtr>::iterator iter = mapT->find(id); + if (iter != mapT->end()) { + return static_cast<T*>(iter->second.get()); + } + return nullptr; + } + }; + extern ELPP_EXPORT base::type::StoragePointer elStorage; +#define ELPP el::base::elStorage + class DefaultLogDispatchCallback : public LogDispatchCallback { + protected: + void handle(const LogDispatchData* data) { + m_data = data; + dispatch(std::move(m_data->logMessage()->logger()->logBuilder()->build(m_data->logMessage(), + m_data->dispatchAction() == base::DispatchAction::NormalLog))); + } + private: + const LogDispatchData* m_data; + void dispatch(base::type::string_t&& logLine) { + if (m_data->dispatchAction() == base::DispatchAction::NormalLog) { + if (m_data->logMessage()->logger()->m_typedConfigurations->toFile(m_data->logMessage()->level())) { + base::type::fstream_t* fs = m_data->logMessage()->logger()->m_typedConfigurations->fileStream(m_data->logMessage()->level()); + if (fs != nullptr) { + fs->write(logLine.c_str(), logLine.size()); + if (fs->fail()) { + ELPP_INTERNAL_ERROR("Unable to write log to file [" + << m_data->logMessage()->logger()->m_typedConfigurations->filename(m_data->logMessage()->level()) << "].\n" + << "Few possible reasons (could be something else):\n" << " * Permission denied\n" + << " * Disk full\n" << " * Disk is not writable", true); + } + else { + if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (m_data->logMessage()->logger()->isFlushNeeded(m_data->logMessage()->level()))) { + m_data->logMessage()->logger()->flush(m_data->logMessage()->level(), fs); + } + } + } + else { + ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(m_data->logMessage()->level()) << "] " + << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " + << m_data->logMessage()->logger()->id() << "]", false); + } + } + if (m_data->logMessage()->logger()->m_typedConfigurations->toStandardOutput(m_data->logMessage()->level())) { + if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) + m_data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, m_data->logMessage()->level()); + ELPP_COUT << ELPP_COUT_LINE(logLine); + } + } +#if defined(ELPP_SYSLOG) + else if (m_data->dispatchAction() == base::DispatchAction::SysLog) { + // Determine syslog priority + int sysLogPriority = 0; + if (m_data->logMessage()->level() == Level::Fatal) + sysLogPriority = LOG_EMERG; + else if (m_data->logMessage()->level() == Level::Error) + sysLogPriority = LOG_ERR; + else if (m_data->logMessage()->level() == Level::Warning) + sysLogPriority = LOG_WARNING; + else if (m_data->logMessage()->level() == Level::Info) + sysLogPriority = LOG_INFO; + else if (m_data->logMessage()->level() == Level::Debug) + sysLogPriority = LOG_DEBUG; + else + sysLogPriority = LOG_NOTICE; +# if defined(ELPP_UNICODE) + char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); + syslog(sysLogPriority, "%s", line); + free(line); +# else + syslog(sysLogPriority, "%s", logLine.c_str()); +# endif + } +#endif // defined(ELPP_SYSLOG) + } + }; +#if ELPP_ASYNC_LOGGING + class AsyncLogDispatchCallback : public LogDispatchCallback { + protected: + void handle(const LogDispatchData* data) { + base::type::string_t logLine = data->logMessage()->logger()->logBuilder()->build(data->logMessage(), data->dispatchAction() == base::DispatchAction::NormalLog); + if (data->dispatchAction() == base::DispatchAction::NormalLog && data->logMessage()->logger()->typedConfigurations()->toStandardOutput(data->logMessage()->level())) { + if (ELPP->hasFlag(LoggingFlag::ColoredTerminalOutput)) + data->logMessage()->logger()->logBuilder()->convertToColoredOutput(&logLine, data->logMessage()->level()); + ELPP_COUT << ELPP_COUT_LINE(logLine); + } + // Save resources and only queue if we want to write to file otherwise just ignore handler + if (data->logMessage()->logger()->typedConfigurations()->toFile(data->logMessage()->level())) { + ELPP->asyncLogQueue()->push(AsyncLogItem(*(data->logMessage()), *data, logLine)); + } + } + }; + class AsyncDispatchWorker : public base::IWorker, public base::threading::ThreadSafe { + public: + AsyncDispatchWorker() { + setContinueRunning(false); + } + + virtual ~AsyncDispatchWorker() { + setContinueRunning(false); + ELPP_INTERNAL_INFO(6, "Stopping dispatch worker - Cleaning log queue"); + clean(); + ELPP_INTERNAL_INFO(6, "Log queue cleaned"); + } + + inline bool clean() { + std::mutex m; + std::unique_lock<std::mutex> lk(m); + cv.wait(lk, [] { return !ELPP->asyncLogQueue()->empty(); }); + emptyQueue(); + lk.unlock(); + cv.notify_one(); + return ELPP->asyncLogQueue()->empty(); + } + + inline void emptyQueue() { + while (!ELPP->asyncLogQueue()->empty()) { + AsyncLogItem data = ELPP->asyncLogQueue()->next(); + handle(&data); + base::threading::msleep(100); + } + } + + virtual inline void start() { + base::threading::msleep(5000); // Wait extra few seconds + setContinueRunning(true); + std::thread t1(&AsyncDispatchWorker::runner, this); + t1.join(); + } + + void handle(AsyncLogItem* logItem) { + LogDispatchData* data = logItem->data(); + LogMessage* logMessage = logItem->logMessage(); + Logger* logger = logMessage->logger(); + base::TypedConfigurations* conf = logger->typedConfigurations(); + base::type::string_t logLine = logItem->logLine(); + if (data->dispatchAction() == base::DispatchAction::NormalLog) { + if (conf->toFile(logMessage->level())) { + base::type::fstream_t* fs = conf->fileStream(logMessage->level()); + if (fs != nullptr) { + fs->write(logLine.c_str(), logLine.size()); + if (fs->fail()) { + ELPP_INTERNAL_ERROR("Unable to write log to file [" + << conf->filename(logMessage->level()) << "].\n" + << "Few possible reasons (could be something else):\n" << " * Permission denied\n" + << " * Disk full\n" << " * Disk is not writable", true); + } + else { + if (ELPP->hasFlag(LoggingFlag::ImmediateFlush) || (logger->isFlushNeeded(logMessage->level()))) { + logger->flush(logMessage->level(), fs); + } + } + } + else { + ELPP_INTERNAL_ERROR("Log file for [" << LevelHelper::convertToString(logMessage->level()) << "] " + << "has not been configured but [TO_FILE] is configured to TRUE. [Logger ID: " << logger->id() << "]", false); + } + } + } +# if defined(ELPP_SYSLOG) + else if (data->dispatchAction() == base::DispatchAction::SysLog) { + // Determine syslog priority + int sysLogPriority = 0; + if (logMessage->level() == Level::Fatal) + sysLogPriority = LOG_EMERG; + else if (logMessage->level() == Level::Error) + sysLogPriority = LOG_ERR; + else if (logMessage->level() == Level::Warning) + sysLogPriority = LOG_WARNING; + else if (logMessage->level() == Level::Info) + sysLogPriority = LOG_INFO; + else if (logMessage->level() == Level::Debug) + sysLogPriority = LOG_DEBUG; + else + sysLogPriority = LOG_NOTICE; +# if defined(ELPP_UNICODE) + char* line = base::utils::Str::wcharPtrToCharPtr(logLine.c_str()); + syslog(sysLogPriority, "%s", line); + free(line); +# else + syslog(sysLogPriority, "%s", logLine.c_str()); +# endif + } +# endif // defined(ELPP_SYSLOG) + } + + void run() { + while (continueRunning()) { + emptyQueue(); + base::threading::msleep(10); // 10ms + } + } + + static void* runner(void *context) { + static_cast<AsyncDispatchWorker*>(context)->run(); + return NULL; + } + + void setContinueRunning(bool value) { + base::threading::ScopedLock scopedLock(m_continueRunningMutex); + m_continueRunning = value; + } + bool continueRunning(void) { + return m_continueRunning; + } + private: + std::condition_variable cv; + bool m_continueRunning; + base::threading::Mutex m_continueRunningMutex; + }; +#endif // ELPP_ASYNC_LOGGING + } // namespace base + namespace base { + class DefaultLogBuilder : public LogBuilder { + public: + base::type::string_t build(const LogMessage* logMessage, bool appendNewLine) const { + base::TypedConfigurations* tc = logMessage->logger()->typedConfigurations(); + const base::LogFormat* logFormat = &tc->logFormat(logMessage->level()); + base::type::string_t logLine = logFormat->format(); + char buff[base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength] = ""; + const char* bufLim = buff + sizeof(buff); + if (logFormat->hasFlag(base::FormatFlags::AppName)) { + // App name + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kAppNameFormatSpecifier, + logMessage->logger()->parentApplicationName()); + } + if (logFormat->hasFlag(base::FormatFlags::ThreadId)) { + // Thread ID + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kThreadIdFormatSpecifier, + base::threading::getCurrentThreadId()); + } + if (logFormat->hasFlag(base::FormatFlags::DateTime)) { + // DateTime + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kDateTimeFormatSpecifier, + base::utils::DateTime::getDateTime(logFormat->dateTimeFormat().c_str(), + &tc->millisecondsWidth(logMessage->level()))); + } + if (logFormat->hasFlag(base::FormatFlags::Function)) { + // Function + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFunctionFormatSpecifier, logMessage->func()); + } + if (logFormat->hasFlag(base::FormatFlags::File)) { + // File + char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); + base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff); + buf = base::utils::Str::addToBuff(buff, buf, bufLim); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::FileBase)) { + // FileBase + char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceFilenameMaxLength); + base::utils::File::buildBaseFilename(logMessage->file(), buff); + buf = base::utils::Str::addToBuff(buff, buf, bufLim); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogFileBaseFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::Line)) { + // Line + char* buf = base::utils::Str::clearBuff(buff, base::consts::kSourceLineMaxLength); + buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), + base::consts::kSourceLineMaxLength, buf, bufLim, false); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLineFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::Location)) { + // Location + char* buf = base::utils::Str::clearBuff(buff, + base::consts::kSourceFilenameMaxLength + base::consts::kSourceLineMaxLength); + base::utils::File::buildStrippedFilename(logMessage->file().c_str(), buff); + buf = base::utils::Str::addToBuff(buff, buf, bufLim); + buf = base::utils::Str::addToBuff(":", buf, bufLim); + buf = base::utils::Str::convertAndAddToBuff(logMessage->line(), + base::consts::kSourceLineMaxLength, buf, bufLim, false); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kLogLocationFormatSpecifier, std::string(buff)); + } + if (logMessage->level() == Level::Verbose && logFormat->hasFlag(base::FormatFlags::VerboseLevel)) { + // Verbose level + char* buf = base::utils::Str::clearBuff(buff, 1); + buf = base::utils::Str::convertAndAddToBuff(logMessage->verboseLevel(), 1, buf, bufLim, false); + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kVerboseLevelFormatSpecifier, std::string(buff)); + } + if (logFormat->hasFlag(base::FormatFlags::LogMessage)) { + // Log message + base::utils::Str::replaceFirstWithEscape(logLine, base::consts::kMessageFormatSpecifier, logMessage->message()); + } +#if !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) + for (std::vector<CustomFormatSpecifier>::const_iterator it = ELPP->customFormatSpecifiers()->begin(); + it != ELPP->customFormatSpecifiers()->end(); ++it) { + std::string fs(it->formatSpecifier()); + base::type::string_t wcsFormatSpecifier(fs.begin(), fs.end()); + base::utils::Str::replaceFirstWithEscape(logLine, wcsFormatSpecifier, std::string(it->resolver()())); + } +#endif // !defined(ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS) + if (appendNewLine) logLine += ELPP_LITERAL("\n"); + return logLine; + } + }; + /// @brief Dispatches log messages + class LogDispatcher : base::NoCopy { + public: + LogDispatcher(bool proceed, LogMessage&& logMessage, base::DispatchAction dispatchAction) : + m_proceed(proceed), + m_logMessage(std::move(logMessage)), + m_dispatchAction(std::move(dispatchAction)) { + } + + void dispatch(void) { + if (m_proceed && m_dispatchAction == base::DispatchAction::None) { + m_proceed = false; + } + if (!m_proceed) { + return; + } + // We minimize the time of ELPP's lock - this lock is released after log is written + base::threading::ScopedLock scopedLock(ELPP->lock()); + base::TypedConfigurations* tc = m_logMessage.logger()->m_typedConfigurations; + if (ELPP->hasFlag(LoggingFlag::StrictLogFileSizeCheck)) { + tc->validateFileRolling(m_logMessage.level(), ELPP->preRollOutCallback()); + } + LogDispatchCallback* callback = nullptr; + LogDispatchData data; + for (const std::pair<std::string, base::type::LogDispatchCallbackPtr>& h + : ELPP->m_logDispatchCallbacks) { + callback = h.second.get(); + if (callback != nullptr && callback->enabled()) { + data.setLogMessage(&m_logMessage); + data.setDispatchAction(m_dispatchAction); + callback->acquireLock(); + callback->handle(&data); + callback->releaseLock(); + } + } + } + + private: + bool m_proceed; + LogMessage m_logMessage; + base::DispatchAction m_dispatchAction; + }; +#if defined(ELPP_STL_LOGGING) + /// @brief Workarounds to write some STL logs + /// + /// @detail There is workaround needed to loop through some stl containers. In order to do that, we need iterable containers + /// of same type and provide iterator interface and pass it on to writeIterator(). + /// Remember, this is passed by value in constructor so that we dont change original containers. + /// This operation is as expensive as Big-O(std::min(class_.size(), base::consts::kMaxLogPerContainer)) + namespace workarounds { + /// @brief Abstract IterableContainer template that provides interface for iterable classes of type T + template <typename T, typename Container> + class IterableContainer { + public: + typedef typename Container::iterator iterator; + typedef typename Container::const_iterator const_iterator; + IterableContainer(void) {} + virtual ~IterableContainer(void) {} + iterator begin(void) { return getContainer().begin(); } + iterator end(void) { return getContainer().end(); } + private: + virtual Container& getContainer(void) = 0; + }; + /// @brief Implements IterableContainer and provides iterable std::priority_queue class + template<typename T, typename Container = std::vector<T>, typename Comparator = std::less<typename Container::value_type>> + class IterablePriorityQueue : public IterableContainer<T, Container>, public std::priority_queue<T, Container, Comparator> { + public: + IterablePriorityQueue(std::priority_queue<T, Container, Comparator> queue_) { + std::size_t count_ = 0; + while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { + this->push(queue_.top()); + queue_.pop(); + } + } + private: + inline Container& getContainer(void) { + return this->c; + } + }; + /// @brief Implements IterableContainer and provides iterable std::queue class + template<typename T, typename Container = std::deque<T>> + class IterableQueue : public IterableContainer<T, Container>, public std::queue<T, Container> { + public: + IterableQueue(std::queue<T, Container> queue_) { + std::size_t count_ = 0; + while (++count_ < base::consts::kMaxLogPerContainer && !queue_.empty()) { + this->push(queue_.front()); + queue_.pop(); + } + } + private: + inline Container& getContainer(void) { + return this->c; + } + }; + /// @brief Implements IterableContainer and provides iterable std::stack class + template<typename T, typename Container = std::deque<T>> + class IterableStack : public IterableContainer<T, Container>, public std::stack<T, Container> { + public: + IterableStack(std::stack<T, Container> stack_) { + std::size_t count_ = 0; + while (++count_ < base::consts::kMaxLogPerContainer && !stack_.empty()) { + this->push(stack_.top()); + stack_.pop(); + } + } + private: + inline Container& getContainer(void) { + return this->c; + } + }; + } // namespace workarounds +#endif // defined(ELPP_STL_LOGGING) + // Log message builder + class MessageBuilder { + public: + MessageBuilder(void) : m_logger(nullptr), m_containerLogSeperator(ELPP_LITERAL("")) {} + void initialize(Logger* logger) { + m_logger = logger; + m_containerLogSeperator = ELPP->hasFlag(LoggingFlag::NewLineForContainer) ? + ELPP_LITERAL("\n ") : ELPP_LITERAL(", "); + } + +# define ELPP_SIMPLE_LOG(LOG_TYPE)\ + inline MessageBuilder& operator<<(LOG_TYPE msg) {\ + m_logger->stream() << msg;\ + if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) {\ + m_logger->stream() << " ";\ + }\ + return *this;\ + } + + inline MessageBuilder& operator<<(const std::string& msg) { + return operator<<(msg.c_str()); + } + ELPP_SIMPLE_LOG(char) + ELPP_SIMPLE_LOG(bool) + ELPP_SIMPLE_LOG(signed short) + ELPP_SIMPLE_LOG(unsigned short) + ELPP_SIMPLE_LOG(signed int) + ELPP_SIMPLE_LOG(unsigned int) + ELPP_SIMPLE_LOG(signed long) + ELPP_SIMPLE_LOG(unsigned long) + ELPP_SIMPLE_LOG(float) + ELPP_SIMPLE_LOG(double) + ELPP_SIMPLE_LOG(char*) + ELPP_SIMPLE_LOG(const char*) + ELPP_SIMPLE_LOG(const void*) + ELPP_SIMPLE_LOG(long double) + inline MessageBuilder& operator<<(const std::wstring& msg) { + return operator<<(msg.c_str()); + } + inline MessageBuilder& operator<<(const wchar_t* msg) { + if (msg == nullptr) { + m_logger->stream() << base::consts::kNullPointer; + return *this; + } +# if defined(ELPP_UNICODE) + m_logger->stream() << msg; +# else + char* buff_ = base::utils::Str::wcharPtrToCharPtr(msg); + m_logger->stream() << buff_; + free(buff_); +# endif + if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) { + m_logger->stream() << " "; + } + return *this; + } + // ostream manipulators + inline MessageBuilder& operator<<(std::ostream& (*OStreamMani)(std::ostream&)) { + m_logger->stream() << OStreamMani; + return *this; + } +#define ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(temp) \ + template <typename T> \ + inline MessageBuilder& operator<<(const temp<T>& template_inst) { \ + return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ + } +#define ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(temp) \ + template <typename T1, typename T2> \ + inline MessageBuilder& operator<<(const temp<T1, T2>& template_inst) { \ + return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ + } +#define ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(temp) \ + template <typename T1, typename T2, typename T3> \ + inline MessageBuilder& operator<<(const temp<T1, T2, T3>& template_inst) { \ + return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ + } +#define ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(temp) \ + template <typename T1, typename T2, typename T3, typename T4> \ + inline MessageBuilder& operator<<(const temp<T1, T2, T3, T4>& template_inst) { \ + return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ + } +#define ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(temp) \ + template <typename T1, typename T2, typename T3, typename T4, typename T5> \ + inline MessageBuilder& operator<<(const temp<T1, T2, T3, T4, T5>& template_inst) { \ + return writeIterator(template_inst.begin(), template_inst.end(), template_inst.size()); \ + } + +#if defined(ELPP_STL_LOGGING) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::vector) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::list) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(std::deque) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::set) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(std::multiset) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::map) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::multimap) + template <class T, class Container> + inline MessageBuilder& operator<<(const std::queue<T, Container>& queue_) { + base::workarounds::IterableQueue<T, Container> iterableQueue_ = + static_cast<base::workarounds::IterableQueue<T, Container> >(queue_); + return writeIterator(iterableQueue_.begin(), iterableQueue_.end(), iterableQueue_.size()); + } + template <class T, class Container> + inline MessageBuilder& operator<<(const std::stack<T, Container>& stack_) { + base::workarounds::IterableStack<T, Container> iterableStack_ = + static_cast<base::workarounds::IterableStack<T, Container> >(stack_); + return writeIterator(iterableStack_.begin(), iterableStack_.end(), iterableStack_.size()); + } + template <class T, class Container, class Comparator> + inline MessageBuilder& operator<<(const std::priority_queue<T, Container, Comparator>& priorityQueue_) { + base::workarounds::IterablePriorityQueue<T, Container, Comparator> iterablePriorityQueue_ = + static_cast<base::workarounds::IterablePriorityQueue<T, Container, Comparator> >(priorityQueue_); + return writeIterator(iterablePriorityQueue_.begin(), iterablePriorityQueue_.end(), iterablePriorityQueue_.size()); + } + template <class First, class Second> + inline MessageBuilder& operator<<(const std::pair<First, Second>& pair_) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast<First>(pair_.first)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast<Second>(pair_.second)); + m_logger->stream() << ELPP_LITERAL(")"); + return *this; + } + template <std::size_t Size> + inline MessageBuilder& operator<<(const std::bitset<Size>& bitset_) { + m_logger->stream() << ELPP_LITERAL("["); + operator << (bitset_.to_string()); + m_logger->stream() << ELPP_LITERAL("]"); + return *this; + } +# if defined(ELPP_LOG_STD_ARRAY) + template <class T, std::size_t Size> + inline MessageBuilder& operator<<(const std::array<T, Size>& array) { + return writeIterator(array.begin(), array.end(), array.size()); + } +# endif // defined(ELPP_LOG_STD_ARRAY) +# if defined(ELPP_LOG_UNORDERED_MAP) + ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_map) + ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG(std::unordered_multimap) +# endif // defined(ELPP_LOG_UNORDERED_MAP) +# if defined(ELPP_LOG_UNORDERED_SET) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_set) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(std::unordered_multiset) +# endif // defined(ELPP_LOG_UNORDERED_SET) +#endif // defined(ELPP_STL_LOGGING) +#if defined(ELPP_QT_LOGGING) + inline MessageBuilder& operator<<(const QString& msg) { +# if defined(ELPP_UNICODE) + m_logger->stream() << msg.toStdWString(); +# else + m_logger->stream() << msg.toStdString(); +# endif // defined(ELPP_UNICODE) + return *this; + } + inline MessageBuilder& operator<<(const QByteArray& msg) { + return operator << (QString(msg)); + } + inline MessageBuilder& operator<<(const QStringRef& msg) { + return operator<<(msg.toString()); + } + inline MessageBuilder& operator<<(qint64 msg) { +# if defined(ELPP_UNICODE) + m_logger->stream() << QString::number(msg).toStdWString(); +# else + m_logger->stream() << QString::number(msg).toStdString(); +# endif // defined(ELPP_UNICODE) + return *this; + } + inline MessageBuilder& operator<<(quint64 msg) { +# if defined(ELPP_UNICODE) + m_logger->stream() << QString::number(msg).toStdWString(); +# else + m_logger->stream() << QString::number(msg).toStdString(); +# endif // defined(ELPP_UNICODE) + return *this; + } + inline MessageBuilder& operator<<(QChar msg) { + m_logger->stream() << msg.toLatin1(); + return *this; + } + inline MessageBuilder& operator<<(const QLatin1String& msg) { + m_logger->stream() << msg.latin1(); + return *this; + } + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QList) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QVector) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QQueue) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QSet) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QLinkedList) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(QStack) + template <typename First, typename Second> + inline MessageBuilder& operator<<(const QPair<First, Second>& pair_) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast<First>(pair_.first)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast<Second>(pair_.second)); + m_logger->stream() << ELPP_LITERAL(")"); + return *this; + } + template <typename K, typename V> + inline MessageBuilder& operator<<(const QMap<K, V>& map_) { + m_logger->stream() << ELPP_LITERAL("["); + QList<K> keys = map_.keys(); + typename QList<K>::const_iterator begin = keys.begin(); + typename QList<K>::const_iterator end = keys.end(); + int max_ = static_cast<int>(base::consts::kMaxLogPerContainer); // to prevent warning + for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast<K>(*begin)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast<V>(map_.value(*begin))); + m_logger->stream() << ELPP_LITERAL(")"); + m_logger->stream() << ((index_ < keys.size() - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); + } + if (begin != end) { + m_logger->stream() << ELPP_LITERAL("..."); + } + m_logger->stream() << ELPP_LITERAL("]"); + return *this; + } + template <typename K, typename V> + inline MessageBuilder& operator<<(const QMultiMap<K, V>& map_) { + operator << (static_cast<QMap<K, V>>(map_)); + return *this; + } + template <typename K, typename V> + inline MessageBuilder& operator<<(const QHash<K, V>& hash_) { + m_logger->stream() << ELPP_LITERAL("["); + QList<K> keys = hash_.keys(); + typename QList<K>::const_iterator begin = keys.begin(); + typename QList<K>::const_iterator end = keys.end(); + int max_ = static_cast<int>(base::consts::kMaxLogPerContainer); // prevent type warning + for (int index_ = 0; begin != end && index_ < max_; ++index_, ++begin) { + m_logger->stream() << ELPP_LITERAL("("); + operator << (static_cast<K>(*begin)); + m_logger->stream() << ELPP_LITERAL(", "); + operator << (static_cast<V>(hash_.value(*begin))); + m_logger->stream() << ELPP_LITERAL(")"); + m_logger->stream() << ((index_ < keys.size() - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); + } + if (begin != end) { + m_logger->stream() << ELPP_LITERAL("..."); + } + m_logger->stream() << ELPP_LITERAL("]"); + return *this; + } + template <typename K, typename V> + inline MessageBuilder& operator<<(const QMultiHash<K, V>& multiHash_) { + operator << (static_cast<QHash<K, V>>(multiHash_)); + return *this; + } +#endif // defined(ELPP_QT_LOGGING) +#if defined(ELPP_BOOST_LOGGING) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::vector) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::stable_vector) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::list) + ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG(boost::container::deque) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::map) + ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG(boost::container::flat_map) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::set) + ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG(boost::container::flat_set) +#endif // defined(ELPP_BOOST_LOGGING) + + /// @brief Macro used internally that can be used externally to make containers easylogging++ friendly + /// + /// @detail This macro expands to write an ostream& operator<< for container. This container is expected to + /// have begin() and end() methods that return respective iterators + /// @param ContainerType Type of container e.g, MyList from WX_DECLARE_LIST(int, MyList); in wxwidgets + /// @param SizeMethod Method used to get size of container. + /// @param ElementInstance Instance of element to be fed out. Insance name is "elem". See WXELPP_ENABLED macro + /// for an example usage +#define MAKE_CONTAINERELPP_FRIENDLY(ContainerType, SizeMethod, ElementInstance) \ + el::base::type::ostream_t& operator<<(el::base::type::ostream_t& ss, const ContainerType& container) {\ + const el::base::type::char_t* sep = ELPP->hasFlag(el::LoggingFlag::NewLineForContainer) ? \ + ELPP_LITERAL("\n ") : ELPP_LITERAL(", ");\ + ContainerType::const_iterator elem = container.begin();\ + ContainerType::const_iterator endElem = container.end();\ + std::size_t size_ = container.SizeMethod; \ + ss << ELPP_LITERAL("[");\ + for (std::size_t i = 0; elem != endElem && i < el::base::consts::kMaxLogPerContainer; ++i, ++elem) { \ + ss << ElementInstance;\ + ss << ((i < size_ - 1) ? sep : ELPP_LITERAL(""));\ + }\ + if (elem != endElem) {\ + ss << ELPP_LITERAL("...");\ + }\ + ss << ELPP_LITERAL("]");\ + return ss;\ + } +#if defined(ELPP_WXWIDGETS_LOGGING) + ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG(wxVector) +# define ELPP_WX_PTR_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), *(*elem)) +# define ELPP_WX_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), (*elem)) +# define ELPP_WX_HASH_MAP_ENABLED(ContainerType) MAKE_CONTAINERELPP_FRIENDLY(ContainerType, size(), \ + ELPP_LITERAL("(") << elem->first << ELPP_LITERAL(", ") << elem->second << ELPP_LITERAL(")") +#else +# define ELPP_WX_PTR_ENABLED(ContainerType) +# define ELPP_WX_ENABLED(ContainerType) +# define ELPP_WX_HASH_MAP_ENABLED(ContainerType) +#endif // defined(ELPP_WXWIDGETS_LOGGING) + // Other classes + template <class Class> + ELPP_SIMPLE_LOG(const Class&) +#undef ELPP_SIMPLE_LOG +#undef ELPP_ITERATOR_CONTAINER_LOG_ONE_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_TWO_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_THREE_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_FOUR_ARG +#undef ELPP_ITERATOR_CONTAINER_LOG_FIVE_ARG + private: + Logger* m_logger; + const base::type::char_t* m_containerLogSeperator; + + template<class Iterator> + inline MessageBuilder& writeIterator(Iterator begin_, Iterator end_, std::size_t size_) { + m_logger->stream() << ELPP_LITERAL("["); + for (std::size_t i = 0; begin_ != end_ && i < base::consts::kMaxLogPerContainer; ++i, ++begin_) { + operator << (*begin_); + m_logger->stream() << ((i < size_ - 1) ? m_containerLogSeperator : ELPP_LITERAL("")); + } + if (begin_ != end_) { + m_logger->stream() << ELPP_LITERAL("..."); + } + m_logger->stream() << ELPP_LITERAL("]"); + if (ELPP->hasFlag(LoggingFlag::AutoSpacing)) { + m_logger->stream() << " "; + } + return *this; + } + }; + /// @brief Writes nothing - Used when certain log is disabled + class NullWriter : base::NoCopy { + public: + NullWriter(void) {} + + // Null manipulator + inline NullWriter& operator<<(std::ostream& (*)(std::ostream&)) { + return *this; + } + + template <typename T> + inline NullWriter& operator<<(const T&) { + return *this; + } + }; + /// @brief Main entry point of each logging + class Writer : base::NoCopy { + public: + Writer(Level level, const char* file, unsigned long int line, + const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, + base::type::VerboseLevel verboseLevel = 0) : + m_level(level), m_file(file), m_line(line), m_func(func), m_verboseLevel(verboseLevel), + m_proceed(false), m_dispatchAction(dispatchAction) { + } + + virtual ~Writer(void) { + processDispatch(); + } + + template <typename T> + inline Writer& operator<<(const T& log) { +#if ELPP_LOGGING_ENABLED + if (m_proceed) { + m_messageBuilder << log; + } +#endif // ELPP_LOGGING_ENABLED + return *this; + } + + inline Writer& operator<<(std::ostream& (*log)(std::ostream&)) { +#if ELPP_LOGGING_ENABLED + if (m_proceed) { + m_messageBuilder << log; + } +#endif // ELPP_LOGGING_ENABLED + return *this; + } + + Writer& construct(Logger* logger, bool needLock = true) { + m_logger = logger; + initializeLogger(logger->id(), false, needLock); + m_messageBuilder.initialize(m_logger); + return *this; + } + + Writer& construct(int count, const char* loggerIds, ...) { + if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) { + va_list loggersList; + va_start(loggersList, loggerIds); + const char* id = loggerIds; + for (int i = 0; i < count; ++i) { + m_loggerIds.push_back(std::string(id)); + id = va_arg(loggersList, const char*); + } + va_end(loggersList); + initializeLogger(m_loggerIds.at(0)); + } + else { + initializeLogger(std::string(loggerIds)); + } + m_messageBuilder.initialize(m_logger); + return *this; + } + protected: + Level m_level; + const char* m_file; + const unsigned long int m_line; + const char* m_func; + base::type::VerboseLevel m_verboseLevel; + Logger* m_logger; + bool m_proceed; + base::MessageBuilder m_messageBuilder; + base::DispatchAction m_dispatchAction; + std::vector<std::string> m_loggerIds; + friend class el::Helpers; + + void initializeLogger(const std::string& loggerId, bool lookup = true, bool needLock = true) { + if (lookup) { + m_logger = ELPP->registeredLoggers()->get(loggerId, ELPP->hasFlag(LoggingFlag::CreateLoggerAutomatically)); + } + if (m_logger == nullptr) { + ELPP->acquireLock(); + if (!ELPP->registeredLoggers()->has(std::string(base::consts::kDefaultLoggerId))) { + // Somehow default logger has been unregistered. Not good! Register again + ELPP->registeredLoggers()->get(std::string(base::consts::kDefaultLoggerId)); + } + ELPP->releaseLock(); // Need to unlock it for next writer + Writer(Level::Debug, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) + << "Logger [" << loggerId << "] is not registered yet!"; + m_proceed = false; + } + else { + if (needLock) { + m_logger->acquireLock(); // This should not be unlocked by checking m_proceed because + // m_proceed can be changed by lines below + } + if (ELPP->hasFlag(LoggingFlag::HierarchicalLogging)) { + m_proceed = m_level == Level::Verbose ? m_logger->enabled(m_level) : + LevelHelper::castToInt(m_level) >= LevelHelper::castToInt(ELPP->m_loggingLevel); + } + else { + m_proceed = m_logger->enabled(m_level); + } + } + } + + void processDispatch() { +#if ELPP_LOGGING_ENABLED + if (ELPP->hasFlag(LoggingFlag::MultiLoggerSupport)) { + bool firstDispatched = false; + base::type::string_t logMessage; + std::size_t i = 0; + do { + if (m_proceed) { + if (firstDispatched) { + m_logger->stream() << logMessage; + } + else { + firstDispatched = true; + if (m_loggerIds.size() > 1) { + logMessage = m_logger->stream().str(); + } + } + triggerDispatch(); + } + else if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } + if (i + 1 < m_loggerIds.size()) { + initializeLogger(m_loggerIds.at(i + 1)); + } + } while (++i < m_loggerIds.size()); + } + else { + if (m_proceed) { + triggerDispatch(); + } + else if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } + } +#else + if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } +#endif // ELPP_LOGGING_ENABLED + } + + void triggerDispatch(void) { + if (m_proceed) { + base::LogDispatcher(m_proceed, LogMessage(m_level, m_file, m_line, m_func, m_verboseLevel, + m_logger), m_dispatchAction).dispatch(); + } + if (m_logger != nullptr) { + m_logger->stream().str(ELPP_LITERAL("")); + m_logger->releaseLock(); + } + if (m_proceed && m_level == Level::Fatal + && !ELPP->hasFlag(LoggingFlag::DisableApplicationAbortOnFatalLog)) { + base::Writer(Level::Warning, m_file, m_line, m_func).construct(1, base::consts::kDefaultLoggerId) + << "Aborting application. Reason: Fatal log at [" << m_file << ":" << m_line << "]"; + std::stringstream reasonStream; + reasonStream << "Fatal log at [" << m_file << ":" << m_line << "]" + << " If you wish to disable 'abort on fatal log' please use " + << "el::Helpers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog)"; + base::utils::abort(1, reasonStream.str()); + } + m_proceed = false; + } + }; + class PErrorWriter : public base::Writer { + public: + PErrorWriter(Level level, const char* file, unsigned long int line, + const char* func, base::DispatchAction dispatchAction = base::DispatchAction::NormalLog, + base::type::VerboseLevel verboseLevel = 0) : + base::Writer(level, file, line, func, dispatchAction, verboseLevel) { + } + + virtual ~PErrorWriter(void) { + if (m_proceed) { +#if ELPP_COMPILER_MSVC + char buff[256]; + strerror_s(buff, 256, errno); + m_logger->stream() << ": " << buff << " [" << errno << "]"; +#else + m_logger->stream() << ": " << strerror(errno) << " [" << errno << "]"; +#endif + } + } + }; + } // namespace base + // Logging from Logger class. Why this is here? Because we have Storage and Writer class available +#if ELPP_VARIADIC_TEMPLATES_SUPPORTED + template <typename T, typename... Args> + void Logger::log_(Level level, int vlevel, const char* s, const T& value, const Args&... args) { + base::MessageBuilder b; + b.initialize(this); + while (*s) { + if (*s == base::consts::kFormatSpecifierChar) { + if (*(s + 1) == base::consts::kFormatSpecifierChar) { + ++s; + } + else { + if (*(s + 1) == base::consts::kFormatSpecifierCharValue) { + ++s; + b << value; + log_(level, vlevel, ++s, args...); + return; + } + } + } + b << *s++; + } + ELPP_INTERNAL_ERROR("Too many arguments provided. Unable to handle. Please provide more format specifiers", false); + } + template <typename T> + inline void Logger::log_(Level level, int vlevel, const T& log) { + if (level == Level::Verbose) { + if (ELPP->vRegistry()->allowed(vlevel, __FILE__)) { + base::Writer(Level::Verbose, "FILE", 0, "FUNCTION", + base::DispatchAction::NormalLog, vlevel).construct(this, false) << log; + } + else { + stream().str(ELPP_LITERAL("")); + } + } + else { + base::Writer(level, "FILE", 0, "FUNCTION").construct(this, false) << log; + } + } + template <typename T, typename... Args> + void Logger::log(Level level, const char* s, const T& value, const Args&... args) { + base::threading::ScopedLock scopedLock(lock()); + log_(level, 0, s, value, args...); + } + template <typename T> + inline void Logger::log(Level level, const T& log) { + base::threading::ScopedLock scopedLock(lock()); + log_(level, 0, log); + } +# if ELPP_VERBOSE_LOG + template <typename T, typename... Args> + inline void Logger::verbose(int vlevel, const char* s, const T& value, const Args&... args) { + base::threading::ScopedLock scopedLock(lock()); + log_(el::Level::Verbose, vlevel, s, value, args...); + } + template <typename T> + inline void Logger::verbose(int vlevel, const T& log) { + base::threading::ScopedLock scopedLock(lock()); + log_(el::Level::Verbose, vlevel, log); + } +# else + template <typename T, typename... Args> + inline void Logger::verbose(int, const char*, const T&, const Args&...) { + return; + } + template <typename T> + inline void Logger::verbose(int, const T&) { + return; + } +# endif // ELPP_VERBOSE_LOG +# define LOGGER_LEVEL_WRITERS(FUNCTION_NAME, LOG_LEVEL)\ + template <typename T, typename... Args>\ + inline void Logger::FUNCTION_NAME(const char* s, const T& value, const Args&... args) {\ + log(LOG_LEVEL, s, value, args...);\ + }\ + template <typename T>\ + inline void Logger::FUNCTION_NAME(const T& value) {\ + log(LOG_LEVEL, value);\ + } +# define LOGGER_LEVEL_WRITERS_DISABLED(FUNCTION_NAME, LOG_LEVEL)\ + template <typename T, typename... Args>\ + inline void Logger::FUNCTION_NAME(const char*, const T&, const Args&...) {\ + return;\ + }\ + template <typename T>\ + inline void Logger::FUNCTION_NAME(const T&) {\ + return;\ + } + +# if ELPP_INFO_LOG + LOGGER_LEVEL_WRITERS(info, Level::Info) +# else + LOGGER_LEVEL_WRITERS_DISABLED(info, Level::Info) +# endif // ELPP_INFO_LOG +# if ELPP_DEBUG_LOG + LOGGER_LEVEL_WRITERS(debug, Level::Debug) +# else + LOGGER_LEVEL_WRITERS_DISABLED(debug, Level::Debug) +# endif // ELPP_DEBUG_LOG +# if ELPP_WARNING_LOG + LOGGER_LEVEL_WRITERS(warn, Level::Warning) +# else + LOGGER_LEVEL_WRITERS_DISABLED(warn, Level::Warning) +# endif // ELPP_WARNING_LOG +# if ELPP_ERROR_LOG + LOGGER_LEVEL_WRITERS(error, Level::Error) +# else + LOGGER_LEVEL_WRITERS_DISABLED(error, Level::Error) +# endif // ELPP_ERROR_LOG +# if ELPP_FATAL_LOG + LOGGER_LEVEL_WRITERS(fatal, Level::Fatal) +# else + LOGGER_LEVEL_WRITERS_DISABLED(fatal, Level::Fatal) +# endif // ELPP_FATAL_LOG +# if ELPP_TRACE_LOG + LOGGER_LEVEL_WRITERS(trace, Level::Trace) +# else + LOGGER_LEVEL_WRITERS_DISABLED(trace, Level::Trace) +# endif // ELPP_TRACE_LOG +# undef LOGGER_LEVEL_WRITERS +# undef LOGGER_LEVEL_WRITERS_DISABLED +#endif // ELPP_VARIADIC_TEMPLATES_SUPPORTED +#if ELPP_COMPILER_MSVC +# define ELPP_VARIADIC_FUNC_MSVC(variadicFunction, variadicArgs) variadicFunction variadicArgs +# define ELPP_VARIADIC_FUNC_MSVC_RUN(variadicFunction, ...) ELPP_VARIADIC_FUNC_MSVC(variadicFunction, (__VA_ARGS__)) +# define el_getVALength(...) ELPP_VARIADIC_FUNC_MSVC_RUN(el_resolveVALength, 0, ## __VA_ARGS__,\ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +#else +# if ELPP_COMPILER_CLANG +# define el_getVALength(...) el_resolveVALength(0, __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +# else +# define el_getVALength(...) el_resolveVALength(0, ## __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) +# endif // ELPP_COMPILER_CLANG +#endif // ELPP_COMPILER_MSVC +#define el_resolveVALength(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N +#define ELPP_WRITE_LOG(writer, level, dispatchAction, ...) \ + writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_IF(writer, condition, level, dispatchAction, ...) if (condition) \ + writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_EVERY_N(writer, occasion, level, dispatchAction, ...) \ + if (ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion)) \ + writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_AFTER_N(writer, n, level, dispatchAction, ...) \ + if (ELPP->validateAfterNCounter(__FILE__, __LINE__, n)) \ + writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#define ELPP_WRITE_LOG_N_TIMES(writer, n, level, dispatchAction, ...) \ + if (ELPP->validateNTimesCounter(__FILE__, __LINE__, n)) \ + writer(level, __FILE__, __LINE__, ELPP_FUNC, dispatchAction).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#undef ELPP_CURR_FILE_PERFORMANCE_LOGGER +#if defined(ELPP_PERFORMANCE_LOGGER) +# define ELPP_CURR_FILE_PERFORMANCE_LOGGER ELPP_PERFORMANCE_LOGGER +#else +# define ELPP_CURR_FILE_PERFORMANCE_LOGGER el::base::consts::kPerformanceLoggerId +#endif + class PerformanceTrackingData { + public: + enum class DataType : base::type::EnumType { + Checkpoint = 1, Complete = 2 + }; + // Do not use constructor, will run into multiple definition error, use init(PerformanceTracker*) + explicit PerformanceTrackingData(DataType dataType) : m_performanceTracker(nullptr), + m_dataType(dataType), m_file(""), m_line(0), m_func("") {} + inline const std::string* blockName(void) const; + inline const struct timeval* startTime(void) const; + inline const struct timeval* endTime(void) const; + inline const struct timeval* lastCheckpointTime(void) const; + inline const base::PerformanceTracker* performanceTracker(void) const { return m_performanceTracker; } + inline PerformanceTrackingData::DataType dataType(void) const { return m_dataType; } + inline bool firstCheckpoint(void) const { return m_firstCheckpoint; } + inline std::string checkpointId(void) const { return m_checkpointId; } + inline const char* file(void) const { return m_file; } + inline unsigned long int line(void) const { return m_line; } + inline const char* func(void) const { return m_func; } + inline const base::type::string_t* formattedTimeTaken() const { return &m_formattedTimeTaken; } + inline const std::string& loggerId(void) const; + private: + base::PerformanceTracker* m_performanceTracker; + base::type::string_t m_formattedTimeTaken; + PerformanceTrackingData::DataType m_dataType; + bool m_firstCheckpoint; + std::string m_checkpointId; + const char* m_file; + unsigned long int m_line; + const char* m_func; + inline void init(base::PerformanceTracker* performanceTracker, bool firstCheckpoint = false) { + m_performanceTracker = performanceTracker; + m_firstCheckpoint = firstCheckpoint; + } + + friend class el::base::PerformanceTracker; + }; + namespace base { + /// @brief Represents performanceTracker block of code that conditionally adds performance status to log + /// either when goes outside the scope of when checkpoint() is called + class PerformanceTracker : public base::threading::ThreadSafe, public Loggable { + public: + PerformanceTracker(const std::string& blockName, + base::TimestampUnit timestampUnit = base::TimestampUnit::Millisecond, + const std::string& loggerId = std::string(ELPP_CURR_FILE_PERFORMANCE_LOGGER), + bool scopedLog = true, Level level = base::consts::kPerformanceTrackerDefaultLevel) : + m_blockName(blockName), m_timestampUnit(timestampUnit), m_loggerId(loggerId), m_scopedLog(scopedLog), + m_level(level), m_hasChecked(false), m_lastCheckpointId(std::string()), m_enabled(false) { +#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + // We store it locally so that if user happen to change configuration by the end of scope + // or before calling checkpoint, we still depend on state of configuraton at time of construction + el::Logger* loggerPtr = ELPP->registeredLoggers()->get(loggerId, false); + m_enabled = loggerPtr != nullptr && loggerPtr->m_typedConfigurations->performanceTracking(m_level); + if (m_enabled) { + base::utils::DateTime::gettimeofday(&m_startTime); + } +#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + } + /// @brief Copy constructor + PerformanceTracker(const PerformanceTracker& t) : + m_blockName(t.m_blockName), m_timestampUnit(t.m_timestampUnit), m_loggerId(t.m_loggerId), m_scopedLog(t.m_scopedLog), + m_level(t.m_level), m_hasChecked(t.m_hasChecked), m_lastCheckpointId(t.m_lastCheckpointId), m_enabled(t.m_enabled), + m_startTime(t.m_startTime), m_endTime(t.m_endTime), m_lastCheckpointTime(t.m_lastCheckpointTime) { + } + virtual ~PerformanceTracker(void) { +#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + if (m_enabled) { + base::threading::ScopedLock scopedLock(lock()); + if (m_scopedLog) { + base::utils::DateTime::gettimeofday(&m_endTime); + base::type::string_t formattedTime = getFormattedTimeTaken(); + PerformanceTrackingData data(PerformanceTrackingData::DataType::Complete); + data.init(this); + data.m_formattedTimeTaken = formattedTime; + PerformanceTrackingCallback* callback = nullptr; + for (const std::pair<std::string, base::type::PerformanceTrackingCallbackPtr>& h + : ELPP->m_performanceTrackingCallbacks) { + callback = h.second.get(); + if (callback != nullptr && callback->enabled()) { + callback->acquireLock(); + callback->handle(&data); + callback->releaseLock(); + } + } + } + } +#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) + } + /// @brief A checkpoint for current performanceTracker block. + void checkpoint(const std::string& id = std::string(), const char* file = __FILE__, unsigned long int line = __LINE__, const char* func = "") { +#if !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + if (m_enabled) { + base::threading::ScopedLock scopedLock(lock()); + base::utils::DateTime::gettimeofday(&m_endTime); + base::type::string_t formattedTime = m_hasChecked ? getFormattedTimeTaken(m_lastCheckpointTime) : ELPP_LITERAL(""); + PerformanceTrackingData data(PerformanceTrackingData::DataType::Checkpoint); + data.init(this); + data.m_checkpointId = id; + data.m_file = file; + data.m_line = line; + data.m_func = func; + data.m_formattedTimeTaken = formattedTime; + PerformanceTrackingCallback* callback = nullptr; + for (const std::pair<std::string, base::type::PerformanceTrackingCallbackPtr>& h + : ELPP->m_performanceTrackingCallbacks) { + callback = h.second.get(); + if (callback != nullptr && callback->enabled()) { + callback->acquireLock(); + callback->handle(&data); + callback->releaseLock(); + } + } + base::utils::DateTime::gettimeofday(&m_lastCheckpointTime); + m_hasChecked = true; + m_lastCheckpointId = id; + } +#endif // !defined(ELPP_DISABLE_PERFORMANCE_TRACKING) && ELPP_LOGGING_ENABLED + ELPP_UNUSED(id); + ELPP_UNUSED(file); + ELPP_UNUSED(line); + ELPP_UNUSED(func); + } + inline Level level(void) const { return m_level; } + private: + std::string m_blockName; + base::TimestampUnit m_timestampUnit; + std::string m_loggerId; + bool m_scopedLog; + Level m_level; + bool m_hasChecked; + std::string m_lastCheckpointId; + bool m_enabled; + struct timeval m_startTime, m_endTime, m_lastCheckpointTime; + + PerformanceTracker(void); + + friend class el::PerformanceTrackingData; + friend class base::DefaultPerformanceTrackingCallback; + + const inline base::type::string_t getFormattedTimeTaken() const { + return getFormattedTimeTaken(m_startTime); + } + + const base::type::string_t getFormattedTimeTaken(struct timeval startTime) const { + if (ELPP->hasFlag(LoggingFlag::FixedTimeFormat)) { + base::type::stringstream_t ss; + ss << base::utils::DateTime::getTimeDifference(m_endTime, + startTime, m_timestampUnit) << " " << base::consts::kTimeFormats[static_cast<base::type::EnumType>(m_timestampUnit)].unit; + return ss.str(); + } + return base::utils::DateTime::formatTime(base::utils::DateTime::getTimeDifference(m_endTime, + startTime, m_timestampUnit), m_timestampUnit); + } + + virtual inline void log(el::base::type::ostream_t& os) const { + os << getFormattedTimeTaken(); + } + }; + class DefaultPerformanceTrackingCallback : public PerformanceTrackingCallback { + protected: + void handle(const PerformanceTrackingData* data) { + m_data = data; + base::type::stringstream_t ss; + if (m_data->dataType() == PerformanceTrackingData::DataType::Complete) { + ss << ELPP_LITERAL("Executed [") << m_data->blockName()->c_str() << ELPP_LITERAL("] in [") << *m_data->formattedTimeTaken() << ELPP_LITERAL("]"); + } + else { + ss << ELPP_LITERAL("Performance checkpoint"); + if (!m_data->checkpointId().empty()) { + ss << ELPP_LITERAL(" [") << m_data->checkpointId().c_str() << ELPP_LITERAL("]"); + } + ss << ELPP_LITERAL(" for block [") << m_data->blockName()->c_str() << ELPP_LITERAL("] : [") << *m_data->performanceTracker(); + if (!ELPP->hasFlag(LoggingFlag::DisablePerformanceTrackingCheckpointComparison) && m_data->performanceTracker()->m_hasChecked) { + ss << ELPP_LITERAL(" ([") << *m_data->formattedTimeTaken() << ELPP_LITERAL("] from "); + if (m_data->performanceTracker()->m_lastCheckpointId.empty()) { + ss << ELPP_LITERAL("last checkpoint"); + } + else { + ss << ELPP_LITERAL("checkpoint '") << m_data->performanceTracker()->m_lastCheckpointId.c_str() << ELPP_LITERAL("'"); + } + ss << ELPP_LITERAL(")]"); + } + else { + ss << ELPP_LITERAL("]"); + } + } + el::base::Writer(m_data->performanceTracker()->level(), m_data->file(), m_data->line(), m_data->func()).construct(1, m_data->loggerId().c_str()) << ss.str(); + } + private: + const PerformanceTrackingData* m_data; + }; + } // namespace base + inline const std::string* PerformanceTrackingData::blockName() const { + return const_cast<const std::string*>(&m_performanceTracker->m_blockName); + } + inline const struct timeval* PerformanceTrackingData::startTime() const { + return const_cast<const struct timeval*>(&m_performanceTracker->m_startTime); + } + inline const struct timeval* PerformanceTrackingData::endTime() const { + return const_cast<const struct timeval*>(&m_performanceTracker->m_endTime); + } + inline const struct timeval* PerformanceTrackingData::lastCheckpointTime() const { + return const_cast<const struct timeval*>(&m_performanceTracker->m_lastCheckpointTime); + } + inline const std::string& PerformanceTrackingData::loggerId(void) const { return m_performanceTracker->m_loggerId; } + namespace base { + /// @brief Contains some internal debugging tools like crash handler and stack tracer + namespace debug { + class StackTrace : base::NoCopy { + public: + static const std::size_t kMaxStack = 64; + static const std::size_t kStackStart = 2; // We want to skip c'tor and StackTrace::generateNew() + class StackTraceEntry { + public: + StackTraceEntry(std::size_t index, const char* loc, const char* demang, const char* hex, const char* addr) { + m_index = index; + m_location = std::string(loc); + m_demangled = std::string(demang); + m_hex = std::string(hex); + m_addr = std::string(addr); + } + StackTraceEntry(std::size_t index, char* loc) { + m_index = index; + m_location = std::string(loc); + } + std::size_t m_index; + std::string m_location; + std::string m_demangled; + std::string m_hex; + std::string m_addr; + friend std::ostream& operator<<(std::ostream& ss, const StackTraceEntry& si) { + ss << "[" << si.m_index << "] " << si.m_location << (si.m_demangled.empty() ? "" : ":") << si.m_demangled + << (si.m_hex.empty() ? "" : "+") << si.m_hex << si.m_addr; + return ss; + } + + private: + StackTraceEntry(void); + }; + + StackTrace(void) { + generateNew(); + } + + virtual ~StackTrace(void) { + } + + inline std::vector<StackTraceEntry>& getLatestStack(void) { + return m_stack; + } + + friend inline std::ostream& operator<<(std::ostream& os, const StackTrace& st) { + std::vector<StackTraceEntry>::const_iterator it = st.m_stack.begin(); + while (it != st.m_stack.end()) { + os << " " << *it++ << "\n"; + } + return os; + } + + private: + std::vector<StackTraceEntry> m_stack; + + void generateNew(void) { +#if ELPP_STACKTRACE + m_stack.clear(); + void* stack[kMaxStack]; + std::size_t size = backtrace(stack, kMaxStack); + char** strings = backtrace_symbols(stack, size); + if (size > kStackStart) { // Skip StackTrace c'tor and generateNew + for (std::size_t i = kStackStart; i < size; ++i) { + char* mangName = nullptr; + char* hex = nullptr; + char* addr = nullptr; + for (char* c = strings[i]; *c; ++c) { + switch (*c) { + case '(': + mangName = c; + break; + case '+': + hex = c; + break; + case ')': + addr = c; + break; + } + } + // Perform demangling if parsed properly + if (mangName != nullptr && hex != nullptr && addr != nullptr && mangName < hex) { + *mangName++ = '\0'; + *hex++ = '\0'; + *addr++ = '\0'; + int status = 0; + char* demangName = abi::__cxa_demangle(mangName, 0, 0, &status); + // if demangling is successful, output the demangled function name + if (status == 0) { + // Success (see http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html) + StackTraceEntry entry(i - 1, strings[i], demangName, hex, addr); + m_stack.push_back(entry); + } + else { + // Not successful - we will use mangled name + StackTraceEntry entry(i - 1, strings[i], mangName, hex, addr); + m_stack.push_back(entry); + } + free(demangName); + } + else { + StackTraceEntry entry(i - 1, strings[i]); + m_stack.push_back(entry); + } + } + } + free(strings); +#else + ELPP_INTERNAL_INFO(1, "Stacktrace generation not supported for selected compiler"); +#endif // ELPP_STACKTRACE + } + }; + static std::string crashReason(int sig) { + std::stringstream ss; + bool foundReason = false; + for (int i = 0; i < base::consts::kCrashSignalsCount; ++i) { + if (base::consts::kCrashSignals[i].numb == sig) { + ss << "Application has crashed due to [" << base::consts::kCrashSignals[i].name << "] signal"; + if (ELPP->hasFlag(el::LoggingFlag::LogDetailedCrashReason)) { + ss << std::endl << + " " << base::consts::kCrashSignals[i].brief << std::endl << + " " << base::consts::kCrashSignals[i].detail; + } + foundReason = true; + } + } + if (!foundReason) { + ss << "Application has crashed due to unknown signal [" << sig << "]"; + } + return ss.str(); + } + /// @brief Logs reason of crash from sig + static void logCrashReason(int sig, bool stackTraceIfAvailable, Level level, const char* logger) { + std::stringstream ss; + ss << "CRASH HANDLED; "; + ss << crashReason(sig); +#if ELPP_STACKTRACE + if (stackTraceIfAvailable) { + ss << std::endl << " ======= Backtrace: =========" << std::endl << base::debug::StackTrace(); + } +#else + ELPP_UNUSED(stackTraceIfAvailable); +#endif // ELPP_STACKTRACE + ELPP_WRITE_LOG(el::base::Writer, level, base::DispatchAction::NormalLog, logger) << ss.str(); + } + static inline void crashAbort(int sig) { + base::utils::abort(sig); + } + /// @brief Default application crash handler + /// + /// @detail This function writes log using 'default' logger, prints stack trace for GCC based compilers and aborts program. + static inline void defaultCrashHandler(int sig) { + base::debug::logCrashReason(sig, true, Level::Fatal, base::consts::kDefaultLoggerId); + base::debug::crashAbort(sig); + } + /// @brief Handles unexpected crashes + class CrashHandler : base::NoCopy { + public: + typedef void(*Handler)(int); + + explicit CrashHandler(bool useDefault) { + if (useDefault) { + setHandler(defaultCrashHandler); + } + } + explicit CrashHandler(const Handler& cHandler) { + setHandler(cHandler); + } + void setHandler(const Handler& cHandler) { + m_handler = cHandler; +#if defined(ELPP_HANDLE_SIGABRT) + int i = 0; // SIGABRT is at base::consts::kCrashSignals[0] +#else + int i = 1; +#endif // defined(ELPP_HANDLE_SIGABRT) + for (; i < base::consts::kCrashSignalsCount; ++i) { + m_handler = signal(base::consts::kCrashSignals[i].numb, cHandler); + } + } + + private: + Handler m_handler; + }; + } // namespace debug + } // namespace base + extern base::debug::CrashHandler elCrashHandler; +#define MAKE_LOGGABLE(ClassType, ClassInstance, OutputStreamInstance) \ + el::base::type::ostream_t& operator<<(el::base::type::ostream_t& OutputStreamInstance, const ClassType& ClassInstance) + /// @brief Initializes syslog with process ID, options and facility. calls closelog() on d'tor + class SysLogInitializer { + public: + SysLogInitializer(const char* processIdent, int options = 0, int facility = 0) { +#if defined(ELPP_SYSLOG) + openlog(processIdent, options, facility); +#else + ELPP_UNUSED(processIdent); + ELPP_UNUSED(options); + ELPP_UNUSED(facility); +#endif // defined(ELPP_SYSLOG) + } + virtual ~SysLogInitializer(void) { +#if defined(ELPP_SYSLOG) + closelog(); +#endif // defined(ELPP_SYSLOG) + } + }; +#define ELPP_INITIALIZE_SYSLOG(id, opt, fac) el::SysLogInitializer elSyslogInit(id, opt, fac) + /// @brief Static helpers for developers + class Helpers : base::StaticClass { + public: + /// @brief Shares logging repository (base::Storage) + static inline void setStorage(base::type::StoragePointer storage) { + ELPP = storage; + } + /// @return Main storage repository + static inline base::type::StoragePointer storage() { + return ELPP; + } + /// @brief Sets application arguments and figures out whats active for logging and whats not. + static inline void setArgs(int argc, char** argv) { + ELPP->setApplicationArguments(argc, argv); + } + /// @copydoc setArgs(int argc, char** argv) + static inline void setArgs(int argc, const char** argv) { + ELPP->setApplicationArguments(argc, const_cast<char**>(argv)); + } + /// @brief Overrides default crash handler and installs custom handler. + /// @param crashHandler A functor with no return type that takes single int argument. + /// Handler is a typedef with specification: void (*Handler)(int) + static inline void setCrashHandler(const el::base::debug::CrashHandler::Handler& crashHandler) { + el::elCrashHandler.setHandler(crashHandler); + } + /// @brief Abort due to crash with signal in parameter + /// @param sig Crash signal + static inline void crashAbort(int sig, const char* sourceFile = "", unsigned int long line = 0) { + std::stringstream ss; + ss << base::debug::crashReason(sig).c_str(); + ss << " - [Called el::Helpers::crashAbort(" << sig << ")]"; + if (sourceFile != nullptr && strlen(sourceFile) > 0) { + ss << " - Source: " << sourceFile; + if (line > 0) + ss << ":" << line; + else + ss << " (line number not specified)"; + } + base::utils::abort(sig, ss.str()); + } + /// @brief Logs reason of crash as per sig + /// @param sig Crash signal + /// @param stackTraceIfAvailable Includes stack trace if available + /// @param level Logging level + /// @param logger Logger to use for logging + static inline void logCrashReason(int sig, bool stackTraceIfAvailable = false, + Level level = Level::Fatal, const char* logger = base::consts::kDefaultLoggerId) { + el::base::debug::logCrashReason(sig, stackTraceIfAvailable, level, logger); + } + /// @brief Installs pre rollout callback, this callback is triggered when log file is about to be rolled out + /// (can be useful for backing up) + static inline void installPreRollOutCallback(const PreRollOutCallback& callback) { + ELPP->setPreRollOutCallback(callback); + } + /// @brief Uninstalls pre rollout callback + static inline void uninstallPreRollOutCallback(void) { + ELPP->unsetPreRollOutCallback(); + } + /// @brief Installs post log dispatch callback, this callback is triggered when log is dispatched + template <typename T> + static inline bool installLogDispatchCallback(const std::string& id) { + return ELPP->installLogDispatchCallback<T>(id); + } + /// @brief Uninstalls log dispatch callback + template <typename T> + static inline void uninstallLogDispatchCallback(const std::string& id) { + ELPP->uninstallLogDispatchCallback<T>(id); + } + template <typename T> + static inline T* logDispatchCallback(const std::string& id) { + return ELPP->logDispatchCallback<T>(id); + } + /// @brief Installs post performance tracking callback, this callback is triggered when performance tracking is finished + template <typename T> + static inline bool installPerformanceTrackingCallback(const std::string& id) { + return ELPP->installPerformanceTrackingCallback<T>(id); + } + /// @brief Uninstalls post performance tracking handler + template <typename T> + static inline void uninstallPerformanceTrackingCallback(const std::string& id) { + ELPP->uninstallPerformanceTrackingCallback<T>(id); + } + template <typename T> + static inline T* performanceTrackingCallback(const std::string& id) { + return ELPP->performanceTrackingCallback<T>(id); + } + /// @brief Converts template to std::string - useful for loggable classes to log containers within log(std::ostream&) const + template <typename T> + static std::string convertTemplateToStdString(const T& templ) { + el::Logger* logger = + ELPP->registeredLoggers()->get(el::base::consts::kDefaultLoggerId); + if (logger == nullptr) { + return std::string(); + } + base::MessageBuilder b; + b.initialize(logger); + logger->acquireLock(); + b << templ; +#if defined(ELPP_UNICODE) + std::string s = std::string(logger->stream().str().begin(), logger->stream().str().end()); +#else + std::string s = logger->stream().str(); +#endif // defined(ELPP_UNICODE) + logger->stream().str(ELPP_LITERAL("")); + logger->releaseLock(); + return s; + } + /// @brief Returns command line arguments (pointer) provided to easylogging++ + static inline const el::base::utils::CommandLineArgs* commandLineArgs(void) { + return ELPP->commandLineArgs(); + } + /// @brief Installs user defined format specifier and handler + static inline void installCustomFormatSpecifier(const CustomFormatSpecifier& customFormatSpecifier) { + ELPP->installCustomFormatSpecifier(customFormatSpecifier); + } + /// @brief Uninstalls user defined format specifier and handler + static inline bool uninstallCustomFormatSpecifier(const char* formatSpecifier) { + return ELPP->uninstallCustomFormatSpecifier(formatSpecifier); + } + /// @brief Returns true if custom format specifier is installed + static inline bool hasCustomFormatSpecifier(const char* formatSpecifier) { + return ELPP->hasCustomFormatSpecifier(formatSpecifier); + } + static inline void validateFileRolling(Logger* logger, Level level) { + if (logger == nullptr) return; + logger->m_typedConfigurations->validateFileRolling(level, ELPP->preRollOutCallback()); + } + }; + /// @brief Static helpers to deal with loggers and their configurations + class Loggers : base::StaticClass { + public: + /// @brief Gets existing or registers new logger + static inline Logger* getLogger(const std::string& identity, bool registerIfNotAvailable = true) { + base::threading::ScopedLock scopedLock(ELPP->lock()); + return ELPP->registeredLoggers()->get(identity, registerIfNotAvailable); + } + /// @brief Unregisters logger - use it only when you know what you are doing, you may unregister + /// loggers initialized / used by third-party libs. + static inline bool unregisterLogger(const std::string& identity) { + base::threading::ScopedLock scopedLock(ELPP->lock()); + return ELPP->registeredLoggers()->remove(identity); + } + /// @brief Whether or not logger with id is registered + static inline bool hasLogger(const std::string& identity) { + base::threading::ScopedLock scopedLock(ELPP->lock()); + return ELPP->registeredLoggers()->has(identity); + } + /// @brief Reconfigures specified logger with new configurations + static inline Logger* reconfigureLogger(Logger* logger, const Configurations& configurations) { + if (!logger) return nullptr; + logger->configure(configurations); + return logger; + } + /// @brief Reconfigures logger with new configurations after looking it up using identity + static inline Logger* reconfigureLogger(const std::string& identity, const Configurations& configurations) { + return Loggers::reconfigureLogger(Loggers::getLogger(identity), configurations); + } + /// @brief Reconfigures logger's single configuration + static inline Logger* reconfigureLogger(const std::string& identity, ConfigurationType configurationType, + const std::string& value) { + Logger* logger = Loggers::getLogger(identity); + if (logger == nullptr) { + return nullptr; + } + logger->configurations()->set(Level::Global, configurationType, value); + logger->reconfigure(); + return logger; + } + /// @brief Reconfigures all the existing loggers with new configurations + static inline void reconfigureAllLoggers(const Configurations& configurations) { + for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); + it != ELPP->registeredLoggers()->end(); ++it) { + Loggers::reconfigureLogger(it->second, configurations); + } + } + /// @brief Reconfigures single configuration for all the loggers + static inline void reconfigureAllLoggers(ConfigurationType configurationType, const std::string& value) { + reconfigureAllLoggers(Level::Global, configurationType, value); + } + /// @brief Reconfigures single configuration for all the loggers for specified level + static inline void reconfigureAllLoggers(Level level, ConfigurationType configurationType, + const std::string& value) { + for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->begin(); + it != ELPP->registeredLoggers()->end(); ++it) { + Logger* logger = it->second; + logger->configurations()->set(level, configurationType, value); + logger->reconfigure(); + } + } + /// @brief Sets default configurations. This configuration is used for future (and conditionally for existing) loggers + static inline void setDefaultConfigurations(const Configurations& configurations, bool reconfigureExistingLoggers = false) { + ELPP->registeredLoggers()->setDefaultConfigurations(configurations); + if (reconfigureExistingLoggers) { + Loggers::reconfigureAllLoggers(configurations); + } + } + /// @brief Returns current default + static inline const Configurations* defaultConfigurations(void) { + return ELPP->registeredLoggers()->defaultConfigurations(); + } + /// @brief Returns log stream reference pointer if needed by user + static inline const base::LogStreamsReferenceMap* logStreamsReference(void) { + return ELPP->registeredLoggers()->logStreamsReference(); + } + /// @brief Default typed configuration based on existing defaultConf + static base::TypedConfigurations defaultTypedConfigurations(void) { + return base::TypedConfigurations( + ELPP->registeredLoggers()->defaultConfigurations(), + ELPP->registeredLoggers()->logStreamsReference()); + } + /// @brief Populates all logger IDs in current repository. + /// @param [out] targetList List of fill up. + static inline std::vector<std::string>* populateAllLoggerIds(std::vector<std::string>* targetList) { + targetList->clear(); + for (base::RegisteredLoggers::iterator it = ELPP->registeredLoggers()->list().begin(); + it != ELPP->registeredLoggers()->list().end(); ++it) { + targetList->push_back(it->first); + } + return targetList; + } + /// @brief Sets configurations from global configuration file. + static void configureFromGlobal(const char* globalConfigurationFilePath) { + std::ifstream gcfStream(globalConfigurationFilePath, std::ifstream::in); + ELPP_ASSERT(gcfStream.is_open(), "Unable to open global configuration file [" << globalConfigurationFilePath + << "] for parsing."); + std::string line = std::string(); + std::stringstream ss; + Logger* logger = nullptr; + auto configure = [&](void) { + ELPP_INTERNAL_INFO(8, "Configuring logger: '" << logger->id() << "' with configurations \n" << ss.str() + << "\n--------------"); + Configurations c; + c.parseFromText(ss.str()); + logger->configure(c); + }; + while (gcfStream.good()) { + std::getline(gcfStream, line); + ELPP_INTERNAL_INFO(1, "Parsing line: " << line); + base::utils::Str::trim(line); + if (Configurations::Parser::isComment(line)) continue; + Configurations::Parser::ignoreComments(&line); + base::utils::Str::trim(line); + if (line.size() > 2 && base::utils::Str::startsWith(line, std::string(base::consts::kConfigurationLoggerId))) { + if (!ss.str().empty() && logger != nullptr) { + configure(); + } + ss.str(std::string("")); + line = line.substr(2); + base::utils::Str::trim(line); + if (line.size() > 1) { + ELPP_INTERNAL_INFO(1, "Getting logger: '" << line << "'"); + logger = getLogger(line); + } + } + else { + ss << line << "\n"; + } + } + if (!ss.str().empty() && logger != nullptr) { + configure(); + } + } + /// @brief Configures loggers using command line arg. Ensure you have already set command line args, + /// @return False if invalid argument or argument with no value provided, true if attempted to configure logger. + /// If true is returned that does not mean it has been configured successfully, it only means that it + /// has attempeted to configure logger using configuration file provided in argument + static inline bool configureFromArg(const char* argKey) { +#if defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) + ELPP_UNUSED(argKey); +#else + if (!Helpers::commandLineArgs()->hasParamWithValue(argKey)) { + return false; + } + configureFromGlobal(Helpers::commandLineArgs()->getParamValue(argKey)); +#endif // defined(ELPP_DISABLE_CONFIGURATION_FROM_PROGRAM_ARGS) + return true; + } + /// @brief Flushes all loggers for all levels - Be careful if you dont know how many loggers are registered + static inline void flushAll(void) { + ELPP->registeredLoggers()->flushAll(); + } + /// @brief Adds logging flag used internally. + static inline void addFlag(LoggingFlag flag) { + ELPP->addFlag(flag); + } + /// @brief Removes logging flag used internally. + static inline void removeFlag(LoggingFlag flag) { + ELPP->removeFlag(flag); + } + /// @brief Determines whether or not certain flag is active + static inline bool hasFlag(LoggingFlag flag) { + return ELPP->hasFlag(flag); + } + /// @brief Adds flag and removes it when scope goes out + class ScopedAddFlag { + public: + ScopedAddFlag(LoggingFlag flag) : m_flag(flag) { Loggers::addFlag(m_flag); } + ~ScopedAddFlag(void) { Loggers::removeFlag(m_flag); } + private: + LoggingFlag m_flag; + }; + /// @brief Removes flag and add it when scope goes out + class ScopedRemoveFlag { + public: + ScopedRemoveFlag(LoggingFlag flag) : m_flag(flag) { Loggers::removeFlag(m_flag); } + ~ScopedRemoveFlag(void) { Loggers::addFlag(m_flag); } + private: + LoggingFlag m_flag; + }; + /// @brief Sets hierarchy for logging. Needs to enable logging flag (HierarchicalLogging) + static inline void setLoggingLevel(Level level) { + ELPP->setLoggingLevel(level); + } + /// @brief Sets verbose level on the fly + static inline void setVerboseLevel(base::type::VerboseLevel level) { + ELPP->vRegistry()->setLevel(level); + } + /// @brief Gets current verbose level + static inline base::type::VerboseLevel verboseLevel(void) { + return ELPP->vRegistry()->level(); + } + /// @brief Sets vmodules as specified (on the fly) + static inline void setVModules(const char* modules) { + if (ELPP->vRegistry()->vModulesEnabled()) { + ELPP->vRegistry()->setModules(modules); + } + } + /// @brief Clears vmodules + static inline void clearVModules(void) { + ELPP->vRegistry()->clearModules(); + } + }; + class VersionInfo : base::StaticClass { + public: + /// @brief Current version number + static inline const std::string version(void) { return std::string("9.80"); } + /// @brief Release date of current version + static inline const std::string releaseDate(void) { return std::string("08-01-2015 0850hrs"); } + }; +} // namespace el +#undef VLOG_IS_ON + /// @brief Determines whether verbose logging is on for specified level current file. +#define VLOG_IS_ON(verboseLevel) (ELPP->vRegistry()->allowed(verboseLevel, __FILE__)) +#undef TIMED_BLOCK +#undef TIMED_SCOPE +#undef TIMED_FUNC +#undef ELPP_MIN_UNIT +#if defined(ELPP_PERFORMANCE_MICROSECONDS) +# define ELPP_MIN_UNIT el::base::TimestampUnit::Microsecond +#else +# define ELPP_MIN_UNIT el::base::TimestampUnit::Millisecond +#endif // (defined(ELPP_PERFORMANCE_MICROSECONDS)) + /// @brief Performance tracked scope. Performance gets written when goes out of scope using + /// 'performance' logger. + /// + /// @detail Please note in order to check the performance at a certain time you can use obj.checkpoint(); + /// @see el::base::PerformanceTracker + /// @see el::base::PerformanceTracker::checkpoint + // Note: Do not surround this definition with null macro because of obj instance +#define TIMED_SCOPE(obj, blockname) el::base::PerformanceTracker obj(blockname, ELPP_MIN_UNIT) +#define TIMED_BLOCK(obj, blockName) for (struct { int i; el::base::PerformanceTracker timer; } obj = { 0, \ + el::base::PerformanceTracker(blockName, ELPP_MIN_UNIT) }; obj.i < 1; ++obj.i) + /// @brief Performance tracked function. Performance gets written when goes out of scope using + /// 'performance' logger. + /// + /// @detail Please note in order to check the performance at a certain time you can use obj.checkpoint(); + /// @see el::base::PerformanceTracker + /// @see el::base::PerformanceTracker::checkpoint +#define TIMED_FUNC(obj) TIMED_SCOPE(obj, ELPP_FUNC) +#undef PERFORMANCE_CHECKPOINT +#undef PERFORMANCE_CHECKPOINT_WITH_ID +#define PERFORMANCE_CHECKPOINT(obj) obj.checkpoint(std::string(), __FILE__, __LINE__, ELPP_FUNC) +#define PERFORMANCE_CHECKPOINT_WITH_ID(obj, id) obj.checkpoint(id, __FILE__, __LINE__, ELPP_FUNC) +#undef ELPP_COUNTER +#undef ELPP_COUNTER_POS + /// @brief Gets hit counter for file/line +#define ELPP_COUNTER (ELPP->hitCounters()->getCounter(__FILE__, __LINE__)) + /// @brief Gets hit counter position for file/line, -1 if not registered yet +#define ELPP_COUNTER_POS (ELPP_COUNTER == nullptr ? -1 : ELPP_COUNTER->hitCounts()) + // Undef levels to support LOG(LEVEL) +#undef INFO +#undef WARNING +#undef DEBUG +#undef ERROR +#undef FATAL +#undef TRACE +#undef VERBOSE + // Undef existing +#undef CINFO +#undef CWARNING +#undef CDEBUG +#undef CFATAL +#undef CERROR +#undef CTRACE +#undef CVERBOSE +#undef CINFO_IF +#undef CWARNING_IF +#undef CDEBUG_IF +#undef CERROR_IF +#undef CFATAL_IF +#undef CTRACE_IF +#undef CVERBOSE_IF +#undef CINFO_EVERY_N +#undef CWARNING_EVERY_N +#undef CDEBUG_EVERY_N +#undef CERROR_EVERY_N +#undef CFATAL_EVERY_N +#undef CTRACE_EVERY_N +#undef CVERBOSE_EVERY_N +#undef CINFO_AFTER_N +#undef CWARNING_AFTER_N +#undef CDEBUG_AFTER_N +#undef CERROR_AFTER_N +#undef CFATAL_AFTER_N +#undef CTRACE_AFTER_N +#undef CVERBOSE_AFTER_N +#undef CINFO_N_TIMES +#undef CWARNING_N_TIMES +#undef CDEBUG_N_TIMES +#undef CERROR_N_TIMES +#undef CFATAL_N_TIMES +#undef CTRACE_N_TIMES +#undef CVERBOSE_N_TIMES + // Normal logs +#if ELPP_INFO_LOG +# define CINFO(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE(writer, dispatchAction, ...) ELPP_WRITE_LOG(writer, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE(writer, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE(writer, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel)) writer(\ + el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#else +# define CVERBOSE(writer, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG + // Conditional logs +#if ELPP_INFO_LOG +# define CINFO_IF(writer, condition_, dispatchAction, ...) \ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_IF(writer, condition_, dispatchAction, ...)\ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_IF(writer, condition_, dispatchAction, ...)\ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_IF(writer, condition_, dispatchAction, ...)\ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_IF(writer, condition_, dispatchAction, ...)\ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_IF(writer, condition_, dispatchAction, ...)\ + ELPP_WRITE_LOG_IF(writer, (condition_), el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_IF(writer, condition_, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) if (VLOG_IS_ON(vlevel) && (condition_)) writer( \ + el::Level::Verbose, __FILE__, __LINE__, ELPP_FUNC, dispatchAction, vlevel).construct(el_getVALength(__VA_ARGS__), __VA_ARGS__) +#else +# define CVERBOSE_IF(writer, condition_, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG + // Occasional logs +#if ELPP_INFO_LOG +# define CINFO_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...)\ + ELPP_WRITE_LOG_EVERY_N(writer, occasion, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_EVERY_N(writer, occasion, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...)\ + CVERBOSE_IF(writer, ELPP->validateEveryNCounter(__FILE__, __LINE__, occasion), vlevel, dispatchAction, __VA_ARGS__) +#else +# define CVERBOSE_EVERY_N(writer, occasion, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG + // After N logs +#if ELPP_INFO_LOG +# define CINFO_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_AFTER_N(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_AFTER_N(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_AFTER_N(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...)\ + CVERBOSE_IF(writer, ELPP->validateAfterNCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) +#else +# define CVERBOSE_AFTER_N(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG + // N Times logs +#if ELPP_INFO_LOG +# define CINFO_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Info, dispatchAction, __VA_ARGS__) +#else +# define CINFO_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_INFO_LOG +#if ELPP_WARNING_LOG +# define CWARNING_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Warning, dispatchAction, __VA_ARGS__) +#else +# define CWARNING_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_WARNING_LOG +#if ELPP_DEBUG_LOG +# define CDEBUG_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Debug, dispatchAction, __VA_ARGS__) +#else +# define CDEBUG_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_DEBUG_LOG +#if ELPP_ERROR_LOG +# define CERROR_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Error, dispatchAction, __VA_ARGS__) +#else +# define CERROR_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_ERROR_LOG +#if ELPP_FATAL_LOG +# define CFATAL_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Fatal, dispatchAction, __VA_ARGS__) +#else +# define CFATAL_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_FATAL_LOG +#if ELPP_TRACE_LOG +# define CTRACE_N_TIMES(writer, n, dispatchAction, ...)\ + ELPP_WRITE_LOG_N_TIMES(writer, n, el::Level::Trace, dispatchAction, __VA_ARGS__) +#else +# define CTRACE_N_TIMES(writer, n, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_TRACE_LOG +#if ELPP_VERBOSE_LOG +# define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...)\ + CVERBOSE_IF(writer, ELPP->validateNTimesCounter(__FILE__, __LINE__, n), vlevel, dispatchAction, __VA_ARGS__) +#else +# define CVERBOSE_N_TIMES(writer, n, vlevel, dispatchAction, ...) el::base::NullWriter() +#endif // ELPP_VERBOSE_LOG + // + // Custom Loggers - Requires (level, dispatchAction, loggerId/s) + // + // undef existing +#undef CLOG +#undef CLOG_VERBOSE +#undef CVLOG +#undef CLOG_IF +#undef CLOG_VERBOSE_IF +#undef CVLOG_IF +#undef CLOG_EVERY_N +#undef CVLOG_EVERY_N +#undef CLOG_AFTER_N +#undef CVLOG_AFTER_N +#undef CLOG_N_TIMES +#undef CVLOG_N_TIMES + // Normal logs +#define CLOG(LEVEL, ...)\ + C##LEVEL(el::base::Writer, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG(vlevel, ...) CVERBOSE(el::base::Writer, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) + // Conditional logs +#define CLOG_IF(condition, LEVEL, ...)\ + C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_IF(condition, vlevel, ...)\ + CVERBOSE_IF(el::base::Writer, condition, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) + // Hit counts based logs +#define CLOG_EVERY_N(n, LEVEL, ...)\ + C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_EVERY_N(n, vlevel, ...)\ + CVERBOSE_EVERY_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CLOG_AFTER_N(n, LEVEL, ...)\ + C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_AFTER_N(n, vlevel, ...)\ + CVERBOSE_AFTER_N(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CLOG_N_TIMES(n, LEVEL, ...)\ + C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CVLOG_N_TIMES(n, vlevel, ...)\ + CVERBOSE_N_TIMES(el::base::Writer, n, vlevel, el::base::DispatchAction::NormalLog, __VA_ARGS__) + // + // Default Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros + // + // undef existing +#undef LOG +#undef VLOG +#undef LOG_IF +#undef VLOG_IF +#undef LOG_EVERY_N +#undef VLOG_EVERY_N +#undef LOG_AFTER_N +#undef VLOG_AFTER_N +#undef LOG_N_TIMES +#undef VLOG_N_TIMES +#undef ELPP_CURR_FILE_LOGGER_ID +#if defined(ELPP_DEFAULT_LOGGER) +# define ELPP_CURR_FILE_LOGGER_ID ELPP_DEFAULT_LOGGER +#else +# define ELPP_CURR_FILE_LOGGER_ID el::base::consts::kDefaultLoggerId +#endif +#undef ELPP_TRACE +#define ELPP_TRACE CLOG(TRACE, ELPP_CURR_FILE_LOGGER_ID) + // Normal logs +#define LOG(LEVEL) CLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG(vlevel) CVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Conditional logs +#define LOG_IF(condition, LEVEL) CLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_IF(condition, vlevel) CVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Hit counts based logs +#define LOG_EVERY_N(n, LEVEL) CLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_EVERY_N(n, vlevel) CVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define LOG_AFTER_N(n, LEVEL) CLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_AFTER_N(n, vlevel) CVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define LOG_N_TIMES(n, LEVEL) CLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define VLOG_N_TIMES(n, vlevel) CVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Generic PLOG() +#undef CPLOG +#undef CPLOG_IF +#undef PLOG +#undef PLOG_IF +#undef DCPLOG +#undef DCPLOG_IF +#undef DPLOG +#undef DPLOG_IF +#define CPLOG(LEVEL, ...)\ + C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define CPLOG_IF(condition, LEVEL, ...)\ + C##LEVEL##_IF(el::base::PErrorWriter, condition, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define DCPLOG(LEVEL, ...)\ + if (ELPP_DEBUG_LOG) C##LEVEL(el::base::PErrorWriter, el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define DCPLOG_IF(condition, LEVEL, ...)\ + C##LEVEL##_IF(el::base::PErrorWriter, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::NormalLog, __VA_ARGS__) +#define PLOG(LEVEL) CPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define PLOG_IF(condition, LEVEL) CPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DPLOG(LEVEL) DCPLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DPLOG_IF(condition, LEVEL) DCPLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) + // Generic SYSLOG() +#undef CSYSLOG +#undef CSYSLOG_IF +#undef CSYSLOG_EVERY_N +#undef CSYSLOG_AFTER_N +#undef CSYSLOG_N_TIMES +#undef SYSLOG +#undef SYSLOG_IF +#undef SYSLOG_EVERY_N +#undef SYSLOG_AFTER_N +#undef SYSLOG_N_TIMES +#undef DCSYSLOG +#undef DCSYSLOG_IF +#undef DCSYSLOG_EVERY_N +#undef DCSYSLOG_AFTER_N +#undef DCSYSLOG_N_TIMES +#undef DSYSLOG +#undef DSYSLOG_IF +#undef DSYSLOG_EVERY_N +#undef DSYSLOG_AFTER_N +#undef DSYSLOG_N_TIMES +#if defined(ELPP_SYSLOG) +# define CSYSLOG(LEVEL, ...)\ + C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_IF(condition, LEVEL, ...)\ + C##LEVEL##_IF(el::base::Writer, condition, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_EVERY_N(n, LEVEL, ...) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_AFTER_N(n, LEVEL, ...) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define CSYSLOG_N_TIMES(n, LEVEL, ...) C##LEVEL##_N_TIMES(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define SYSLOG(LEVEL) CSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_IF(condition, LEVEL) CSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_EVERY_N(n, LEVEL) CSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_AFTER_N(n, LEVEL) CSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define SYSLOG_N_TIMES(n, LEVEL) CSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define DCSYSLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) C##LEVEL(el::base::Writer, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_IF(condition, LEVEL, ...)\ + C##LEVEL##_IF(el::base::Writer, (ELPP_DEBUG_LOG) && (condition), el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_EVERY_N(n, LEVEL, ...)\ + if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_AFTER_N(n, LEVEL, ...)\ + if (ELPP_DEBUG_LOG) C##LEVEL##_AFTER_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DCSYSLOG_N_TIMES(n, LEVEL, ...)\ + if (ELPP_DEBUG_LOG) C##LEVEL##_EVERY_N(el::base::Writer, n, el::base::DispatchAction::SysLog, __VA_ARGS__) +# define DSYSLOG(LEVEL) DCSYSLOG(LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_IF(condition, LEVEL) DCSYSLOG_IF(condition, LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_EVERY_N(n, LEVEL) DCSYSLOG_EVERY_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_AFTER_N(n, LEVEL) DCSYSLOG_AFTER_N(n, LEVEL, el::base::consts::kSysLogLoggerId) +# define DSYSLOG_N_TIMES(n, LEVEL) DCSYSLOG_N_TIMES(n, LEVEL, el::base::consts::kSysLogLoggerId) +#else +# define CSYSLOG(LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() +# define CSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() +# define SYSLOG(LEVEL) el::base::NullWriter() +# define SYSLOG_IF(condition, LEVEL) el::base::NullWriter() +# define SYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() +# define SYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() +# define SYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() +# define DCSYSLOG(LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_IF(condition, LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_EVERY_N(n, LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_AFTER_N(n, LEVEL, ...) el::base::NullWriter() +# define DCSYSLOG_N_TIMES(n, LEVEL, ...) el::base::NullWriter() +# define DSYSLOG(LEVEL) el::base::NullWriter() +# define DSYSLOG_IF(condition, LEVEL) el::base::NullWriter() +# define DSYSLOG_EVERY_N(n, LEVEL) el::base::NullWriter() +# define DSYSLOG_AFTER_N(n, LEVEL) el::base::NullWriter() +# define DSYSLOG_N_TIMES(n, LEVEL) el::base::NullWriter() +#endif // defined(ELPP_SYSLOG) + // + // Custom Debug Only Loggers - Requires (level, loggerId/s) + // + // undef existing +#undef DCLOG +#undef DCVLOG +#undef DCLOG_IF +#undef DCVLOG_IF +#undef DCLOG_EVERY_N +#undef DCVLOG_EVERY_N +#undef DCLOG_AFTER_N +#undef DCVLOG_AFTER_N +#undef DCLOG_N_TIMES +#undef DCVLOG_N_TIMES + // Normal logs +#define DCLOG(LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG(LEVEL, __VA_ARGS__) +#define DCLOG_VERBOSE(vlevel, ...) if (ELPP_DEBUG_LOG) CLOG_VERBOSE(vlevel, __VA_ARGS__) +#define DCVLOG(vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG(vlevel, __VA_ARGS__) + // Conditional logs +#define DCLOG_IF(condition, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_IF(condition, LEVEL, __VA_ARGS__) +#define DCVLOG_IF(condition, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_IF(condition, vlevel, __VA_ARGS__) + // Hit counts based logs +#define DCLOG_EVERY_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_EVERY_N(n, LEVEL, __VA_ARGS__) +#define DCVLOG_EVERY_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_EVERY_N(n, vlevel, __VA_ARGS__) +#define DCLOG_AFTER_N(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_AFTER_N(n, LEVEL, __VA_ARGS__) +#define DCVLOG_AFTER_N(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_AFTER_N(n, vlevel, __VA_ARGS__) +#define DCLOG_N_TIMES(n, LEVEL, ...) if (ELPP_DEBUG_LOG) CLOG_N_TIMES(n, LEVEL, __VA_ARGS__) +#define DCVLOG_N_TIMES(n, vlevel, ...) if (ELPP_DEBUG_LOG) CVLOG_N_TIMES(n, vlevel, __VA_ARGS__) + // + // Default Debug Only Loggers macro using CLOG(), CLOG_VERBOSE() and CVLOG() macros + // + // undef existing +#undef DLOG +#undef DVLOG +#undef DLOG_IF +#undef DVLOG_IF +#undef DLOG_EVERY_N +#undef DVLOG_EVERY_N +#undef DLOG_AFTER_N +#undef DVLOG_AFTER_N +#undef DLOG_N_TIMES +#undef DVLOG_N_TIMES + // Normal logs +#define DLOG(LEVEL) DCLOG(LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG(vlevel) DCVLOG(vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Conditional logs +#define DLOG_IF(condition, LEVEL) DCLOG_IF(condition, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_IF(condition, vlevel) DCVLOG_IF(condition, vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Hit counts based logs +#define DLOG_EVERY_N(n, LEVEL) DCLOG_EVERY_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_EVERY_N(n, vlevel) DCVLOG_EVERY_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define DLOG_AFTER_N(n, LEVEL) DCLOG_AFTER_N(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_AFTER_N(n, vlevel) DCVLOG_AFTER_N(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) +#define DLOG_N_TIMES(n, LEVEL) DCLOG_N_TIMES(n, LEVEL, ELPP_CURR_FILE_LOGGER_ID) +#define DVLOG_N_TIMES(n, vlevel) DCVLOG_N_TIMES(n, vlevel, ELPP_CURR_FILE_LOGGER_ID) + // Check macros +#undef CCHECK +#undef CPCHECK +#undef CCHECK_EQ +#undef CCHECK_NE +#undef CCHECK_LT +#undef CCHECK_GT +#undef CCHECK_LE +#undef CCHECK_GE +#undef CCHECK_BOUNDS +#undef CCHECK_NOTNULL +#undef CCHECK_STRCASEEQ +#undef CCHECK_STRCASENE +#undef CHECK +#undef PCHECK +#undef CHECK_EQ +#undef CHECK_NE +#undef CHECK_LT +#undef CHECK_GT +#undef CHECK_LE +#undef CHECK_GE +#undef CHECK_BOUNDS +#undef CHECK_NOTNULL +#undef CHECK_STRCASEEQ +#undef CHECK_STRCASENE +#define CCHECK(condition, ...) CLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " +#define CPCHECK(condition, ...) CPLOG_IF(!(condition), FATAL, __VA_ARGS__) << "Check failed: [" << #condition << "] " +#define CHECK(condition) CCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#define PCHECK(condition) CPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#define CCHECK_EQ(a, b, ...) CCHECK(a == b, __VA_ARGS__) +#define CCHECK_NE(a, b, ...) CCHECK(a != b, __VA_ARGS__) +#define CCHECK_LT(a, b, ...) CCHECK(a < b, __VA_ARGS__) +#define CCHECK_GT(a, b, ...) CCHECK(a > b, __VA_ARGS__) +#define CCHECK_LE(a, b, ...) CCHECK(a <= b, __VA_ARGS__) +#define CCHECK_GE(a, b, ...) CCHECK(a >= b, __VA_ARGS__) +#define CCHECK_BOUNDS(val, min, max, ...) CCHECK(val >= min && val <= max, __VA_ARGS__) +#define CHECK_EQ(a, b) CCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_NE(a, b) CCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_LT(a, b) CCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_GT(a, b) CCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_LE(a, b) CCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_GE(a, b) CCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_BOUNDS(val, min, max) CCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) +namespace el { + namespace base { + namespace utils { + template <typename T> + static T* checkNotNull(T* ptr, const char* name, const char* loggers, ...) { + CLOG_IF(ptr == nullptr, FATAL, loggers) << "Check failed: [" << name << " != nullptr]"; + return ptr; + } + } // namespace utils + } // namespace base +} // namespace el +#define CCHECK_NOTNULL(ptr, ...) el::base::utils::checkNotNull(ptr, #ptr, __VA_ARGS__) +#define CCHECK_STREQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ + << "Check failed: [" << #str1 << " == " << #str2 << "] " +#define CCHECK_STRNE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringEq(str1, str2), FATAL, __VA_ARGS__) \ + << "Check failed: [" << #str1 << " != " << #str2 << "] " +#define CCHECK_STRCASEEQ(str1, str2, ...) CLOG_IF(!el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ + << "Check failed: [" << #str1 << " == " << #str2 << "] " +#define CCHECK_STRCASENE(str1, str2, ...) CLOG_IF(el::base::utils::Str::cStringCaseEq(str1, str2), FATAL, __VA_ARGS__) \ + << "Check failed: [" << #str1 << " != " << #str2 << "] " +#define CHECK_NOTNULL(ptr) CCHECK_NOTNULL(ptr, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STREQ(str1, str2) CCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STRNE(str1, str2) CCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STRCASEEQ(str1, str2) CCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define CHECK_STRCASENE(str1, str2) CCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#undef DCCHECK +#undef DCCHECK_EQ +#undef DCCHECK_NE +#undef DCCHECK_LT +#undef DCCHECK_GT +#undef DCCHECK_LE +#undef DCCHECK_GE +#undef DCCHECK_BOUNDS +#undef DCCHECK_NOTNULL +#undef DCCHECK_STRCASEEQ +#undef DCCHECK_STRCASENE +#undef DCPCHECK +#undef DCHECK +#undef DCHECK_EQ +#undef DCHECK_NE +#undef DCHECK_LT +#undef DCHECK_GT +#undef DCHECK_LE +#undef DCHECK_GE +#undef DCHECK_BOUNDS_ +#undef DCHECK_NOTNULL +#undef DCHECK_STRCASEEQ +#undef DCHECK_STRCASENE +#undef DPCHECK +#define DCCHECK(condition, ...) if (ELPP_DEBUG_LOG) CCHECK(condition, __VA_ARGS__) +#define DCCHECK_EQ(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_EQ(a, b, __VA_ARGS__) +#define DCCHECK_NE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_NE(a, b, __VA_ARGS__) +#define DCCHECK_LT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LT(a, b, __VA_ARGS__) +#define DCCHECK_GT(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GT(a, b, __VA_ARGS__) +#define DCCHECK_LE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_LE(a, b, __VA_ARGS__) +#define DCCHECK_GE(a, b, ...) if (ELPP_DEBUG_LOG) CCHECK_GE(a, b, __VA_ARGS__) +#define DCCHECK_BOUNDS(val, min, max, ...) if (ELPP_DEBUG_LOG) CCHECK_BOUNDS(val, min, max, __VA_ARGS__) +#define DCCHECK_NOTNULL(ptr, ...) if (ELPP_DEBUG_LOG) CCHECK_NOTNULL(ptr, __VA_ARGS__) +#define DCCHECK_STREQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STREQ(str1, str2, __VA_ARGS__) +#define DCCHECK_STRNE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRNE(str1, str2, __VA_ARGS__) +#define DCCHECK_STRCASEEQ(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASEEQ(str1, str2, __VA_ARGS__) +#define DCCHECK_STRCASENE(str1, str2, ...) if (ELPP_DEBUG_LOG) CCHECK_STRCASENE(str1, str2, __VA_ARGS__) +#define DCPCHECK(condition, ...) if (ELPP_DEBUG_LOG) CPCHECK(condition, __VA_ARGS__) +#define DCHECK(condition) DCCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_EQ(a, b) DCCHECK_EQ(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_NE(a, b) DCCHECK_NE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_LT(a, b) DCCHECK_LT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_GT(a, b) DCCHECK_GT(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_LE(a, b) DCCHECK_LE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_GE(a, b) DCCHECK_GE(a, b, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_BOUNDS(val, min, max) DCCHECK_BOUNDS(val, min, max, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_NOTNULL(ptr) DCCHECK_NOTNULL(ptr, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STREQ(str1, str2) DCCHECK_STREQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STRNE(str1, str2) DCCHECK_STRNE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STRCASEEQ(str1, str2) DCCHECK_STRCASEEQ(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DCHECK_STRCASENE(str1, str2) DCCHECK_STRCASENE(str1, str2, ELPP_CURR_FILE_LOGGER_ID) +#define DPCHECK(condition) DCPCHECK(condition, ELPP_CURR_FILE_LOGGER_ID) +#if defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) +# define ELPP_USE_DEF_CRASH_HANDLER false +#else +# define ELPP_USE_DEF_CRASH_HANDLER true +#endif // defined(ELPP_DISABLE_DEFAULT_CRASH_HANDLING) +#define ELPP_CRASH_HANDLER_INIT +#define ELPP_INIT_EASYLOGGINGPP(val)\ + ELPP_INITI_BASIC_DECLR\ + namespace el {\ + namespace base {\ + el::base::type::StoragePointer elStorage(val);\ + }\ + el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ + } + +#if ELPP_ASYNC_LOGGING +# define INITIALIZE_EASYLOGGINGPP\ + ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()),\ + new el::base::AsyncDispatchWorker()))\ + +#else +# define INITIALIZE_EASYLOGGINGPP\ + ELPP_INIT_EASYLOGGINGPP(new el::base::Storage(el::LogBuilderPtr(new el::base::DefaultLogBuilder()))) +#endif // ELPP_ASYNC_LOGGING +#define INITIALIZE_NULL_EASYLOGGINGPP\ + ELPP_INITI_BASIC_DECLR\ + namespace el {\ + namespace base {\ + el::base::type::StoragePointer elStorage;\ + }\ + el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ + } + // NOTE: no ELPP_INITI_BASIC_DECLR when sharing - causes double free corruption on external symbols +#define SHARE_EASYLOGGINGPP(initializedStorage)\ + namespace el {\ + namespace base {\ + el::base::type::StoragePointer elStorage(initializedStorage);\ + }\ + el::base::debug::CrashHandler elCrashHandler(ELPP_USE_DEF_CRASH_HANDLER);\ + } + +#if defined(ELPP_UNICODE) +# define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv); std::locale::global(std::locale("")) +#else +# define START_EASYLOGGINGPP(argc, argv) el::Helpers::setArgs(argc, argv) +#endif // defined(ELPP_UNICODE) +#endif // EASYLOGGINGPP_H \ No newline at end of file diff --git a/extensions/common/glm/CMakeLists.txt b/extensions/common/glm/CMakeLists.txt new file mode 100644 index 0000000000..fe28b5d975 --- /dev/null +++ b/extensions/common/glm/CMakeLists.txt @@ -0,0 +1,43 @@ +set(NAME glm_dummy) + +file(GLOB ROOT_SOURCE *.cpp) +file(GLOB ROOT_INLINE *.inl) +file(GLOB ROOT_HEADER *.hpp) +file(GLOB ROOT_TEXT ../*.txt) +file(GLOB ROOT_NAT ../util/glm.natvis) + +file(GLOB_RECURSE CORE_SOURCE ./detail/*.cpp) +file(GLOB_RECURSE CORE_INLINE ./detail/*.inl) +file(GLOB_RECURSE CORE_HEADER ./detail/*.hpp) + +file(GLOB_RECURSE GTC_SOURCE ./gtc/*.cpp) +file(GLOB_RECURSE GTC_INLINE ./gtc/*.inl) +file(GLOB_RECURSE GTC_HEADER ./gtc/*.hpp) + +file(GLOB_RECURSE GTX_SOURCE ./gtx/*.cpp) +file(GLOB_RECURSE GTX_INLINE ./gtx/*.inl) +file(GLOB_RECURSE GTX_HEADER ./gtx/*.hpp) + +source_group("Text Files" FILES ${ROOT_TEXT}) +source_group("Core Files" FILES ${CORE_SOURCE}) +source_group("Core Files" FILES ${CORE_INLINE}) +source_group("Core Files" FILES ${CORE_HEADER}) +source_group("GTC Files" FILES ${GTC_SOURCE}) +source_group("GTC Files" FILES ${GTC_INLINE}) +source_group("GTC Files" FILES ${GTC_HEADER}) +source_group("GTX Files" FILES ${GTX_SOURCE}) +source_group("GTX Files" FILES ${GTX_INLINE}) +source_group("GTX Files" FILES ${GTX_HEADER}) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/..) + +if(GLM_TEST_ENABLE) + add_executable(${NAME} ${ROOT_TEXT} ${ROOT_NAT} + ${ROOT_SOURCE} ${ROOT_INLINE} ${ROOT_HEADER} + ${CORE_SOURCE} ${CORE_INLINE} ${CORE_HEADER} + ${GTC_SOURCE} ${GTC_INLINE} ${GTC_HEADER} + ${GTX_SOURCE} ${GTX_INLINE} ${GTX_HEADER}) +endif(GLM_TEST_ENABLE) + +#add_library(glm STATIC glm.cpp) +#add_library(glm_shared SHARED glm.cpp) diff --git a/extensions/common/glm/common.hpp b/extensions/common/glm/common.hpp new file mode 100644 index 0000000000..57beb106a9 --- /dev/null +++ b/extensions/common/glm/common.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/common.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/func_common.hpp" diff --git a/extensions/common/glm/detail/_features.hpp b/extensions/common/glm/detail/_features.hpp new file mode 100644 index 0000000000..ce2a35d9c1 --- /dev/null +++ b/extensions/common/glm/detail/_features.hpp @@ -0,0 +1,428 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_features.hpp +/// @date 2013-02-20 / 2013-02-20 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// #define GLM_CXX98_EXCEPTIONS +// #define GLM_CXX98_RTTI + +// #define GLM_CXX11_RVALUE_REFERENCES +// Rvalue references - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2118.html + +// GLM_CXX11_TRAILING_RETURN +// Rvalue references for *this - GCC not supported +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2439.htm + +// GLM_CXX11_NONSTATIC_MEMBER_INIT +// Initialization of class objects by rvalues - GCC any +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1610.html + +// GLM_CXX11_NONSTATIC_MEMBER_INIT +// Non-static data member initializers - GCC 4.7 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2756.htm + +// #define GLM_CXX11_VARIADIC_TEMPLATE +// Variadic templates - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf + +// +// Extending variadic template template parameters - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf + +// #define GLM_CXX11_GENERALIZED_INITIALIZERS +// Initializer lists - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2672.htm + +// #define GLM_CXX11_STATIC_ASSERT +// Static assertions - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1720.html + +// #define GLM_CXX11_AUTO_TYPE +// auto-typed variables - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf + +// #define GLM_CXX11_AUTO_TYPE +// Multi-declarator auto - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1737.pdf + +// #define GLM_CXX11_AUTO_TYPE +// Removal of auto as a storage-class specifier - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2546.htm + +// #define GLM_CXX11_AUTO_TYPE +// New function declarator syntax - GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2541.htm + +// #define GLM_CXX11_LAMBDAS +// New wording for C++0x lambdas - GCC 4.5 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2927.pdf + +// #define GLM_CXX11_DECLTYPE +// Declared type of an expression - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2343.pdf + +// +// Right angle brackets - GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1757.html + +// +// Default template arguments for function templates DR226 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#226 + +// +// Solving the SFINAE problem for expressions DR339 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html + +// #define GLM_CXX11_ALIAS_TEMPLATE +// Template aliases N2258 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf + +// +// Extern templates N1987 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm + +// #define GLM_CXX11_NULLPTR +// Null pointer constant N2431 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2431.pdf + +// #define GLM_CXX11_STRONG_ENUMS +// Strongly-typed enums N2347 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2347.pdf + +// +// Forward declarations for enums N2764 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf + +// +// Generalized attributes N2761 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2761.pdf + +// +// Generalized constant expressions N2235 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf + +// +// Alignment support N2341 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf + +// #define GLM_CXX11_DELEGATING_CONSTRUCTORS +// Delegating constructors N1986 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf + +// +// Inheriting constructors N2540 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm + +// #define GLM_CXX11_EXPLICIT_CONVERSIONS +// Explicit conversion operators N2437 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf + +// +// New character types N2249 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2249.html + +// +// Unicode string literals N2442 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm + +// +// Raw string literals N2442 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm + +// +// Universal character name literals N2170 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2170.html + +// #define GLM_CXX11_USER_LITERALS +// User-defined literals N2765 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2765.pdf + +// +// Standard Layout Types N2342 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm + +// #define GLM_CXX11_DEFAULTED_FUNCTIONS +// #define GLM_CXX11_DELETED_FUNCTIONS +// Defaulted and deleted functions N2346 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2346.htm + +// +// Extended friend declarations N1791 GCC 4.7 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf + +// +// Extending sizeof N2253 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html + +// #define GLM_CXX11_INLINE_NAMESPACES +// Inline namespaces N2535 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm + +// #define GLM_CXX11_UNRESTRICTED_UNIONS +// Unrestricted unions N2544 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf + +// #define GLM_CXX11_LOCAL_TYPE_TEMPLATE_ARGS +// Local and unnamed types as template arguments N2657 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm + +// #define GLM_CXX11_RANGE_FOR +// Range-based for N2930 GCC 4.6 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2930.html + +// #define GLM_CXX11_OVERRIDE_CONTROL +// Explicit virtual overrides N2928 N3206 N3272 GCC 4.7 +// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2009/n2928.htm +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3206.htm +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3272.htm + +// +// Minimal support for garbage collection and reachability-based leak detection N2670 No +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2670.htm + +// #define GLM_CXX11_NOEXCEPT +// Allowing move constructors to throw [noexcept] N3050 GCC 4.6 (core language only) +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3050.html + +// +// Defining move special member functions N3053 GCC 4.6 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3053.html + +// +// Sequence points N2239 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2239.html + +// +// Atomic operations N2427 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2239.html + +// +// Strong Compare and Exchange N2748 GCC 4.5 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html + +// +// Bidirectional Fences N2752 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2752.htm + +// +// Memory model N2429 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2429.htm + +// +// Data-dependency ordering: atomics and memory model N2664 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2664.htm + +// +// Propagating exceptions N2179 GCC 4.4 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html + +// +// Abandoning a process and at_quick_exit N2440 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2440.htm + +// +// Allow atomics use in signal handlers N2547 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2547.htm + +// +// Thread-local storage N2659 GCC 4.8 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2659.htm + +// +// Dynamic initialization and destruction with concurrency N2660 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2660.htm + +// +// __func__ predefined identifier N2340 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2340.htm + +// +// C99 preprocessor N1653 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1653.htm + +// +// long long N1811 GCC 4.3 +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1811.pdf + +// +// Extended integral types N1988 Yes +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1988.pdf + +#if(GLM_COMPILER & GLM_COMPILER_GCC) + +# if(GLM_COMPILER >= GLM_COMPILER_GCC43) +# define GLM_CXX11_STATIC_ASSERT +# endif + +#elif(GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) +# if(__has_feature(cxx_exceptions)) +# define GLM_CXX98_EXCEPTIONS +# endif + +# if(__has_feature(cxx_rtti)) +# define GLM_CXX98_RTTI +# endif + +# if(__has_feature(cxx_access_control_sfinae)) +# define GLM_CXX11_ACCESS_CONTROL_SFINAE +# endif + +# if(__has_feature(cxx_alias_templates)) +# define GLM_CXX11_ALIAS_TEMPLATE +# endif + +# if(__has_feature(cxx_alignas)) +# define GLM_CXX11_ALIGNAS +# endif + +# if(__has_feature(cxx_attributes)) +# define GLM_CXX11_ATTRIBUTES +# endif + +# if(__has_feature(cxx_constexpr)) +# define GLM_CXX11_CONSTEXPR +# endif + +# if(__has_feature(cxx_decltype)) +# define GLM_CXX11_DECLTYPE +# endif + +# if(__has_feature(cxx_default_function_template_args)) +# define GLM_CXX11_DEFAULT_FUNCTION_TEMPLATE_ARGS +# endif + +# if(__has_feature(cxx_defaulted_functions)) +# define GLM_CXX11_DEFAULTED_FUNCTIONS +# endif + +# if(__has_feature(cxx_delegating_constructors)) +# define GLM_CXX11_DELEGATING_CONSTRUCTORS +# endif + +# if(__has_feature(cxx_deleted_functions)) +# define GLM_CXX11_DELETED_FUNCTIONS +# endif + +# if(__has_feature(cxx_explicit_conversions)) +# define GLM_CXX11_EXPLICIT_CONVERSIONS +# endif + +# if(__has_feature(cxx_generalized_initializers)) +# define GLM_CXX11_GENERALIZED_INITIALIZERS +# endif + +# if(__has_feature(cxx_implicit_moves)) +# define GLM_CXX11_IMPLICIT_MOVES +# endif + +# if(__has_feature(cxx_inheriting_constructors)) +# define GLM_CXX11_INHERITING_CONSTRUCTORS +# endif + +# if(__has_feature(cxx_inline_namespaces)) +# define GLM_CXX11_INLINE_NAMESPACES +# endif + +# if(__has_feature(cxx_lambdas)) +# define GLM_CXX11_LAMBDAS +# endif + +# if(__has_feature(cxx_local_type_template_args)) +# define GLM_CXX11_LOCAL_TYPE_TEMPLATE_ARGS +# endif + +# if(__has_feature(cxx_noexcept)) +# define GLM_CXX11_NOEXCEPT +# endif + +# if(__has_feature(cxx_nonstatic_member_init)) +# define GLM_CXX11_NONSTATIC_MEMBER_INIT +# endif + +# if(__has_feature(cxx_nullptr)) +# define GLM_CXX11_NULLPTR +# endif + +# if(__has_feature(cxx_override_control)) +# define GLM_CXX11_OVERRIDE_CONTROL +# endif + +# if(__has_feature(cxx_reference_qualified_functions)) +# define GLM_CXX11_REFERENCE_QUALIFIED_FUNCTIONS +# endif + +# if(__has_feature(cxx_range_for)) +# define GLM_CXX11_RANGE_FOR +# endif + +# if(__has_feature(cxx_raw_string_literals)) +# define GLM_CXX11_RAW_STRING_LITERALS +# endif + +# if(__has_feature(cxx_rvalue_references)) +# define GLM_CXX11_RVALUE_REFERENCES +# endif + +# if(__has_feature(cxx_static_assert)) +# define GLM_CXX11_STATIC_ASSERT +# endif + +# if(__has_feature(cxx_auto_type)) +# define GLM_CXX11_AUTO_TYPE +# endif + +# if(__has_feature(cxx_strong_enums)) +# define GLM_CXX11_STRONG_ENUMS +# endif + +# if(__has_feature(cxx_trailing_return)) +# define GLM_CXX11_TRAILING_RETURN +# endif + +# if(__has_feature(cxx_unicode_literals)) +# define GLM_CXX11_UNICODE_LITERALS +# endif + +# if(__has_feature(cxx_unrestricted_unions)) +# define GLM_CXX11_UNRESTRICTED_UNIONS +# endif + +# if(__has_feature(cxx_user_literals)) +# define GLM_CXX11_USER_LITERALS +# endif + +# if(__has_feature(cxx_variadic_templates)) +# define GLM_CXX11_VARIADIC_TEMPLATES +# endif + +#endif//(GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) diff --git a/extensions/common/glm/detail/_fixes.hpp b/extensions/common/glm/detail/_fixes.hpp new file mode 100644 index 0000000000..9728cafb73 --- /dev/null +++ b/extensions/common/glm/detail/_fixes.hpp @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_fixes.hpp +/// @date 2011-02-21 / 2011-11-22 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include <cmath> + +//! Workaround for compatibility with other libraries +#ifdef max +#undef max +#endif + +//! Workaround for compatibility with other libraries +#ifdef min +#undef min +#endif + +//! Workaround for Android +#ifdef isnan +#undef isnan +#endif + +//! Workaround for Android +#ifdef isinf +#undef isinf +#endif + +//! Workaround for Chrone Native Client +#ifdef log2 +#undef log2 +#endif + diff --git a/extensions/common/glm/detail/_noise.hpp b/extensions/common/glm/detail/_noise.hpp new file mode 100644 index 0000000000..296709d4b9 --- /dev/null +++ b/extensions/common/glm/detail/_noise.hpp @@ -0,0 +1,136 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_noise.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../common.hpp" + +namespace glm{ +namespace detail +{ + template <typename T> + GLM_FUNC_QUALIFIER T mod289(T const & x) + { + return x - floor(x * static_cast<T>(1.0) / static_cast<T>(289.0)) * static_cast<T>(289.0); + } + + template <typename T> + GLM_FUNC_QUALIFIER T permute(T const & x) + { + return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> permute(tvec2<T, P> const & x) + { + return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> permute(tvec3<T, P> const & x) + { + return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> permute(tvec4<T, P> const & x) + { + return mod289(((x * static_cast<T>(34)) + static_cast<T>(1)) * x); + } +/* + template <typename T, precision P, template<typename> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> permute(vecType<T, P> const & x) + { + return mod289(((x * T(34)) + T(1)) * x); + } +*/ + template <typename T> + GLM_FUNC_QUALIFIER T taylorInvSqrt(T const & r) + { + return T(1.79284291400159) - T(0.85373472095314) * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> taylorInvSqrt(tvec2<T, P> const & r) + { + return T(1.79284291400159) - T(0.85373472095314) * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> taylorInvSqrt(tvec3<T, P> const & r) + { + return T(1.79284291400159) - T(0.85373472095314) * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> taylorInvSqrt(tvec4<T, P> const & r) + { + return T(1.79284291400159) - T(0.85373472095314) * r; + } +/* + template <typename T, precision P, template<typename> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> taylorInvSqrt(vecType<T, P> const & r) + { + return T(1.79284291400159) - T(0.85373472095314) * r; + } +*/ + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> fade(tvec2<T, P> const & t) + { + return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> fade(tvec3<T, P> const & t) + { + return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> fade(tvec4<T, P> const & t) + { + return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); + } +/* + template <typename T, precision P, template <typename> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fade(vecType<T, P> const & t) + { + return (t * t * t) * (t * (t * T(6) - T(15)) + T(10)); + } +*/ +}//namespace detail +}//namespace glm + diff --git a/extensions/common/glm/detail/_swizzle.hpp b/extensions/common/glm/detail/_swizzle.hpp new file mode 100644 index 0000000000..04ea55bcf2 --- /dev/null +++ b/extensions/common/glm/detail/_swizzle.hpp @@ -0,0 +1,833 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_swizzle.hpp +/// @date 2006-04-20 / 2011-02-16 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +namespace glm{ +namespace detail +{ + // Internal class for implementing swizzle operators + template <typename T, int N> + struct _swizzle_base0 + { + typedef T value_type; + + protected: + GLM_FUNC_QUALIFIER value_type& elem (size_t i) { return (reinterpret_cast<value_type*>(_buffer))[i]; } + GLM_FUNC_QUALIFIER const value_type& elem (size_t i) const { return (reinterpret_cast<const value_type*>(_buffer))[i]; } + + // Use an opaque buffer to *ensure* the compiler doesn't call a constructor. + // The size 1 buffer is assumed to aligned to the actual members so that the + // elem() + char _buffer[1]; + }; + + template <typename T, precision P, typename V, int E0, int E1, int E2, int E3, int N> + struct _swizzle_base1 : public _swizzle_base0<T, N> + { + }; + + template <typename T, precision P, typename V, int E0, int E1> + struct _swizzle_base1<T, P, V,E0,E1,-1,-2,2> : public _swizzle_base0<T, 2> + { + GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1)); } + }; + + template <typename T, precision P, typename V, int E0, int E1, int E2> + struct _swizzle_base1<T, P, V,E0,E1,E2,-1,3> : public _swizzle_base0<T, 3> + { + GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1), this->elem(E2)); } + }; + + template <typename T, precision P, typename V, int E0, int E1, int E2, int E3> + struct _swizzle_base1<T, P, V,E0,E1,E2,E3,4> : public _swizzle_base0<T, 4> + { + GLM_FUNC_QUALIFIER V operator ()() const { return V(this->elem(E0), this->elem(E1), this->elem(E2), this->elem(E3)); } + }; + + // Internal class for implementing swizzle operators + /* + Template parameters: + + ValueType = type of scalar values (e.g. float, double) + VecType = class the swizzle is applies to (e.g. tvec3<float>) + N = number of components in the vector (e.g. 3) + E0...3 = what index the n-th element of this swizzle refers to in the unswizzled vec + + DUPLICATE_ELEMENTS = 1 if there is a repeated element, 0 otherwise (used to specialize swizzles + containing duplicate elements so that they cannot be used as r-values). + */ + template <typename ValueType, precision P, typename VecType, int N, int E0, int E1, int E2, int E3, int DUPLICATE_ELEMENTS> + struct _swizzle_base2 : public _swizzle_base1<ValueType, P, VecType,E0,E1,E2,E3,N> + { + typedef VecType vec_type; + typedef ValueType value_type; + + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const ValueType& t) + { + for (int i = 0; i < N; ++i) + (*this)[i] = t; + return *this; + } + + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (const VecType& that) + { + struct op { + GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e = t; } + }; + _apply_op(that, op()); + return *this; + } + + GLM_FUNC_QUALIFIER void operator -= (const VecType& that) + { + struct op { + GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e -= t; } + }; + _apply_op(that, op()); + } + + GLM_FUNC_QUALIFIER void operator += (const VecType& that) + { + struct op { + GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e += t; } + }; + _apply_op(that, op()); + } + + GLM_FUNC_QUALIFIER void operator *= (const VecType& that) + { + struct op { + GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e *= t; } + }; + _apply_op(that, op()); + } + + GLM_FUNC_QUALIFIER void operator /= (const VecType& that) + { + struct op { + GLM_FUNC_QUALIFIER void operator() (value_type& e, value_type& t) { e /= t; } + }; + _apply_op(that, op()); + } + + GLM_FUNC_QUALIFIER value_type& operator[] (size_t i) + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + GLM_FUNC_QUALIFIER value_type operator[] (size_t i) const + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + + protected: + template <typename T> + GLM_FUNC_QUALIFIER void _apply_op(const VecType& that, T op) + { + // Make a copy of the data in this == &that. + // The copier should optimize out the copy in cases where the function is + // properly inlined and the copy is not necessary. + ValueType t[N]; + for (int i = 0; i < N; ++i) + t[i] = that[i]; + for (int i = 0; i < N; ++i) + op( (*this)[i], t[i] ); + } + }; + + // Specialization for swizzles containing duplicate elements. These cannot be modified. + template <typename ValueType, precision P, typename VecType, int N, int E0, int E1, int E2, int E3> + struct _swizzle_base2<ValueType, P, VecType,N,E0,E1,E2,E3,1> : public _swizzle_base1<ValueType, P, VecType,E0,E1,E2,E3,N> + { + typedef VecType vec_type; + typedef ValueType value_type; + + struct Stub {}; + GLM_FUNC_QUALIFIER _swizzle_base2& operator= (Stub const &) { return *this; } + + GLM_FUNC_QUALIFIER value_type operator[] (size_t i) const + { + const int offset_dst[4] = { E0, E1, E2, E3 }; + return this->elem(offset_dst[i]); + } + }; + + template <int N,typename ValueType, precision P, typename VecType, int E0,int E1,int E2,int E3> + struct _swizzle : public _swizzle_base2<ValueType, P, VecType, N, E0, E1, E2, E3, (E0==E1||E0==E2||E0==E3||E1==E2||E1==E3||E2==E3)> + { + typedef _swizzle_base2<ValueType, P, VecType,N,E0,E1,E2,E3,(E0==E1||E0==E2||E0==E3||E1==E2||E1==E3||E2==E3)> base_type; + + using base_type::operator=; + + GLM_FUNC_QUALIFIER operator VecType () const { return (*this)(); } + }; + +// +// To prevent the C++ syntax from getting entirely overwhelming, define some alias macros +// +#define _GLM_SWIZZLE_TEMPLATE1 template <int N, typename T, precision P, typename V, int E0, int E1, int E2, int E3> +#define _GLM_SWIZZLE_TEMPLATE2 template <int N, typename T, precision P, typename V, int E0, int E1, int E2, int E3, int F0, int F1, int F2, int F3> +#define _GLM_SWIZZLE_TYPE1 _swizzle<N, T, P, V, E0, E1, E2, E3> +#define _GLM_SWIZZLE_TYPE2 _swizzle<N, T, P, V, F0, F1, F2, F3> + +// +// Wrapper for a binary operator (e.g. u.yy + v.zy) +// +#define _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ + _GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b) \ + { \ + return a() OPERAND b(); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const V& b) \ + { \ + return a() OPERAND b; \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER V operator OPERAND ( const V& a, const _GLM_SWIZZLE_TYPE1& b) \ + { \ + return a OPERAND b(); \ + } + +// +// Wrapper for a operand between a swizzle and a binary (e.g. 1.0f - u.xyz) +// +#define _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(OPERAND) \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER V operator OPERAND ( const _GLM_SWIZZLE_TYPE1& a, const T& b) \ + { \ + return a() OPERAND b; \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER V operator OPERAND ( const T& a, const _GLM_SWIZZLE_TYPE1& b) \ + { \ + return a OPERAND b(); \ + } + +// +// Macro for wrapping a function taking one argument (e.g. abs()) +// +#define _GLM_SWIZZLE_FUNCTION_1_ARGS(RETURN_TYPE,FUNCTION) \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a) \ + { \ + return FUNCTION(a()); \ + } + +// +// Macro for wrapping a function taking two vector arguments (e.g. dot()). +// +#define _GLM_SWIZZLE_FUNCTION_2_ARGS(RETURN_TYPE,FUNCTION) \ + _GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b) \ + { \ + return FUNCTION(a(), b()); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE1& b) \ + { \ + return FUNCTION(a(), b()); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const typename V& b) \ + { \ + return FUNCTION(a(), b); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const V& a, const _GLM_SWIZZLE_TYPE1& b) \ + { \ + return FUNCTION(a, b()); \ + } + +// +// Macro for wrapping a function take 2 vec arguments followed by a scalar (e.g. mix()). +// +#define _GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(RETURN_TYPE,FUNCTION) \ + _GLM_SWIZZLE_TEMPLATE2 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE2& b, const T& c) \ + { \ + return FUNCTION(a(), b(), c); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const _GLM_SWIZZLE_TYPE1& b, const T& c) \ + { \ + return FUNCTION(a(), b(), c); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const _GLM_SWIZZLE_TYPE1& a, const typename S0::vec_type& b, const T& c)\ + { \ + return FUNCTION(a(), b, c); \ + } \ + _GLM_SWIZZLE_TEMPLATE1 \ + GLM_FUNC_QUALIFIER typename _GLM_SWIZZLE_TYPE1::RETURN_TYPE FUNCTION(const typename V& a, const _GLM_SWIZZLE_TYPE1& b, const T& c) \ + { \ + return FUNCTION(a, b(), c); \ + } + +}//namespace detail +}//namespace glm + +namespace glm +{ + namespace detail + { + _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(-) + _GLM_SWIZZLE_SCALAR_BINARY_OPERATOR_IMPLEMENTATION(*) + _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(+) + _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(-) + _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(*) + _GLM_SWIZZLE_VECTOR_BINARY_OPERATOR_IMPLEMENTATION(/) + } + + // + // Swizzles are distinct types from the unswizzled type. The below macros will + // provide template specializations for the swizzle types for the given functions + // so that the compiler does not have any ambiguity to choosing how to handle + // the function. + // + // The alternative is to use the operator()() when calling the function in order + // to explicitly convert the swizzled type to the unswizzled type. + // + + //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, abs); + //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acos); + //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, acosh); + //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, all); + //_GLM_SWIZZLE_FUNCTION_1_ARGS(vec_type, any); + + //_GLM_SWIZZLE_FUNCTION_2_ARGS(value_type, dot); + //_GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, cross); + //_GLM_SWIZZLE_FUNCTION_2_ARGS(vec_type, step); + //_GLM_SWIZZLE_FUNCTION_2_ARGS_SCALAR(vec_type, mix); +} + +#define _GLM_SWIZZLE2_2_MEMBERS(T, P, V, E0,E1) \ + struct { detail::_swizzle<2, T, P, V<T, P>, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2, T, P, V<T, P>, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2, T, P, V<T, P>, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2, T, P, V<T, P>, 1,1,-1,-2> E1 ## E1; }; + +#define _GLM_SWIZZLE2_3_MEMBERS(T, P, V, E0,E1) \ + struct { detail::_swizzle<3,T, P, V<T, P>, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V<T, P>, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V<T, P>, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V<T, P>, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V<T, P>, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V<T, P>, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T, P, V<T, P>, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T, P, V<T, P>, 1,1,1,-1> E1 ## E1 ## E1; }; + +#define _GLM_SWIZZLE2_4_MEMBERS(T, P, V, E0,E1) \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; + +#define _GLM_SWIZZLE3_2_MEMBERS(T, P, V, E0,E1,E2) \ + struct { detail::_swizzle<2,T, P, V<T, P>, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 2,2,-1,-2> E2 ## E2; }; + +#define _GLM_SWIZZLE3_3_MEMBERS(T, P, V ,E0,E1,E2) \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,2,2,-1> E2 ## E2 ## E2; }; + +#define _GLM_SWIZZLE3_4_MEMBERS(T, P, V, E0,E1,E2) \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4,T, P, V<T, P>, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; + +#define _GLM_SWIZZLE4_2_MEMBERS(T, P, V, E0,E1,E2,E3) \ + struct { detail::_swizzle<2,T, P, V<T, P>, 0,0,-1,-2> E0 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 0,1,-1,-2> E0 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 0,2,-1,-2> E0 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 0,3,-1,-2> E0 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 1,0,-1,-2> E1 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 1,1,-1,-2> E1 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 1,2,-1,-2> E1 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 1,3,-1,-2> E1 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 2,0,-1,-2> E2 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 2,1,-1,-2> E2 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 2,2,-1,-2> E2 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 2,3,-1,-2> E2 ## E3; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 3,0,-1,-2> E3 ## E0; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 3,1,-1,-2> E3 ## E1; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 3,2,-1,-2> E3 ## E2; }; \ + struct { detail::_swizzle<2,T, P, V<T, P>, 3,3,-1,-2> E3 ## E3; }; + +#define _GLM_SWIZZLE4_3_MEMBERS(T,P, V, E0,E1,E2,E3) \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,0,0,-1> E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,0,1,-1> E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,0,2,-1> E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,0,3,-1> E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,1,0,-1> E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,1,1,-1> E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,1,2,-1> E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,1,3,-1> E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,2,0,-1> E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,2,1,-1> E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,2,2,-1> E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,2,3,-1> E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,3,0,-1> E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,3,1,-1> E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,3,2,-1> E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 0,3,3,-1> E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,0,0,-1> E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,0,1,-1> E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,0,2,-1> E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,0,3,-1> E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,1,0,-1> E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,1,1,-1> E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,1,2,-1> E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,1,3,-1> E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,2,0,-1> E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,2,1,-1> E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,2,2,-1> E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,2,3,-1> E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,3,0,-1> E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,3,1,-1> E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,3,2,-1> E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 1,3,3,-1> E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,0,0,-1> E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,0,1,-1> E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,0,2,-1> E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,0,3,-1> E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,1,0,-1> E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,1,1,-1> E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,1,2,-1> E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,1,3,-1> E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,2,0,-1> E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,2,1,-1> E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,2,2,-1> E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,2,3,-1> E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,3,0,-1> E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,3,1,-1> E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,3,2,-1> E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 2,3,3,-1> E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,0,0,-1> E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,0,1,-1> E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,0,2,-1> E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,0,3,-1> E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,1,0,-1> E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,1,1,-1> E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,1,2,-1> E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,1,3,-1> E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,2,0,-1> E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,2,1,-1> E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,2,2,-1> E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,2,3,-1> E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,3,0,-1> E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,3,1,-1> E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,3,2,-1> E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<3,T,P, V<T, P>, 3,3,3,-1> E3 ## E3 ## E3; }; + +#define _GLM_SWIZZLE4_4_MEMBERS(T, P, V, E0,E1,E2,E3) \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,0,0> E0 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,0,1> E0 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,0,2> E0 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,0,3> E0 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,1,0> E0 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,1,1> E0 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,1,2> E0 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,1,3> E0 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,2,0> E0 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,2,1> E0 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,2,2> E0 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,2,3> E0 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,3,0> E0 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,3,1> E0 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,3,2> E0 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,0,3,3> E0 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,0,0> E0 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,0,1> E0 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,0,2> E0 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,0,3> E0 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,1,0> E0 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,1,1> E0 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,1,2> E0 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,1,3> E0 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,2,0> E0 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,2,1> E0 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,2,2> E0 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,2,3> E0 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,3,0> E0 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,3,1> E0 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,3,2> E0 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,1,3,3> E0 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,0,0> E0 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,0,1> E0 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,0,2> E0 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,0,3> E0 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,1,0> E0 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,1,1> E0 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,1,2> E0 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,1,3> E0 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,2,0> E0 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,2,1> E0 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,2,2> E0 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,2,3> E0 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,3,0> E0 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,3,1> E0 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,3,2> E0 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,2,3,3> E0 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,0,0> E0 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,0,1> E0 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,0,2> E0 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,0,3> E0 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,1,0> E0 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,1,1> E0 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,1,2> E0 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,1,3> E0 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,2,0> E0 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,2,1> E0 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,2,2> E0 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,2,3> E0 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,3,0> E0 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,3,1> E0 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,3,2> E0 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 0,3,3,3> E0 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,0,0> E1 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,0,1> E1 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,0,2> E1 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,0,3> E1 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,1,0> E1 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,1,1> E1 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,1,2> E1 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,1,3> E1 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,2,0> E1 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,2,1> E1 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,2,2> E1 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,2,3> E1 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,3,0> E1 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,3,1> E1 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,3,2> E1 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,0,3,3> E1 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,0,0> E1 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,0,1> E1 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,0,2> E1 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,0,3> E1 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,1,0> E1 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,1,1> E1 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,1,2> E1 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,1,3> E1 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,2,0> E1 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,2,1> E1 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,2,2> E1 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,2,3> E1 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,3,0> E1 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,3,1> E1 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,3,2> E1 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,1,3,3> E1 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,0,0> E1 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,0,1> E1 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,0,2> E1 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,0,3> E1 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,1,0> E1 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,1,1> E1 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,1,2> E1 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,1,3> E1 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,2,0> E1 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,2,1> E1 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,2,2> E1 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,2,3> E1 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,3,0> E1 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,3,1> E1 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,3,2> E1 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,2,3,3> E1 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,0,0> E1 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,0,1> E1 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,0,2> E1 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,0,3> E1 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,1,0> E1 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,1,1> E1 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,1,2> E1 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,1,3> E1 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,2,0> E1 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,2,1> E1 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,2,2> E1 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,2,3> E1 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,3,0> E1 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,3,1> E1 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,3,2> E1 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 1,3,3,3> E1 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,0,0> E2 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,0,1> E2 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,0,2> E2 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,0,3> E2 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,1,0> E2 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,1,1> E2 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,1,2> E2 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,1,3> E2 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,2,0> E2 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,2,1> E2 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,2,2> E2 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,2,3> E2 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,3,0> E2 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,3,1> E2 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,3,2> E2 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,0,3,3> E2 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,0,0> E2 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,0,1> E2 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,0,2> E2 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,0,3> E2 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,1,0> E2 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,1,1> E2 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,1,2> E2 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,1,3> E2 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,2,0> E2 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,2,1> E2 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,2,2> E2 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,2,3> E2 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,3,0> E2 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,3,1> E2 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,3,2> E2 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,1,3,3> E2 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,0,0> E2 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,0,1> E2 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,0,2> E2 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,0,3> E2 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,1,0> E2 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,1,1> E2 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,1,2> E2 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,1,3> E2 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,2,0> E2 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,2,1> E2 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,2,2> E2 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,2,3> E2 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,3,0> E2 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,3,1> E2 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,3,2> E2 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,2,3,3> E2 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,0,0> E2 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,0,1> E2 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,0,2> E2 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,0,3> E2 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,1,0> E2 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,1,1> E2 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,1,2> E2 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,1,3> E2 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,2,0> E2 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,2,1> E2 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,2,2> E2 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,2,3> E2 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,3,0> E2 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,3,1> E2 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,3,2> E2 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 2,3,3,3> E2 ## E3 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,0,0> E3 ## E0 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,0,1> E3 ## E0 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,0,2> E3 ## E0 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,0,3> E3 ## E0 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,1,0> E3 ## E0 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,1,1> E3 ## E0 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,1,2> E3 ## E0 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,1,3> E3 ## E0 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,2,0> E3 ## E0 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,2,1> E3 ## E0 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,2,2> E3 ## E0 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,2,3> E3 ## E0 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,3,0> E3 ## E0 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,3,1> E3 ## E0 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,3,2> E3 ## E0 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,0,3,3> E3 ## E0 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,0,0> E3 ## E1 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,0,1> E3 ## E1 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,0,2> E3 ## E1 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,0,3> E3 ## E1 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,1,0> E3 ## E1 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,1,1> E3 ## E1 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,1,2> E3 ## E1 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,1,3> E3 ## E1 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,2,0> E3 ## E1 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,2,1> E3 ## E1 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,2,2> E3 ## E1 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,2,3> E3 ## E1 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,3,0> E3 ## E1 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,3,1> E3 ## E1 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,3,2> E3 ## E1 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,1,3,3> E3 ## E1 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,0,0> E3 ## E2 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,0,1> E3 ## E2 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,0,2> E3 ## E2 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,0,3> E3 ## E2 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,1,0> E3 ## E2 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,1,1> E3 ## E2 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,1,2> E3 ## E2 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,1,3> E3 ## E2 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,2,0> E3 ## E2 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,2,1> E3 ## E2 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,2,2> E3 ## E2 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,2,3> E3 ## E2 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,3,0> E3 ## E2 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,3,1> E3 ## E2 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,3,2> E3 ## E2 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,2,3,3> E3 ## E2 ## E3 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,0,0> E3 ## E3 ## E0 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,0,1> E3 ## E3 ## E0 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,0,2> E3 ## E3 ## E0 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,0,3> E3 ## E3 ## E0 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,1,0> E3 ## E3 ## E1 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,1,1> E3 ## E3 ## E1 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,1,2> E3 ## E3 ## E1 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,1,3> E3 ## E3 ## E1 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,2,0> E3 ## E3 ## E2 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,2,1> E3 ## E3 ## E2 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,2,2> E3 ## E3 ## E2 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,2,3> E3 ## E3 ## E2 ## E3; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,3,0> E3 ## E3 ## E3 ## E0; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,3,1> E3 ## E3 ## E3 ## E1; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,3,2> E3 ## E3 ## E3 ## E2; }; \ + struct { detail::_swizzle<4, T, P, V<T, P>, 3,3,3,3> E3 ## E3 ## E3 ## E3; }; diff --git a/extensions/common/glm/detail/_swizzle_func.hpp b/extensions/common/glm/detail/_swizzle_func.hpp new file mode 100644 index 0000000000..4dbb783c5b --- /dev/null +++ b/extensions/common/glm/detail/_swizzle_func.hpp @@ -0,0 +1,725 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_swizzle_func.hpp +/// @date 2011-10-16 / 2011-10-16 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#define GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B) \ + SWIZZLED_TYPE<TMPL_TYPE, PRECISION> A ## B() CONST \ + { \ + return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B); \ + } + +#define GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C) \ + SWIZZLED_TYPE<TMPL_TYPE, PRECISION> A ## B ## C() CONST \ + { \ + return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B, this->C); \ + } + +#define GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C, D) \ + SWIZZLED_TYPE<TMPL_TYPE, PRECISION> A ## B ## C ## D() CONST \ + { \ + return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B, this->C, this->D); \ + } + +#define GLM_SWIZZLE_GEN_VEC2_ENTRY_DEF(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B) \ + template <typename TMPL_TYPE> \ + SWIZZLED_TYPE<TMPL_TYPE> CLASS_TYPE<TMPL_TYPE, PRECISION>::A ## B() CONST \ + { \ + return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B); \ + } + +#define GLM_SWIZZLE_GEN_VEC3_ENTRY_DEF(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C) \ + template <typename TMPL_TYPE> \ + SWIZZLED_TYPE<TMPL_TYPE> CLASS_TYPE<TMPL_TYPE, PRECISION>::A ## B ## C() CONST \ + { \ + return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B, this->C); \ + } + +#define GLM_SWIZZLE_GEN_VEC4_ENTRY_DEF(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, CONST, A, B, C, D) \ + template <typename TMPL_TYPE> \ + SWIZZLED_TYPE<TMPL_TYPE> CLASS_TYPE<TMPL_TYPE, PRECISION>::A ## B ## C ## D() CONST \ + { \ + return SWIZZLED_TYPE<TMPL_TYPE, PRECISION>(this->A, this->B, this->C, this->D); \ + } + +#define GLM_MUTABLE + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC2(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, x, y) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, r, g) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, s, t) + +//GLM_SWIZZLE_GEN_REF_FROM_VEC2(valType, detail::vec2, detail::ref2) + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B) + +#define GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_REF3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC3(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, x, y, z) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, r, g, b) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, s, t, p) + +//GLM_SWIZZLE_GEN_REF_FROM_VEC3(valType, detail::vec3, detail::ref2, detail::ref3) + +#define GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, A, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, B, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, GLM_MUTABLE, D, C) + +#define GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, B) + +#define GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , B, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , C, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, , D, B, C, A) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_REF4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) + +#define GLM_SWIZZLE_GEN_REF_FROM_VEC4(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z, w) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b, a) \ + GLM_SWIZZLE_GEN_REF_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, p, q) + +//GLM_SWIZZLE_GEN_REF_FROM_VEC4(valType, detail::vec4, detail::ref2, detail::ref3, detail::ref4) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC2_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC2(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC2_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t) + +//GLM_SWIZZLE_GEN_VEC_FROM_VEC2(valType, detail::vec2, detail::vec2, detail::vec3, detail::vec4) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, C) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC3_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC3(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC3_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, p) + +//GLM_SWIZZLE_GEN_VEC_FROM_VEC3(valType, detail::vec3, detail::vec2, detail::vec3, detail::vec4) + +#define GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C) \ + GLM_SWIZZLE_GEN_VEC2_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D) + +#define GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C) \ + GLM_SWIZZLE_GEN_VEC3_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D) + +#define GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, A, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, B, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, C, D, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, A, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, B, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, C, D, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, A, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, B, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, C, D) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, A) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, B) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, C) \ + GLM_SWIZZLE_GEN_VEC4_ENTRY(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_TYPE, const, D, D, D, D) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC2_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC3_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC3_TYPE, A, B, C, D) \ + GLM_SWIZZLE_GEN_VEC4_FROM_VEC4_SWIZZLE(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC4_TYPE, A, B, C, D) + +#define GLM_SWIZZLE_GEN_VEC_FROM_VEC4(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, x, y, z, w) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, r, g, b, a) \ + GLM_SWIZZLE_GEN_VEC_FROM_VEC4_COMP(TMPL_TYPE, PRECISION, CLASS_TYPE, SWIZZLED_VEC2_TYPE, SWIZZLED_VEC3_TYPE, SWIZZLED_VEC4_TYPE, s, t, p, q) + +//GLM_SWIZZLE_GEN_VEC_FROM_VEC4(valType, detail::vec4, detail::vec2, detail::vec3, detail::vec4) diff --git a/extensions/common/glm/detail/_vectorize.hpp b/extensions/common/glm/detail/_vectorize.hpp new file mode 100644 index 0000000000..1deff1e080 --- /dev/null +++ b/extensions/common/glm/detail/_vectorize.hpp @@ -0,0 +1,160 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/_vectorize.hpp +/// @date 2011-10-14 / 2011-10-14 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "type_vec1.hpp" +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include "type_vec4.hpp" + +namespace glm{ +namespace detail +{ + template <typename R, typename T, precision P, template <typename, precision> class vecType> + struct functor1{}; + + template <typename R, typename T, precision P> + struct functor1<R, T, P, tvec1> + { + GLM_FUNC_QUALIFIER static tvec1<R, P> call(R (*Func) (T x), tvec1<T, P> const & v) + { + return tvec1<R, P>(Func(v.x)); + } + }; + + template <typename R, typename T, precision P> + struct functor1<R, T, P, tvec2> + { + GLM_FUNC_QUALIFIER static tvec2<R, P> call(R (*Func) (T x), tvec2<T, P> const & v) + { + return tvec2<R, P>(Func(v.x), Func(v.y)); + } + }; + + template <typename R, typename T, precision P> + struct functor1<R, T, P, tvec3> + { + GLM_FUNC_QUALIFIER static tvec3<R, P> call(R (*Func) (T x), tvec3<T, P> const & v) + { + return tvec3<R, P>(Func(v.x), Func(v.y), Func(v.z)); + } + }; + + template <typename R, typename T, precision P> + struct functor1<R, T, P, tvec4> + { + GLM_FUNC_QUALIFIER static tvec4<R, P> call(R (*Func) (T x), tvec4<T, P> const & v) + { + return tvec4<R, P>(Func(v.x), Func(v.y), Func(v.z), Func(v.w)); + } + }; + + template <typename T, precision P, template <typename, precision> class vecType> + struct functor2{}; + + template <typename T, precision P> + struct functor2<T, P, tvec1> + { + GLM_FUNC_QUALIFIER static tvec1<T, P> call(T (*Func) (T x, T y), tvec1<T, P> const & a, tvec1<T, P> const & b) + { + return tvec1<T, P>(Func(a.x, b.x)); + } + }; + + template <typename T, precision P> + struct functor2<T, P, tvec2> + { + GLM_FUNC_QUALIFIER static tvec2<T, P> call(T (*Func) (T x, T y), tvec2<T, P> const & a, tvec2<T, P> const & b) + { + return tvec2<T, P>(Func(a.x, b.x), Func(a.y, b.y)); + } + }; + + template <typename T, precision P> + struct functor2<T, P, tvec3> + { + GLM_FUNC_QUALIFIER static tvec3<T, P> call(T (*Func) (T x, T y), tvec3<T, P> const & a, tvec3<T, P> const & b) + { + return tvec3<T, P>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z)); + } + }; + + template <typename T, precision P> + struct functor2<T, P, tvec4> + { + GLM_FUNC_QUALIFIER static tvec4<T, P> call(T (*Func) (T x, T y), tvec4<T, P> const & a, tvec4<T, P> const & b) + { + return tvec4<T, P>(Func(a.x, b.x), Func(a.y, b.y), Func(a.z, b.z), Func(a.w, b.w)); + } + }; + + template <typename T, precision P, template <typename, precision> class vecType> + struct functor2_vec_sca{}; + + template <typename T, precision P> + struct functor2_vec_sca<T, P, tvec1> + { + GLM_FUNC_QUALIFIER static tvec1<T, P> call(T (*Func) (T x, T y), tvec1<T, P> const & a, T b) + { + return tvec1<T, P>(Func(a.x, b)); + } + }; + + template <typename T, precision P> + struct functor2_vec_sca<T, P, tvec2> + { + GLM_FUNC_QUALIFIER static tvec2<T, P> call(T (*Func) (T x, T y), tvec2<T, P> const & a, T b) + { + return tvec2<T, P>(Func(a.x, b), Func(a.y, b)); + } + }; + + template <typename T, precision P> + struct functor2_vec_sca<T, P, tvec3> + { + GLM_FUNC_QUALIFIER static tvec3<T, P> call(T (*Func) (T x, T y), tvec3<T, P> const & a, T b) + { + return tvec3<T, P>(Func(a.x, b), Func(a.y, b), Func(a.z, b)); + } + }; + + template <typename T, precision P> + struct functor2_vec_sca<T, P, tvec4> + { + GLM_FUNC_QUALIFIER static tvec4<T, P> call(T (*Func) (T x, T y), tvec4<T, P> const & a, T b) + { + return tvec4<T, P>(Func(a.x, b), Func(a.y, b), Func(a.z, b), Func(a.w, b)); + } + }; +}//namespace detail +}//namespace glm diff --git a/extensions/common/glm/detail/dummy.cpp b/extensions/common/glm/detail/dummy.cpp new file mode 100644 index 0000000000..88d8f3b807 --- /dev/null +++ b/extensions/common/glm/detail/dummy.cpp @@ -0,0 +1,232 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/core/dummy.cpp +/// @date 2011-01-19 / 2011-06-15 +/// @author Christophe Riccio +/// +/// GLM is a header only library. There is nothing to compile. +/// dummy.cpp exist only a wordaround for CMake file. +/////////////////////////////////////////////////////////////////////////////////// + +#define GLM_MESSAGES +#include <glm/glm.hpp> +#include <glm/ext.hpp> +#include <limits> + +struct material +{ + glm::vec4 emission; // Ecm + glm::vec4 ambient; // Acm + glm::vec4 diffuse; // Dcm + glm::vec4 specular; // Scm + float shininess; // Srm +}; + +struct light +{ + glm::vec4 ambient; // Acli + glm::vec4 diffuse; // Dcli + glm::vec4 specular; // Scli + glm::vec4 position; // Ppli + glm::vec4 halfVector; // Derived: Hi + glm::vec3 spotDirection; // Sdli + float spotExponent; // Srli + float spotCutoff; // Crli + // (range: [0.0,90.0], 180.0) + float spotCosCutoff; // Derived: cos(Crli) + // (range: [1.0,0.0],-1.0) + float constantAttenuation; // K0 + float linearAttenuation; // K1 + float quadraticAttenuation;// K2 +}; + + +// Sample 1 +#include <glm/vec3.hpp>// glm::vec3 +#include <glm/geometric.hpp>// glm::cross, glm::normalize + +glm::vec3 computeNormal +( + glm::vec3 const & a, + glm::vec3 const & b, + glm::vec3 const & c +) +{ + return glm::normalize(glm::cross(c - a, b - a)); +} + +typedef unsigned int GLuint; +#define GL_FALSE 0 +void glUniformMatrix4fv(GLuint, int, int, float*){} + +// Sample 2 +#include <glm/vec3.hpp> // glm::vec3 +#include <glm/vec4.hpp> // glm::vec4, glm::ivec4 +#include <glm/mat4x4.hpp> // glm::mat4 +#include <glm/gtc/matrix_transform.hpp> // glm::translate, glm::rotate, glm::scale, glm::perspective +#include <glm/gtc/type_ptr.hpp> // glm::value_ptr +void func(GLuint LocationMVP, float Translate, glm::vec2 const & Rotate) +{ + glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.f); + glm::mat4 ViewTranslate = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -Translate)); + glm::mat4 ViewRotateX = glm::rotate(ViewTranslate, Rotate.y, glm::vec3(-1.0f, 0.0f, 0.0f)); + glm::mat4 View = glm::rotate(ViewRotateX, Rotate.x, glm::vec3(0.0f, 1.0f, 0.0f)); + glm::mat4 Model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f)); + glm::mat4 MVP = Projection * View * Model; + glUniformMatrix4fv(LocationMVP, 1, GL_FALSE, glm::value_ptr(MVP)); +} + +// Sample 3 +#include <glm/vec2.hpp>// glm::vec2 +#include <glm/packing.hpp>// glm::packUnorm2x16 +#include <glm/integer.hpp>// glm::uint +#include <glm/gtc/type_precision.hpp>// glm::i8vec2, glm::i32vec2 +std::size_t const VertexCount = 4; +// Float quad geometry +std::size_t const PositionSizeF32 = VertexCount * sizeof(glm::vec2); +glm::vec2 const PositionDataF32[VertexCount] = +{ + glm::vec2(-1.0f,-1.0f), + glm::vec2( 1.0f,-1.0f), + glm::vec2( 1.0f, 1.0f), + glm::vec2(-1.0f, 1.0f) + }; +// Half-float quad geometry +std::size_t const PositionSizeF16 = VertexCount * sizeof(glm::uint); +glm::uint const PositionDataF16[VertexCount] = +{ + glm::uint(glm::packUnorm2x16(glm::vec2(-1.0f, -1.0f))), + glm::uint(glm::packUnorm2x16(glm::vec2( 1.0f, -1.0f))), + glm::uint(glm::packUnorm2x16(glm::vec2( 1.0f, 1.0f))), + glm::uint(glm::packUnorm2x16(glm::vec2(-1.0f, 1.0f))) +}; +// 8 bits signed integer quad geometry +std::size_t const PositionSizeI8 = VertexCount * sizeof(glm::i8vec2); +glm::i8vec2 const PositionDataI8[VertexCount] = +{ + glm::i8vec2(-1,-1), + glm::i8vec2( 1,-1), + glm::i8vec2( 1, 1), + glm::i8vec2(-1, 1) +}; +// 32 bits signed integer quad geometry +std::size_t const PositionSizeI32 = VertexCount * sizeof(glm::i32vec2); +glm::i32vec2 const PositionDataI32[VertexCount] = +{ + glm::i32vec2 (-1,-1), + glm::i32vec2 ( 1,-1), + glm::i32vec2 ( 1, 1), + glm::i32vec2 (-1, 1) +}; + +struct intersection +{ + glm::vec4 position; + glm::vec3 normal; +}; + +/* +// Sample 4 +#include <glm/vec3.hpp>// glm::vec3 +#include <glm/geometric.hpp>// glm::normalize, glm::dot, glm::reflect +#include <glm/exponential.hpp>// glm::pow +#include <glm/gtc/random.hpp>// glm::vecRand3 +glm::vec3 lighting +( + intersection const & Intersection, + material const & Material, + light const & Light, + glm::vec3 const & View +) +{ + glm::vec3 Color(0.0f); + glm::vec3 LightVertor(glm::normalize( + Light.position - Intersection.position + + glm::vecRand3(0.0f, Light.inaccuracy)); + + if(!shadow(Intersection.position, Light.position, LightVertor)) + { + float Diffuse = glm::dot(Intersection.normal, LightVector); + if(Diffuse <= 0.0f) + return Color; + if(Material.isDiffuse()) + Color += Light.color() * Material.diffuse * Diffuse; + if(Material.isSpecular()) + { + glm::vec3 Reflect(glm::reflect( + glm::normalize(-LightVector), + glm::normalize(Intersection.normal))); + float Dot = glm::dot(Reflect, View); + float Base = Dot > 0.0f ? Dot : 0.0f; + float Specular = glm::pow(Base, Material.exponent); + Color += Material.specular * Specular; + } + } + return Color; +} +*/ + + +template <typename T, glm::precision P, template<typename, glm::precision> class vecType> +T normalizeDotA(vecType<T, P> const & x, vecType<T, P> const & y) +{ + return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y)); +} + +#define GLM_TEMPLATE_GENTYPE typename T, glm::precision P, template<typename, glm::precision> class + +template <GLM_TEMPLATE_GENTYPE vecType> +T normalizeDotB(vecType<T, P> const & x, vecType<T, P> const & y) +{ + return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y)); +} + +template <typename vecType> +typename vecType::value_type normalizeDotC(vecType const & a, vecType const & b) +{ + return glm::dot(a, b) * glm::inversesqrt(glm::dot(a, a) * glm::dot(b, b)); +} + +int main() +{ + glm::vec1 o(1); + glm::vec2 a(1); + glm::vec3 b(1); + glm::vec4 c(1); + + glm::quat q; + glm::dualquat p; + + glm::mat4 m(1); + + float a0 = normalizeDotA(a, a); + float b0 = normalizeDotB(b, b); + float c0 = normalizeDotC(c, c); + + return 0; +} diff --git a/extensions/common/glm/detail/func_common.hpp b/extensions/common/glm/detail/func_common.hpp new file mode 100644 index 0000000000..da28007b05 --- /dev/null +++ b/extensions/common/glm/detail/func_common.hpp @@ -0,0 +1,456 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_common.hpp +/// @date 2008-03-08 / 2010-01-26 +/// @author Christophe Riccio +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> +/// +/// @defgroup core_func_common Common functions +/// @ingroup core +/// +/// These all operate component-wise. The description is per component. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" +#include "precision.hpp" +#include "type_int.hpp" +#include "_fixes.hpp" + +namespace glm +{ + /// @addtogroup core_func_common + /// @{ + + /// Returns x if x >= 0; otherwise, it returns -x. + /// + /// @tparam genType floating-point or signed integer; scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/abs.xml">GLSL abs man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType> + GLM_FUNC_DECL genType abs(genType x); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> abs(vecType<T, P> const & x); + + /// Returns 1.0 if x > 0, 0.0 if x == 0, or -1.0 if x < 0. + /// + /// @tparam genType Floating-point or signed integer; scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sign.xml">GLSL sign man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> sign(vecType<T, P> const & x); + + /// Returns a value equal to the nearest integer that is less then or equal to x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floor.xml">GLSL floor man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> floor(vecType<T, P> const & x); + + /// Returns a value equal to the nearest integer to x + /// whose absolute value is not larger than the absolute value of x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/trunc.xml">GLSL trunc man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> trunc(vecType<T, P> const & x); + + /// Returns a value equal to the nearest integer to x. + /// The fraction 0.5 will round in a direction chosen by the + /// implementation, presumably the direction that is fastest. + /// This includes the possibility that round(x) returns the + /// same value as roundEven(x) for all values of x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/round.xml">GLSL round man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> round(vecType<T, P> const & x); + + /// Returns a value equal to the nearest integer to x. + /// A fractional part of 0.5 will round toward the nearest even + /// integer. (Both 3.5 and 4.5 for x will return 4.0.) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/roundEven.xml">GLSL roundEven man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + /// @see <a href="http://developer.amd.com/documentation/articles/pages/New-Round-to-Even-Technique.aspx">New round to even technique</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> roundEven(vecType<T, P> const & x); + + /// Returns a value equal to the nearest integer + /// that is greater than or equal to x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/ceil.xml">GLSL ceil man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> ceil(vecType<T, P> const & x); + + /// Return x - floor(x). + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/fract.xml">GLSL fract man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType> + GLM_FUNC_DECL genType fract(genType x); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> fract(vecType<T, P> const & x); + + /// Modulus. Returns x - y * floor(x / y) + /// for each component in x using the floating point value y. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml">GLSL mod man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType> + GLM_FUNC_DECL genType mod(genType x, genType y); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> mod(vecType<T, P> const & x, T y); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> mod(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Returns the fractional part of x and sets i to the integer + /// part (as a whole number floating point value). Both the + /// return value and the output parameter will have the same + /// sign as x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/modf.xml">GLSL modf man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType> + GLM_FUNC_DECL genType modf(genType x, genType & i); + + /// Returns y if y < x; otherwise, it returns x. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/min.xml">GLSL min man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType> + GLM_FUNC_DECL genType min(genType x, genType y); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> min(vecType<T, P> const & x, T y); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> min(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Returns y if x < y; otherwise, it returns x. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/max.xml">GLSL max man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType> + GLM_FUNC_DECL genType max(genType x, genType y); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> max(vecType<T, P> const & x, T y); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> max(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Returns min(max(x, minVal), maxVal) for each component in x + /// using the floating-point values minVal and maxVal. + /// + /// @tparam genType Floating-point or integer; scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/clamp.xml">GLSL clamp man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType> + GLM_FUNC_DECL genType clamp(genType x, genType minVal, genType maxVal); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> clamp(vecType<T, P> const & x, T minVal, T maxVal); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> clamp(vecType<T, P> const & x, vecType<T, P> const & minVal, vecType<T, P> const & maxVal); + + /// If genTypeU is a floating scalar or vector: + /// Returns x * (1.0 - a) + y * a, i.e., the linear blend of + /// x and y using the floating-point value a. + /// The value for a is not restricted to the range [0, 1]. + /// + /// If genTypeU is a boolean scalar or vector: + /// Selects which vector each returned component comes + /// from. For a component of <a> that is false, the + /// corresponding component of x is returned. For a + /// component of a that is true, the corresponding + /// component of y is returned. Components of x and y that + /// are not selected are allowed to be invalid floating point + /// values and will have no effect on the results. Thus, this + /// provides different functionality than + /// genType mix(genType x, genType y, genType(a)) + /// where a is a Boolean vector. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mix.xml">GLSL mix man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + /// + /// @param[in] x Value to interpolate. + /// @param[in] y Value to interpolate. + /// @param[in] a Interpolant. + /// + /// @tparam genTypeT Floating point scalar or vector. + /// @tparam genTypeU Floating point or boolean scalar or vector. It can't be a vector if it is the length of genTypeT. + /// + /// @code + /// #include <glm/glm.hpp> + /// ... + /// float a; + /// bool b; + /// glm::dvec3 e; + /// glm::dvec3 f; + /// glm::vec4 g; + /// glm::vec4 h; + /// ... + /// glm::vec4 r = glm::mix(g, h, a); // Interpolate with a floating-point scalar two vectors. + /// glm::vec4 s = glm::mix(g, h, b); // Teturns g or h; + /// glm::dvec3 t = glm::mix(e, f, a); // Types of the third parameter is not required to match with the first and the second. + /// glm::vec4 u = glm::mix(g, h, r); // Interpolations can be perform per component with a vector for the last parameter. + /// @endcode + template <typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, vecType<U, P> const & a); + + template <typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, U a); + + template <typename genTypeT, typename genTypeU> + GLM_FUNC_DECL genTypeT mix(genTypeT x, genTypeT y, genTypeU a); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0 for each component of a genType. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType> + GLM_FUNC_DECL genType step(genType edge, genType x); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <template <typename, precision> class vecType, typename T, precision P> + GLM_FUNC_DECL vecType<T, P> step(T edge, vecType<T, P> const & x); + + /// Returns 0.0 if x < edge, otherwise it returns 1.0. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/step.xml">GLSL step man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <template <typename, precision> class vecType, typename T, precision P> + GLM_FUNC_DECL vecType<T, P> step(vecType<T, P> const & edge, vecType<T, P> const & x); + + /// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and + /// performs smooth Hermite interpolation between 0 and 1 + /// when edge0 < x < edge1. This is useful in cases where + /// you would want a threshold function with a smooth + /// transition. This is equivalent to: + /// genType t; + /// t = clamp ((x - edge0) / (edge1 - edge0), 0, 1); + /// return t * t * (3 - 2 * t); + /// Results are undefined if edge0 >= edge1. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/smoothstep.xml">GLSL smoothstep man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType> + GLM_FUNC_DECL genType smoothstep(genType edge0, genType edge1, genType x); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> smoothstep(T edge0, T edge1, vecType<T, P> const & x); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> smoothstep(vecType<T, P> const & edge0, vecType<T, P> const & edge1, vecType<T, P> const & x); + + /// Returns true if x holds a NaN (not a number) + /// representation in the underlying implementation's set of + /// floating point representations. Returns false otherwise, + /// including for implementations with no NaN + /// representations. + /// + /// /!\ When using compiler fast math, this function may fail. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isnan.xml">GLSL isnan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> isnan(vecType<T, P> const & x); + + /// Returns true if x holds a positive infinity or negative + /// infinity representation in the underlying implementation's + /// set of floating point representations. Returns false + /// otherwise, including for implementations with no infinity + /// representations. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isinf.xml">GLSL isinf man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> isinf(vecType<T, P> const & x); + + /// Returns a signed integer value representing + /// the encoding of a floating-point value. The floating-point + /// value's bit-level representation is preserved. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToInt.xml">GLSL floatBitsToInt man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + GLM_FUNC_DECL int floatBitsToInt(float const & v); + + /// Returns a signed integer value representing + /// the encoding of a floating-point value. The floatingpoint + /// value's bit-level representation is preserved. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToInt.xml">GLSL floatBitsToInt man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <template <typename, precision> class vecType, precision P> + GLM_FUNC_DECL vecType<int, P> floatBitsToInt(vecType<float, P> const & v); + + /// Returns a unsigned integer value representing + /// the encoding of a floating-point value. The floatingpoint + /// value's bit-level representation is preserved. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToUint.xml">GLSL floatBitsToUint man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + GLM_FUNC_DECL uint floatBitsToUint(float const & v); + + /// Returns a unsigned integer value representing + /// the encoding of a floating-point value. The floatingpoint + /// value's bit-level representation is preserved. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/floatBitsToUint.xml">GLSL floatBitsToUint man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <template <typename, precision> class vecType, precision P> + GLM_FUNC_DECL vecType<uint, P> floatBitsToUint(vecType<float, P> const & v); + + /// Returns a floating-point value corresponding to a signed + /// integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/intBitsToFloat.xml">GLSL intBitsToFloat man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + GLM_FUNC_DECL float intBitsToFloat(int const & v); + + /// Returns a floating-point value corresponding to a signed + /// integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/intBitsToFloat.xml">GLSL intBitsToFloat man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <template <typename, precision> class vecType, precision P> + GLM_FUNC_DECL vecType<float, P> intBitsToFloat(vecType<int, P> const & v); + + /// Returns a floating-point value corresponding to a + /// unsigned integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/uintBitsToFloat.xml">GLSL uintBitsToFloat man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + GLM_FUNC_DECL float uintBitsToFloat(uint const & v); + + /// Returns a floating-point value corresponding to a + /// unsigned integer encoding of a floating-point value. + /// If an inf or NaN is passed in, it will not signal, and the + /// resulting floating point value is unspecified. Otherwise, + /// the bit-level representation is preserved. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/uintBitsToFloat.xml">GLSL uintBitsToFloat man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <template <typename, precision> class vecType, precision P> + GLM_FUNC_DECL vecType<float, P> uintBitsToFloat(vecType<uint, P> const & v); + + /// Computes and returns a * b + c. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/fma.xml">GLSL fma man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType> + GLM_FUNC_DECL genType fma(genType const & a, genType const & b, genType const & c); + + /// Splits x into a floating-point significand in the range + /// [0.5, 1.0) and an integral exponent of two, such that: + /// x = significand * exp(2, exponent) + /// + /// The significand is returned by the function and the + /// exponent is returned in the parameter exp. For a + /// floating-point value of zero, the significant and exponent + /// are both zero. For a floating-point value that is an + /// infinity or is not a number, the results are undefined. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/frexp.xml">GLSL frexp man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType, typename genIType> + GLM_FUNC_DECL genType frexp(genType const & x, genIType & exp); + + /// Builds a floating-point number from x and the + /// corresponding integral exponent of two in exp, returning: + /// significand * exp(2, exponent) + /// + /// If this product is too large to be represented in the + /// floating-point type, the result is undefined. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/ldexp.xml">GLSL ldexp man page</a>; + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType, typename genIType> + GLM_FUNC_DECL genType ldexp(genType const & x, genIType const & exp); + + /// @} +}//namespace glm + +#include "func_common.inl" + diff --git a/extensions/common/glm/detail/func_common.inl b/extensions/common/glm/detail/func_common.inl new file mode 100644 index 0000000000..015ac0dd1e --- /dev/null +++ b/extensions/common/glm/detail/func_common.inl @@ -0,0 +1,758 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_common.inl +/// @date 2008-08-03 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "func_vector_relational.hpp" +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include "type_vec4.hpp" +#include "_vectorize.hpp" +#include <limits> + +namespace glm{ +namespace detail +{ + template <typename genFIType, bool /*signed*/> + struct compute_abs + {}; + + template <typename genFIType> + struct compute_abs<genFIType, true> + { + GLM_FUNC_QUALIFIER static genFIType call(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits<genFIType>::is_iec559 || std::numeric_limits<genFIType>::is_signed, + "'abs' only accept floating-point and integer scalar or vector inputs"); + + return x >= genFIType(0) ? x : -x; + // TODO, perf comp with: *(((int *) &x) + 1) &= 0x7fffffff; + } + }; + + template <typename genFIType> + struct compute_abs<genFIType, false> + { + GLM_FUNC_QUALIFIER static genFIType call(genFIType x) + { + GLM_STATIC_ASSERT( + !std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer, + "'abs' only accept floating-point and integer scalar or vector inputs"); + return x; + } + }; + + template <typename T, typename U, precision P, template <class, precision> class vecType> + struct compute_mix_vector + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, vecType<U, P> const & a) + { + GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559, "'mix' only accept floating-point inputs for the interpolator a"); + + return vecType<T, P>(vecType<U, P>(x) + a * vecType<U, P>(y - x)); + } + }; + + template <typename T, precision P, template <class, precision> class vecType> + struct compute_mix_vector<T, bool, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, vecType<bool, P> const & a) + { + vecType<T, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = a[i] ? y[i] : x[i]; + return Result; + } + }; + + template <typename T, typename U, precision P, template <class, precision> class vecType> + struct compute_mix_scalar + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, U const & a) + { + GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559, "'mix' only accept floating-point inputs for the interpolator a"); + + return vecType<T, P>(vecType<U, P>(x) + a * vecType<U, P>(y - x)); + } + }; + + template <typename T, precision P, template <class, precision> class vecType> + struct compute_mix_scalar<T, bool, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, vecType<T, P> const & y, bool const & a) + { + return a ? y : x; + } + }; + + template <typename T, typename U> + struct compute_mix + { + GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, U const & a) + { + GLM_STATIC_ASSERT(std::numeric_limits<U>::is_iec559, "'mix' only accept floating-point inputs for the interpolator a"); + + return static_cast<T>(static_cast<U>(x) + a * static_cast<U>(y - x)); + } + }; + + template <typename T> + struct compute_mix<T, bool> + { + GLM_FUNC_QUALIFIER static T call(T const & x, T const & y, bool const & a) + { + return a ? y : x; + } + }; + + template <typename T, precision P, template <class, precision> class vecType, bool isFloat = true, bool isSigned = true> + struct compute_sign + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) + { + return vecType<T, P>(glm::lessThan(vecType<T, P>(0), x)) - vecType<T, P>(glm::lessThan(x, vecType<T, P>(0))); + } + }; + + template <typename T, precision P, template <class, precision> class vecType> + struct compute_sign<T, P, vecType, false, false> + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) + { + return vecType<T, P>(glm::greaterThan(x , vecType<T, P>(0))); + } + }; + + template <typename T, precision P, template <class, precision> class vecType> + struct compute_sign<T, P, vecType, false, true> + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) + { + T const Shift(static_cast<T>(sizeof(T) * 8 - 1)); + vecType<T, P> const y(vecType<typename make_unsigned<T>::type, P>(-x) >> typename make_unsigned<T>::type(Shift)); + + return (x >> Shift) | y; + } + }; + + template <typename T, precision P, template <class, precision> class vecType, typename genType, bool isFloat = true> + struct compute_mod + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & a, genType const & b) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'mod' only accept floating-point inputs. Include <glm/gtc/integer.hpp> for integer inputs."); + return a - b * floor(a / b); + } + }; +}//namespace detail + + // abs + template <> + GLM_FUNC_QUALIFIER int32 abs(int32 x) + { + int32 const y = x >> 31; + return (x ^ y) - y; + } + + template <typename genFIType> + GLM_FUNC_QUALIFIER genFIType abs(genFIType x) + { + return detail::compute_abs<genFIType, std::numeric_limits<genFIType>::is_signed>::call(x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> abs(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(abs, x); + } + + // sign + // fast and works for any type + template <typename genFIType> + GLM_FUNC_QUALIFIER genFIType sign(genFIType x) + { + GLM_STATIC_ASSERT( + std::numeric_limits<genFIType>::is_iec559 || (std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer), + "'sign' only accept signed inputs"); + + return detail::compute_sign<genFIType, defaultp, tvec1, std::numeric_limits<genFIType>::is_iec559>::call(tvec1<genFIType>(x)).x; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> sign(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT( + std::numeric_limits<T>::is_iec559 || (std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_integer), + "'sign' only accept signed inputs"); + + return detail::compute_sign<T, P, vecType, std::numeric_limits<T>::is_iec559>::call(x); + } + + // floor + using ::std::floor; + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> floor(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(floor, x); + } + + // trunc +# if GLM_HAS_CXX11_STL + using ::std::trunc; +# else + template <typename genType> + GLM_FUNC_QUALIFIER genType trunc(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'trunc' only accept floating-point inputs"); + + return x < static_cast<genType>(0) ? -floor(-x) : floor(x); + } +# endif + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> trunc(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(trunc, x); + } + + // round +# if GLM_HAS_CXX11_STL + using ::std::round; +# else + template <typename genType> + GLM_FUNC_QUALIFIER genType round(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'round' only accept floating-point inputs"); + + return x < static_cast<genType>(0) ? static_cast<genType>(int(x - static_cast<genType>(0.5))) : static_cast<genType>(int(x + static_cast<genType>(0.5))); + } +# endif + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> round(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(round, x); + } + +/* + // roundEven + template <typename genType> + GLM_FUNC_QUALIFIER genType roundEven(genType const& x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs"); + + return genType(int(x + genType(int(x) % 2))); + } +*/ + + // roundEven + template <typename genType> + GLM_FUNC_QUALIFIER genType roundEven(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'roundEven' only accept floating-point inputs"); + + int Integer = static_cast<int>(x); + genType IntegerPart = static_cast<genType>(Integer); + genType FractionalPart = fract(x); + + if(FractionalPart > static_cast<genType>(0.5) || FractionalPart < static_cast<genType>(0.5)) + { + return round(x); + } + else if((Integer % 2) == 0) + { + return IntegerPart; + } + else if(x <= static_cast<genType>(0)) // Work around... + { + return IntegerPart - static_cast<genType>(1); + } + else + { + return IntegerPart + static_cast<genType>(1); + } + //else // Bug on MinGW 4.5.2 + //{ + // return mix(IntegerPart + genType(-1), IntegerPart + genType(1), x <= genType(0)); + //} + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> roundEven(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(roundEven, x); + } + + // ceil + using ::std::ceil; + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> ceil(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(ceil, x); + } + + // fract + template <typename genType> + GLM_FUNC_QUALIFIER genType fract(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'fract' only accept floating-point inputs"); + + return fract(tvec1<genType>(x)).x; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fract(vecType<T, P> const & x) + { + return x - floor(x); + } + + // mod + template <typename genType> + GLM_FUNC_QUALIFIER genType mod(genType x, genType y) + { + return mod(tvec1<genType>(x), y).x; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> mod(vecType<T, P> const & x, T y) + { + return detail::compute_mod<T, P, vecType, T, std::numeric_limits<T>::is_iec559>::call(x, y); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> mod(vecType<T, P> const & x, vecType<T, P> const & y) + { + return detail::compute_mod<T, P, vecType, vecType<T, P>, std::numeric_limits<T>::is_iec559>::call(x, y); + } + + // modf + template <typename genType> + GLM_FUNC_QUALIFIER genType modf(genType x, genType & i) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'modf' only accept floating-point inputs"); + + return std::modf(x, &i); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> modf(tvec1<T, P> const & x, tvec1<T, P> & i) + { + return tvec1<T, P>( + modf(x.x, i.x)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> modf(tvec2<T, P> const & x, tvec2<T, P> & i) + { + return tvec2<T, P>( + modf(x.x, i.x), + modf(x.y, i.y)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> modf(tvec3<T, P> const & x, tvec3<T, P> & i) + { + return tvec3<T, P>( + modf(x.x, i.x), + modf(x.y, i.y), + modf(x.z, i.z)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> modf(tvec4<T, P> const & x, tvec4<T, P> & i) + { + return tvec4<T, P>( + modf(x.x, i.x), + modf(x.y, i.y), + modf(x.z, i.z), + modf(x.w, i.w)); + } + + //// Only valid if (INT_MIN <= x-y <= INT_MAX) + //// min(x,y) + //r = y + ((x - y) & ((x - y) >> (sizeof(int) * + //CHAR_BIT - 1))); + //// max(x,y) + //r = x - ((x - y) & ((x - y) >> (sizeof(int) * + //CHAR_BIT - 1))); + + // min + template <typename genType> + GLM_FUNC_QUALIFIER genType min(genType x, genType y) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, "'min' only accept floating-point or integer inputs"); + + return x < y ? x : y; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> min(vecType<T, P> const & a, T b) + { + return detail::functor2_vec_sca<T, P, vecType>::call(min, a, b); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> min(vecType<T, P> const & a, vecType<T, P> const & b) + { + return detail::functor2<T, P, vecType>::call(min, a, b); + } + + // max + template <typename genType> + GLM_FUNC_QUALIFIER genType max(genType x, genType y) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, "'max' only accept floating-point or integer inputs"); + + return x > y ? x : y; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> max(vecType<T, P> const & a, T b) + { + return detail::functor2_vec_sca<T, P, vecType>::call(max, a, b); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> max(vecType<T, P> const & a, vecType<T, P> const & b) + { + return detail::functor2<T, P, vecType>::call(max, a, b); + } + + // clamp + template <typename genType> + GLM_FUNC_QUALIFIER genType clamp(genType x, genType minVal, genType maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559 || std::numeric_limits<genType>::is_integer, "'clamp' only accept floating-point or integer inputs"); + + return min(max(x, minVal), maxVal); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> clamp(vecType<T, P> const & x, T minVal, T maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'clamp' only accept floating-point or integer inputs"); + + return min(max(x, minVal), maxVal); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> clamp(vecType<T, P> const & x, vecType<T, P> const & minVal, vecType<T, P> const & maxVal) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559 || std::numeric_limits<T>::is_integer, "'clamp' only accept floating-point or integer inputs"); + + return min(max(x, minVal), maxVal); + } + + template <typename genTypeT, typename genTypeU> + GLM_FUNC_QUALIFIER genTypeT mix(genTypeT x, genTypeT y, genTypeU a) + { + return detail::compute_mix<genTypeT, genTypeU>::call(x, y, a); + } + + template <typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, U a) + { + return detail::compute_mix_scalar<T, U, P, vecType>::call(x, y, a); + } + + template <typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> mix(vecType<T, P> const & x, vecType<T, P> const & y, vecType<U, P> const & a) + { + return detail::compute_mix_vector<T, U, P, vecType>::call(x, y, a); + } + + // step + template <typename genType> + GLM_FUNC_QUALIFIER genType step(genType edge, genType x) + { + return mix(static_cast<genType>(1), static_cast<genType>(0), glm::lessThan(x, edge)); + } + + template <template <typename, precision> class vecType, typename T, precision P> + GLM_FUNC_QUALIFIER vecType<T, P> step(T edge, vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'step' only accept floating-point inputs"); + + return mix(vecType<T, P>(1), vecType<T, P>(0), glm::lessThan(x, vecType<T, P>(edge))); + } + + template <template <typename, precision> class vecType, typename T, precision P> + GLM_FUNC_QUALIFIER vecType<T, P> step(vecType<T, P> const & edge, vecType<T, P> const & x) + { + return mix(vecType<T, P>(1), vecType<T, P>(0), glm::lessThan(x, edge)); + } + + // smoothstep + template <typename genType> + GLM_FUNC_QUALIFIER genType smoothstep(genType edge0, genType edge1, genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'smoothstep' only accept floating-point inputs"); + + genType const tmp(clamp((x - edge0) / (edge1 - edge0), genType(0), genType(1))); + return tmp * tmp * (genType(3) - genType(2) * tmp); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> smoothstep(T edge0, T edge1, vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'smoothstep' only accept floating-point inputs"); + + vecType<T, P> const tmp(clamp((x - edge0) / (edge1 - edge0), static_cast<T>(0), static_cast<T>(1))); + return tmp * tmp * (static_cast<T>(3) - static_cast<T>(2) * tmp); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> smoothstep(vecType<T, P> const & edge0, vecType<T, P> const & edge1, vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'smoothstep' only accept floating-point inputs"); + + vecType<T, P> const tmp(clamp((x - edge0) / (edge1 - edge0), static_cast<T>(0), static_cast<T>(1))); + return tmp * tmp * (static_cast<T>(3) - static_cast<T>(2) * tmp); + } + +# if GLM_HAS_CXX11_STL + using std::isnan; +# else + template <typename genType> + GLM_FUNC_QUALIFIER bool isnan(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'isnan' only accept floating-point inputs"); + +# if GLM_HAS_CXX11_STL + return std::isnan(x); +# elif GLM_COMPILER & (GLM_COMPILER_VC | GLM_COMPILER_INTEL) + return _isnan(x) != 0; +# elif GLM_COMPILER & (GLM_COMPILER_GCC | (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) +# if GLM_PLATFORM & GLM_PLATFORM_ANDROID && __cplusplus < 201103L + return _isnan(x) != 0; +# else + return std::isnan(x); +# endif +# elif GLM_COMPILER & GLM_COMPILER_CUDA + return isnan(x) != 0; +# else + return std::isnan(x); +# endif + } +# endif + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> isnan(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs"); + + return detail::functor1<bool, T, P, vecType>::call(isnan, x); + } + +# if GLM_HAS_CXX11_STL + using std::isinf; +# else + template <typename genType> + GLM_FUNC_QUALIFIER bool isinf(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'isinf' only accept floating-point inputs"); + +# if GLM_HAS_CXX11_STL + return std::isinf(x); +# elif GLM_COMPILER & (GLM_COMPILER_INTEL | GLM_COMPILER_VC) + return _fpclass(x) == _FPCLASS_NINF || _fpclass(x) == _FPCLASS_PINF; +# elif GLM_COMPILER & (GLM_COMPILER_GCC | (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) +# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID && __cplusplus < 201103L) + return _isinf(x) != 0; +# else + return std::isinf(x); +# endif +# elif GLM_COMPILER & GLM_COMPILER_CUDA + // http://developer.download.nvidia.com/compute/cuda/4_2/rel/toolkit/docs/online/group__CUDA__MATH__DOUBLE_g13431dd2b40b51f9139cbb7f50c18fab.html#g13431dd2b40b51f9139cbb7f50c18fab + return isinf(double(x)) != 0; +# else + return std::isinf(x); +# endif + } +# endif + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> isinf(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isnan' only accept floating-point inputs"); + + return detail::functor1<bool, T, P, vecType>::call(isinf, x); + } + + GLM_FUNC_QUALIFIER int floatBitsToInt(float const & v) + { + return reinterpret_cast<int&>(const_cast<float&>(v)); + } + + template <template <typename, precision> class vecType, precision P> + GLM_FUNC_QUALIFIER vecType<int, P> floatBitsToInt(vecType<float, P> const & v) + { + return reinterpret_cast<vecType<int, P>&>(const_cast<vecType<float, P>&>(v)); + } + + GLM_FUNC_QUALIFIER uint floatBitsToUint(float const & v) + { + return reinterpret_cast<uint&>(const_cast<float&>(v)); + } + + template <template <typename, precision> class vecType, precision P> + GLM_FUNC_QUALIFIER vecType<uint, P> floatBitsToUint(vecType<float, P> const & v) + { + return reinterpret_cast<vecType<uint, P>&>(const_cast<vecType<float, P>&>(v)); + } + + GLM_FUNC_QUALIFIER float intBitsToFloat(int const & v) + { + return reinterpret_cast<float&>(const_cast<int&>(v)); + } + + template <template <typename, precision> class vecType, precision P> + GLM_FUNC_QUALIFIER vecType<float, P> intBitsToFloat(vecType<int, P> const & v) + { + return reinterpret_cast<vecType<float, P>&>(const_cast<vecType<int, P>&>(v)); + } + + GLM_FUNC_QUALIFIER float uintBitsToFloat(uint const & v) + { + return reinterpret_cast<float&>(const_cast<uint&>(v)); + } + + template <template <typename, precision> class vecType, precision P> + GLM_FUNC_QUALIFIER vecType<float, P> uintBitsToFloat(vecType<uint, P> const & v) + { + return reinterpret_cast<vecType<float, P>&>(const_cast<vecType<uint, P>&>(v)); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType fma(genType const & a, genType const & b, genType const & c) + { + return a * b + c; + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType frexp(genType x, int & exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'frexp' only accept floating-point inputs"); + + return std::frexp(x, exp); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> frexp(tvec1<T, P> const & x, tvec1<int, P> & exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'frexp' only accept floating-point inputs"); + + return tvec1<T, P>(std::frexp(x.x, exp.x)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> frexp(tvec2<T, P> const & x, tvec2<int, P> & exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'frexp' only accept floating-point inputs"); + + return tvec2<T, P>( + frexp(x.x, exp.x), + frexp(x.y, exp.y)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> frexp(tvec3<T, P> const & x, tvec3<int, P> & exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'frexp' only accept floating-point inputs"); + + return tvec3<T, P>( + frexp(x.x, exp.x), + frexp(x.y, exp.y), + frexp(x.z, exp.z)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> frexp(tvec4<T, P> const & x, tvec4<int, P> & exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'frexp' only accept floating-point inputs"); + + return tvec4<T, P>( + frexp(x.x, exp.x), + frexp(x.y, exp.y), + frexp(x.z, exp.z), + frexp(x.w, exp.w)); + } + + template <typename genType, precision P> + GLM_FUNC_QUALIFIER genType ldexp(genType const & x, int const & exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'ldexp' only accept floating-point inputs"); + + return std::ldexp(x, exp); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> ldexp(tvec1<T, P> const & x, tvec1<int, P> const & exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ldexp' only accept floating-point inputs"); + + return tvec1<T, P>( + ldexp(x.x, exp.x)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> ldexp(tvec2<T, P> const & x, tvec2<int, P> const & exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ldexp' only accept floating-point inputs"); + + return tvec2<T, P>( + ldexp(x.x, exp.x), + ldexp(x.y, exp.y)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> ldexp(tvec3<T, P> const & x, tvec3<int, P> const & exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ldexp' only accept floating-point inputs"); + + return tvec3<T, P>( + ldexp(x.x, exp.x), + ldexp(x.y, exp.y), + ldexp(x.z, exp.z)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> ldexp(tvec4<T, P> const & x, tvec4<int, P> const & exp) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'ldexp' only accept floating-point inputs"); + + return tvec4<T, P>( + ldexp(x.x, exp.x), + ldexp(x.y, exp.y), + ldexp(x.z, exp.z), + ldexp(x.w, exp.w)); + } +}//namespace glm diff --git a/extensions/common/glm/detail/func_exponential.hpp b/extensions/common/glm/detail/func_exponential.hpp new file mode 100644 index 0000000000..5497bc95d6 --- /dev/null +++ b/extensions/common/glm/detail/func_exponential.hpp @@ -0,0 +1,132 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_exponential.hpp +/// @date 2008-08-08 / 2011-06-14 +/// @author Christophe Riccio +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> +/// +/// @defgroup core_func_exponential Exponential functions +/// @ingroup core +/// +/// These all operate component-wise. The description is per component. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "type_vec1.hpp" +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include "type_vec4.hpp" +#include <cmath> + +namespace glm +{ + /// @addtogroup core_func_exponential + /// @{ + + /// Returns 'base' raised to the power 'exponent'. + /// + /// @param base Floating point value. pow function is defined for input values of 'base' defined in the range (inf-, inf+) in the limit of the type precision. + /// @param exponent Floating point value representing the 'exponent'. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/pow.xml">GLSL pow man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> pow(vecType<T, P> const & base, vecType<T, P> const & exponent); + + /// Returns the natural exponentiation of x, i.e., e^x. + /// + /// @param v exp function is defined for input values of v defined in the range (inf-, inf+) in the limit of the type precision. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/exp.xml">GLSL exp man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> exp(vecType<T, P> const & v); + + /// Returns the natural logarithm of v, i.e., + /// returns the value y which satisfies the equation x = e^y. + /// Results are undefined if v <= 0. + /// + /// @param v log function is defined for input values of v defined in the range (0, inf+) in the limit of the type precision. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/log.xml">GLSL log man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> log(vecType<T, P> const & v); + + /// Returns 2 raised to the v power. + /// + /// @param v exp2 function is defined for input values of v defined in the range (inf-, inf+) in the limit of the type precision. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/exp2.xml">GLSL exp2 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> exp2(vecType<T, P> const & v); + + /// Returns the base 2 log of x, i.e., returns the value y, + /// which satisfies the equation x = 2 ^ y. + /// + /// @param v log2 function is defined for input values of v defined in the range (0, inf+) in the limit of the type precision. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/log2.xml">GLSL log2 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> log2(vecType<T, P> const & v); + + /// Returns the positive square root of v. + /// + /// @param v sqrt function is defined for input values of v defined in the range [0, inf+) in the limit of the type precision. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sqrt.xml">GLSL sqrt man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + //template <typename genType> + //GLM_FUNC_DECL genType sqrt(genType const & x); + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> sqrt(vecType<T, P> const & v); + + /// Returns the reciprocal of the positive square root of v. + /// + /// @param v inversesqrt function is defined for input values of v defined in the range [0, inf+) in the limit of the type precision. + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/inversesqrt.xml">GLSL inversesqrt man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.2 Exponential Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> inversesqrt(vecType<T, P> const & v); + + /// @} +}//namespace glm + +#include "func_exponential.inl" diff --git a/extensions/common/glm/detail/func_exponential.inl b/extensions/common/glm/detail/func_exponential.inl new file mode 100644 index 0000000000..bbd76a8dfa --- /dev/null +++ b/extensions/common/glm/detail/func_exponential.inl @@ -0,0 +1,161 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_exponential.inl +/// @date 2008-08-03 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "func_vector_relational.hpp" +#include "_vectorize.hpp" +#include <limits> +#include <cmath> +#include <cassert> + +namespace glm{ +namespace detail +{ +# if GLM_HAS_CXX11_STL + using std::log2; +# else + template <typename genType> + genType log2(genType Value) + { + return std::log(Value) * static_cast<genType>(1.4426950408889634073599246810019); + } +# endif + + template <typename T, precision P, template <class, precision> class vecType, bool isFloat = true> + struct compute_log2 + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & vec) + { + return detail::functor1<T, T, P, vecType>::call(log2, vec); + } + }; + + template <template <class, precision> class vecType, typename T, precision P> + struct compute_inversesqrt + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) + { + return static_cast<T>(1) / sqrt(x); + } + }; + + template <template <class, precision> class vecType> + struct compute_inversesqrt<vecType, float, lowp> + { + GLM_FUNC_QUALIFIER static vecType<float, lowp> call(vecType<float, lowp> const & x) + { + vecType<float, lowp> tmp(x); + vecType<float, lowp> xhalf(tmp * 0.5f); + vecType<uint, lowp>* p = reinterpret_cast<vecType<uint, lowp>*>(const_cast<vecType<float, lowp>*>(&x)); + vecType<uint, lowp> i = vecType<uint, lowp>(0x5f375a86) - (*p >> vecType<uint, lowp>(1)); + vecType<float, lowp>* ptmp = reinterpret_cast<vecType<float, lowp>*>(&i); + tmp = *ptmp; + tmp = tmp * (1.5f - xhalf * tmp * tmp); + return tmp; + } + }; +}//namespace detail + + // pow + using std::pow; + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> pow(vecType<T, P> const & base, vecType<T, P> const & exponent) + { + return detail::functor2<T, P, vecType>::call(pow, base, exponent); + } + + // exp + using std::exp; + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> exp(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(exp, x); + } + + // log + using std::log; + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> log(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(log, x); + } + + //exp2, ln2 = 0.69314718055994530941723212145818f + template <typename genType> + GLM_FUNC_QUALIFIER genType exp2(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'exp2' only accept floating-point inputs"); + + return std::exp(static_cast<genType>(0.69314718055994530941723212145818) * x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> exp2(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(exp2, x); + } + + // log2, ln2 = 0.69314718055994530941723212145818f + template <typename genType> + GLM_FUNC_QUALIFIER genType log2(genType x) + { + return log2(tvec1<genType>(x)).x; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> log2(vecType<T, P> const & x) + { + return detail::compute_log2<T, P, vecType, std::numeric_limits<T>::is_iec559>::call(x); + } + + // sqrt + using std::sqrt; + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> sqrt(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'sqrt' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(sqrt, x); + } + + // inversesqrt + template <typename genType> + GLM_FUNC_QUALIFIER genType inversesqrt(genType x) + { + return static_cast<genType>(1) / sqrt(x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> inversesqrt(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'inversesqrt' only accept floating-point inputs"); + return detail::compute_inversesqrt<vecType, T, P>::call(x); + } +}//namespace glm diff --git a/extensions/common/glm/detail/func_geometric.hpp b/extensions/common/glm/detail/func_geometric.hpp new file mode 100644 index 0000000000..d1198ab4c8 --- /dev/null +++ b/extensions/common/glm/detail/func_geometric.hpp @@ -0,0 +1,142 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_geometric.hpp +/// @date 2008-08-03 / 2011-06-14 +/// @author Christophe Riccio +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> +/// +/// @defgroup core_func_geometric Geometric functions +/// @ingroup core +/// +/// These operate on vectors as vectors, not component-wise. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "type_vec3.hpp" + +namespace glm +{ + /// @addtogroup core_func_geometric + /// @{ + + /// Returns the length of x, i.e., sqrt(x * x). + /// + /// @tparam genType Floating-point vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/length.xml">GLSL length man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL T length( + vecType<T, P> const & x); + + /// Returns the distance betwwen p0 and p1, i.e., length(p0 - p1). + /// + /// @tparam genType Floating-point vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/distance.xml">GLSL distance man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL T distance( + vecType<T, P> const & p0, + vecType<T, P> const & p1); + + /// Returns the dot product of x and y, i.e., result = x * y. + /// + /// @tparam genType Floating-point vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/dot.xml">GLSL dot man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL T dot( + vecType<T, P> const & x, + vecType<T, P> const & y); + + /// Returns the cross product of x and y. + /// + /// @tparam valType Floating-point scalar types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cross.xml">GLSL cross man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> cross( + tvec3<T, P> const & x, + tvec3<T, P> const & y); + + /// Returns a vector in the same direction as x but with length of 1. + /// According to issue 10 GLSL 1.10 specification, if length(x) == 0 then result is undefined and generate an error. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/normalize.xml">GLSL normalize man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> normalize( + vecType<T, P> const & x); + + /// If dot(Nref, I) < 0.0, return N, otherwise, return -N. + /// + /// @tparam genType Floating-point vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/faceforward.xml">GLSL faceforward man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> faceforward( + vecType<T, P> const & N, + vecType<T, P> const & I, + vecType<T, P> const & Nref); + + /// For the incident vector I and surface orientation N, + /// returns the reflection direction : result = I - 2.0 * dot(N, I) * N. + /// + /// @tparam genType Floating-point vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/reflect.xml">GLSL reflect man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template <typename genType> + GLM_FUNC_DECL genType reflect( + genType const & I, + genType const & N); + + /// For the incident vector I and surface normal N, + /// and the ratio of indices of refraction eta, + /// return the refraction vector. + /// + /// @tparam genType Floating-point vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/refract.xml">GLSL refract man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.5 Geometric Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> refract( + vecType<T, P> const & I, + vecType<T, P> const & N, + T eta); + + /// @} +}//namespace glm + +#include "func_geometric.inl" diff --git a/extensions/common/glm/detail/func_geometric.inl b/extensions/common/glm/detail/func_geometric.inl new file mode 100644 index 0000000000..2d4d50eaf4 --- /dev/null +++ b/extensions/common/glm/detail/func_geometric.inl @@ -0,0 +1,201 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_geometric.inl +/// @date 2008-08-03 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "func_exponential.hpp" +#include "func_common.hpp" +#include "type_vec2.hpp" +#include "type_vec4.hpp" +#include "type_float.hpp" + +namespace glm{ +namespace detail +{ + template <template <class, precision> class vecType, typename T, precision P> + struct compute_dot{}; + + template <typename T, precision P> + struct compute_dot<tvec1, T, P> + { + GLM_FUNC_QUALIFIER static T call(tvec1<T, P> const & a, tvec1<T, P> const & b) + { + return a.x * b.x; + } + }; + + template <typename T, precision P> + struct compute_dot<tvec2, T, P> + { + GLM_FUNC_QUALIFIER static T call(tvec2<T, P> const & x, tvec2<T, P> const & y) + { + tvec2<T, P> tmp(x * y); + return tmp.x + tmp.y; + } + }; + + template <typename T, precision P> + struct compute_dot<tvec3, T, P> + { + GLM_FUNC_QUALIFIER static T call(tvec3<T, P> const & x, tvec3<T, P> const & y) + { + tvec3<T, P> tmp(x * y); + return tmp.x + tmp.y + tmp.z; + } + }; + + template <typename T, precision P> + struct compute_dot<tvec4, T, P> + { + GLM_FUNC_QUALIFIER static T call(tvec4<T, P> const & x, tvec4<T, P> const & y) + { + tvec4<T, P> tmp(x * y); + return (tmp.x + tmp.y) + (tmp.z + tmp.w); + } + }; +}//namespace detail + + // length + template <typename genType> + GLM_FUNC_QUALIFIER genType length(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'length' only accept floating-point inputs"); + + return abs(x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T length(vecType<T, P> const & v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'length' only accept floating-point inputs"); + + return sqrt(dot(v, v)); + } + + // distance + template <typename genType> + GLM_FUNC_QUALIFIER genType distance(genType const & p0, genType const & p1) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'distance' only accept floating-point inputs"); + + return length(p1 - p0); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T distance(vecType<T, P> const & p0, vecType<T, P> const & p1) + { + return length(p1 - p0); + } + + // dot + template <typename T> + GLM_FUNC_QUALIFIER T dot(T x, T y) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' only accept floating-point inputs"); + return x * y; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T dot(vecType<T, P> const & x, vecType<T, P> const & y) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'dot' only accept floating-point inputs"); + return detail::compute_dot<vecType, T, P>::call(x, y); + } + + // cross + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> cross(tvec3<T, P> const & x, tvec3<T, P> const & y) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'cross' only accept floating-point inputs"); + + return tvec3<T, P>( + x.y * y.z - y.y * x.z, + x.z * y.x - y.z * x.x, + x.x * y.y - y.x * x.y); + } + + // normalize + template <typename genType> + GLM_FUNC_QUALIFIER genType normalize(genType const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'normalize' only accept floating-point inputs"); + + return x < genType(0) ? genType(-1) : genType(1); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> normalize(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'normalize' only accept floating-point inputs"); + + return x * inversesqrt(dot(x, x)); + } + + // faceforward + template <typename genType> + GLM_FUNC_QUALIFIER genType faceforward(genType const & N, genType const & I, genType const & Nref) + { + return dot(Nref, I) < static_cast<genType>(0) ? N : -N; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> faceforward(vecType<T, P> const & N, vecType<T, P> const & I, vecType<T, P> const & Nref) + { + return dot(Nref, I) < static_cast<T>(0) ? N : -N; + } + + // reflect + template <typename genType> + GLM_FUNC_QUALIFIER genType reflect(genType const & I, genType const & N) + { + return I - N * dot(N, I) * static_cast<genType>(2); + } + + // refract + template <typename genType> + GLM_FUNC_QUALIFIER genType refract(genType const & I, genType const & N, genType const & eta) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'refract' only accept floating-point inputs"); + + genType const dotValue(dot(N, I)); + genType const k(static_cast<genType>(1) - eta * eta * (static_cast<genType>(1) - dotValue * dotValue)); + return (eta * I - (eta * dotValue + sqrt(k)) * N) * static_cast<genType>(k >= static_cast<genType>(0)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> refract(vecType<T, P> const & I, vecType<T, P> const & N, T eta) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'refract' only accept floating-point inputs"); + + T const dotValue(dot(N, I)); + T const k(static_cast<T>(1) - eta * eta * (static_cast<T>(1) - dotValue * dotValue)); + return (eta * I - (eta * dotValue + std::sqrt(k)) * N) * static_cast<T>(k >= static_cast<T>(0)); + } +}//namespace glm diff --git a/extensions/common/glm/detail/func_integer.hpp b/extensions/common/glm/detail/func_integer.hpp new file mode 100644 index 0000000000..8dc4a41882 --- /dev/null +++ b/extensions/common/glm/detail/func_integer.hpp @@ -0,0 +1,232 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_integer.hpp +/// @date 2010-03-17 / 2011-06-18 +/// @author Christophe Riccio +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> +/// +/// @defgroup core_func_integer Integer functions +/// @ingroup core +/// +/// These all operate component-wise. The description is per component. +/// The notation [a, b] means the set of bits from bit-number a through bit-number +/// b, inclusive. The lowest-order bit is bit 0. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" +#include "precision.hpp" +#include "func_common.hpp" +#include "func_vector_relational.hpp" + +namespace glm +{ + /// @addtogroup core_func_integer + /// @{ + + /// Adds 32-bit unsigned integer x and y, returning the sum + /// modulo pow(2, 32). The value carry is set to 0 if the sum was + /// less than pow(2, 32), or to 1 otherwise. + /// + /// @tparam genUType Unsigned integer scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/uaddCarry.xml">GLSL uaddCarry man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<uint, P> uaddCarry( + vecType<uint, P> const & x, + vecType<uint, P> const & y, + vecType<uint, P> & carry); + + /// Subtracts the 32-bit unsigned integer y from x, returning + /// the difference if non-negative, or pow(2, 32) plus the difference + /// otherwise. The value borrow is set to 0 if x >= y, or to 1 otherwise. + /// + /// @tparam genUType Unsigned integer scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/usubBorrow.xml">GLSL usubBorrow man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<uint, P> usubBorrow( + vecType<uint, P> const & x, + vecType<uint, P> const & y, + vecType<uint, P> & borrow); + + /// Multiplies 32-bit integers x and y, producing a 64-bit + /// result. The 32 least-significant bits are returned in lsb. + /// The 32 most-significant bits are returned in msb. + /// + /// @tparam genUType Unsigned integer scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/umulExtended.xml">GLSL umulExtended man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL void umulExtended( + vecType<uint, P> const & x, + vecType<uint, P> const & y, + vecType<uint, P> & msb, + vecType<uint, P> & lsb); + + /// Multiplies 32-bit integers x and y, producing a 64-bit + /// result. The 32 least-significant bits are returned in lsb. + /// The 32 most-significant bits are returned in msb. + /// + /// @tparam genIType Signed integer scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/imulExtended.xml">GLSL imulExtended man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL void imulExtended( + vecType<int, P> const & x, + vecType<int, P> const & y, + vecType<int, P> & msb, + vecType<int, P> & lsb); + + /// Extracts bits [offset, offset + bits - 1] from value, + /// returning them in the least significant bits of the result. + /// For unsigned data types, the most significant bits of the + /// result will be set to zero. For signed data types, the + /// most significant bits will be set to the value of bit offset + base - 1. + /// + /// If bits is zero, the result will be zero. The result will be + /// undefined if offset or bits is negative, or if the sum of + /// offset and bits is greater than the number of bits used + /// to store the operand. + /// + /// @tparam T Signed or unsigned integer scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldExtract.xml">GLSL bitfieldExtract man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> bitfieldExtract( + vecType<T, P> const & Value, + int Offset, + int Bits); + + /// Returns the insertion the bits least-significant bits of insert into base. + /// + /// The result will have bits [offset, offset + bits - 1] taken + /// from bits [0, bits - 1] of insert, and all other bits taken + /// directly from the corresponding bits of base. If bits is + /// zero, the result will simply be base. The result will be + /// undefined if offset or bits is negative, or if the sum of + /// offset and bits is greater than the number of bits used to + /// store the operand. + /// + /// @tparam T Signed or unsigned integer scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldInsert.xml">GLSL bitfieldInsert man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> bitfieldInsert( + vecType<T, P> const & Base, + vecType<T, P> const & Insert, + int Offset, + int Bits); + + /// Returns the reversal of the bits of value. + /// The bit numbered n of the result will be taken from bit (bits - 1) - n of value, + /// where bits is the total number of bits used to represent value. + /// + /// @tparam T Signed or unsigned integer scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitfieldReverse.xml">GLSL bitfieldReverse man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> bitfieldReverse(vecType<T, P> const & v); + + /// Returns the number of bits set to 1 in the binary representation of value. + /// + /// @tparam T Signed or unsigned integer scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitCount.xml">GLSL bitCount man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <typename genType> + GLM_FUNC_DECL int bitCount(genType v); + + /// Returns the number of bits set to 1 in the binary representation of value. + /// + /// @tparam T Signed or unsigned integer scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/bitCount.xml">GLSL bitCount man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<int, P> bitCount(vecType<T, P> const & v); + + /// Returns the bit number of the least significant bit set to + /// 1 in the binary representation of value. + /// If value is zero, -1 will be returned. + /// + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findLSB.xml">GLSL findLSB man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <typename genIUType> + GLM_FUNC_DECL int findLSB(genIUType x); + + /// Returns the bit number of the least significant bit set to + /// 1 in the binary representation of value. + /// If value is zero, -1 will be returned. + /// + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findLSB.xml">GLSL findLSB man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<int, P> findLSB(vecType<T, P> const & v); + + /// Returns the bit number of the most significant bit in the binary representation of value. + /// For positive integers, the result will be the bit number of the most significant bit set to 1. + /// For negative integers, the result will be the bit number of the most significant + /// bit set to 0. For a value of zero or negative one, -1 will be returned. + /// + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findMSB.xml">GLSL findMSB man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <typename genIUType> + GLM_FUNC_DECL int findMSB(genIUType x); + + /// Returns the bit number of the most significant bit in the binary representation of value. + /// For positive integers, the result will be the bit number of the most significant bit set to 1. + /// For negative integers, the result will be the bit number of the most significant + /// bit set to 0. For a value of zero or negative one, -1 will be returned. + /// + /// @tparam T Signed or unsigned integer scalar types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/findMSB.xml">GLSL findMSB man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.8 Integer Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<int, P> findMSB(vecType<T, P> const & v); + + /// @} +}//namespace glm + +#include "func_integer.inl" diff --git a/extensions/common/glm/detail/func_integer.inl b/extensions/common/glm/detail/func_integer.inl new file mode 100644 index 0000000000..5702a152ca --- /dev/null +++ b/extensions/common/glm/detail/func_integer.inl @@ -0,0 +1,393 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_integer.inl +/// @date 2010-03-17 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include "type_vec4.hpp" +#include "type_int.hpp" +#include "_vectorize.hpp" +#if(GLM_ARCH != GLM_ARCH_PURE) +#if(GLM_COMPILER & GLM_COMPILER_VC) +# include <intrin.h> +# pragma intrinsic(_BitScanReverse) +#endif//(GLM_COMPILER & GLM_COMPILER_VC) +#endif//(GLM_ARCH != GLM_ARCH_PURE) +#include <limits> + +namespace glm{ +namespace detail +{ + template <typename T> + GLM_FUNC_QUALIFIER T mask(T Bits) + { + return Bits >= sizeof(T) * 8 ? ~static_cast<T>(0) : (static_cast<T>(1) << Bits) - static_cast<T>(1); + } + + template <bool EXEC = false> + struct compute_bitfieldReverseStep + { + template <typename T, glm::precision P, template <class, glm::precision> class vecType> + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T, T) + { + return v; + } + }; + + template <> + struct compute_bitfieldReverseStep<true> + { + template <typename T, glm::precision P, template <class, glm::precision> class vecType> + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T Mask, T Shift) + { + return (v & Mask) << Shift | (v & (~Mask)) >> Shift; + } + }; + + template <bool EXEC = false> + struct compute_bitfieldBitCountStep + { + template <typename T, glm::precision P, template <class, glm::precision> class vecType> + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T, T) + { + return v; + } + }; + + template <> + struct compute_bitfieldBitCountStep<true> + { + template <typename T, glm::precision P, template <class, glm::precision> class vecType> + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T Mask, T Shift) + { + return (v & Mask) + ((v >> Shift) & Mask); + } + }; + + template <typename genIUType, size_t Bits> + struct compute_findLSB + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + if(Value == 0) + return -1; + + return glm::bitCount(~Value & (Value - static_cast<genIUType>(1))); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template <typename genIUType> + struct compute_findLSB<genIUType, 32> + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanForward(&Result, *reinterpret_cast<unsigned long*>(&Value)); + return IsNotNull ? int(Result) : -1; + } + }; + +# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32)) + template <typename genIUType> + struct compute_findLSB<genIUType, 64> + { + GLM_FUNC_QUALIFIER static int call(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanForward64(&Result, *reinterpret_cast<unsigned __int64*>(&Value)); + return IsNotNull ? int(Result) : -1; + } + }; +# endif +# endif//GLM_HAS_BITSCAN_WINDOWS + + template <typename T, glm::precision P, template <class, glm::precision> class vecType, bool EXEC = true> + struct compute_findMSB_step_vec + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, T Shift) + { + return x | (x >> Shift); + } + }; + + template <typename T, glm::precision P, template <typename, glm::precision> class vecType> + struct compute_findMSB_step_vec<T, P, vecType, false> + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x, T) + { + return x; + } + }; + + template <typename T, glm::precision P, template <typename, glm::precision> class vecType, int> + struct compute_findMSB_vec + { + GLM_FUNC_QUALIFIER static vecType<int, P> call(vecType<T, P> const & vec) + { + vecType<T, P> x(vec); + x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 1)); + x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 2)); + x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 8>::call(x, static_cast<T>( 4)); + x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 16>::call(x, static_cast<T>( 8)); + x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 32>::call(x, static_cast<T>(16)); + x = compute_findMSB_step_vec<T, P, vecType, sizeof(T) * 8 >= 64>::call(x, static_cast<T>(32)); + return vecType<int, P>(sizeof(T) * 8 - 1) - glm::bitCount(~x); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template <typename genIUType> + GLM_FUNC_QUALIFIER int compute_findMSB_32(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanReverse(&Result, *reinterpret_cast<unsigned long*>(&Value)); + return IsNotNull ? int(Result) : -1; + } + + template <typename T, glm::precision P, template <class, glm::precision> class vecType> + struct compute_findMSB_vec<T, P, vecType, 32> + { + GLM_FUNC_QUALIFIER static vecType<int, P> call(vecType<T, P> const & x) + { + return detail::functor1<int, T, P, vecType>::call(compute_findMSB_32, x); + } + }; + +# if !((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_MODEL == GLM_MODEL_32)) + template <typename genIUType> + GLM_FUNC_QUALIFIER int compute_findMSB_64(genIUType Value) + { + unsigned long Result(0); + unsigned char IsNotNull = _BitScanReverse64(&Result, *reinterpret_cast<unsigned __int64*>(&Value)); + return IsNotNull ? int(Result) : -1; + } + + template <typename T, glm::precision P, template <class, glm::precision> class vecType> + struct compute_findMSB_vec<T, P, vecType, 64> + { + GLM_FUNC_QUALIFIER static vecType<int, P> call(vecType<T, P> const & x) + { + return detail::functor1<int, T, P, vecType>::call(compute_findMSB_64, x); + } + }; +# endif +# endif//GLM_HAS_BITSCAN_WINDOWS +}//namespace detail + + // uaddCarry + GLM_FUNC_QUALIFIER uint uaddCarry(uint const & x, uint const & y, uint & Carry) + { + uint64 const Value64(static_cast<uint64>(x) + static_cast<uint64>(y)); + uint64 const Max32((static_cast<uint64>(1) << static_cast<uint64>(32)) - static_cast<uint64>(1)); + Carry = Value64 > Max32 ? 1 : 0; + return static_cast<uint32>(Value64 % (Max32 + static_cast<uint64>(1))); + } + + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<uint, P> uaddCarry(vecType<uint, P> const & x, vecType<uint, P> const & y, vecType<uint, P> & Carry) + { + vecType<uint64, P> Value64(vecType<uint64, P>(x) + vecType<uint64, P>(y)); + vecType<uint64, P> Max32((static_cast<uint64>(1) << static_cast<uint64>(32)) - static_cast<uint64>(1)); + Carry = mix(vecType<uint32, P>(0), vecType<uint32, P>(1), greaterThan(Value64, Max32)); + return vecType<uint32,P>(Value64 % (Max32 + static_cast<uint64>(1))); + } + + // usubBorrow + GLM_FUNC_QUALIFIER uint usubBorrow(uint const & x, uint const & y, uint & Borrow) + { + GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch"); + + Borrow = x >= y ? static_cast<uint32>(0) : static_cast<uint32>(1); + if(y >= x) + return y - x; + else + return static_cast<uint32>((static_cast<int64>(1) << static_cast<int64>(32)) + (static_cast<int64>(y) - static_cast<int64>(x))); + } + + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<uint, P> usubBorrow(vecType<uint, P> const & x, vecType<uint, P> const & y, vecType<uint, P> & Borrow) + { + Borrow = mix(vecType<uint, P>(1), vecType<uint, P>(0), greaterThanEqual(x, y)); + vecType<uint, P> const YgeX(y - x); + vecType<uint, P> const XgeY(vecType<uint32, P>((static_cast<int64>(1) << static_cast<int64>(32)) + (vecType<int64, P>(y) - vecType<int64, P>(x)))); + return mix(XgeY, YgeX, greaterThanEqual(y, x)); + } + + // umulExtended + GLM_FUNC_QUALIFIER void umulExtended(uint const & x, uint const & y, uint & msb, uint & lsb) + { + GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch"); + + uint64 Value64 = static_cast<uint64>(x) * static_cast<uint64>(y); + uint32* PointerMSB = (reinterpret_cast<uint32*>(&Value64) + 1); + msb = *PointerMSB; + uint32* PointerLSB = (reinterpret_cast<uint32*>(&Value64) + 0); + lsb = *PointerLSB; + } + + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER void umulExtended(vecType<uint, P> const & x, vecType<uint, P> const & y, vecType<uint, P> & msb, vecType<uint, P> & lsb) + { + GLM_STATIC_ASSERT(sizeof(uint) == sizeof(uint32), "uint and uint32 size mismatch"); + + vecType<uint64, P> Value64(vecType<uint64, P>(x) * vecType<uint64, P>(y)); + msb = vecType<uint32, P>(Value64 >> static_cast<uint64>(32)); + lsb = vecType<uint32, P>(Value64); + } + + // imulExtended + GLM_FUNC_QUALIFIER void imulExtended(int x, int y, int & msb, int & lsb) + { + GLM_STATIC_ASSERT(sizeof(int) == sizeof(int32), "int and int32 size mismatch"); + + int64 Value64 = static_cast<int64>(x) * static_cast<int64>(y); + int32* PointerMSB = (reinterpret_cast<int32*>(&Value64) + 1); + msb = *PointerMSB; + int32* PointerLSB = (reinterpret_cast<int32*>(&Value64)); + lsb = *PointerLSB; + } + + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER void imulExtended(vecType<int, P> const & x, vecType<int, P> const & y, vecType<int, P> & msb, vecType<int, P> & lsb) + { + GLM_STATIC_ASSERT(sizeof(int) == sizeof(int32), "int and int32 size mismatch"); + + vecType<int64, P> Value64(vecType<int64, P>(x) * vecType<int64, P>(y)); + lsb = vecType<int32, P>(Value64 & static_cast<int64>(0xFFFFFFFF)); + msb = vecType<int32, P>((Value64 >> static_cast<int64>(32)) & static_cast<int64>(0xFFFFFFFF)); + } + + // bitfieldExtract + template <typename genIUType> + GLM_FUNC_QUALIFIER genIUType bitfieldExtract(genIUType Value, int Offset, int Bits) + { + return bitfieldExtract(tvec1<genIUType>(Value), Offset, Bits).x; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> bitfieldExtract(vecType<T, P> const & Value, int Offset, int Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldExtract' only accept integer inputs"); + + return (Value >> static_cast<T>(Offset)) & static_cast<T>(detail::mask(Bits)); + } + + // bitfieldInsert + template <typename genIUType> + GLM_FUNC_QUALIFIER genIUType bitfieldInsert(genIUType const & Base, genIUType const & Insert, int Offset, int Bits) + { + return bitfieldInsert(tvec1<genIUType>(Base), tvec1<genIUType>(Insert), Offset, Bits).x; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> bitfieldInsert(vecType<T, P> const & Base, vecType<T, P> const & Insert, int Offset, int Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldInsert' only accept integer values"); + + T const Mask = static_cast<T>(detail::mask(Bits) << Offset); + return (Base & ~Mask) | (Insert & Mask); + } + + // bitfieldReverse + template <typename genType> + GLM_FUNC_QUALIFIER genType bitfieldReverse(genType x) + { + return bitfieldReverse(glm::tvec1<genType, glm::defaultp>(x)).x; + } + + template <typename T, glm::precision P, template <typename, glm::precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> bitfieldReverse(vecType<T, P> const & v) + { + vecType<T, P> x(v); + x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 2>::call(x, T(0x5555555555555555ull), static_cast<T>( 1)); + x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 4>::call(x, T(0x3333333333333333ull), static_cast<T>( 2)); + x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 8>::call(x, T(0x0F0F0F0F0F0F0F0Full), static_cast<T>( 4)); + x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 16>::call(x, T(0x00FF00FF00FF00FFull), static_cast<T>( 8)); + x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 32>::call(x, T(0x0000FFFF0000FFFFull), static_cast<T>(16)); + x = detail::compute_bitfieldReverseStep<sizeof(T) * 8 >= 64>::call(x, T(0x00000000FFFFFFFFull), static_cast<T>(32)); + return x; + } + + // bitCount + template <typename genType> + GLM_FUNC_QUALIFIER int bitCount(genType x) + { + return bitCount(glm::tvec1<genType, glm::defaultp>(x)).x; + } + + template <typename T, glm::precision P, template <typename, glm::precision> class vecType> + GLM_FUNC_QUALIFIER vecType<int, P> bitCount(vecType<T, P> const & v) + { + vecType<typename detail::make_unsigned<T>::type, P> x(*reinterpret_cast<vecType<typename detail::make_unsigned<T>::type, P> const *>(&v)); + x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 2>::call(x, typename detail::make_unsigned<T>::type(0x5555555555555555ull), typename detail::make_unsigned<T>::type( 1)); + x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 4>::call(x, typename detail::make_unsigned<T>::type(0x3333333333333333ull), typename detail::make_unsigned<T>::type( 2)); + x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 8>::call(x, typename detail::make_unsigned<T>::type(0x0F0F0F0F0F0F0F0Full), typename detail::make_unsigned<T>::type( 4)); + x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 16>::call(x, typename detail::make_unsigned<T>::type(0x00FF00FF00FF00FFull), typename detail::make_unsigned<T>::type( 8)); + x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 32>::call(x, typename detail::make_unsigned<T>::type(0x0000FFFF0000FFFFull), typename detail::make_unsigned<T>::type(16)); + x = detail::compute_bitfieldBitCountStep<sizeof(T) * 8 >= 64>::call(x, typename detail::make_unsigned<T>::type(0x00000000FFFFFFFFull), typename detail::make_unsigned<T>::type(32)); + return vecType<int, P>(x); + } + + // findLSB + template <typename genIUType> + GLM_FUNC_QUALIFIER int findLSB(genIUType Value) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findLSB' only accept integer values"); + + return detail::compute_findLSB<genIUType, sizeof(genIUType) * 8>::call(Value); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<int, P> findLSB(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'findLSB' only accept integer values"); + + return detail::functor1<int, T, P, vecType>::call(findLSB, x); + } + + // findMSB + template <typename genIUType> + GLM_FUNC_QUALIFIER int findMSB(genIUType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'findMSB' only accept integer values"); + + return findMSB(tvec1<genIUType>(x)).x; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<int, P> findMSB(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'findMSB' only accept integer values"); + + return detail::compute_findMSB_vec<T, P, vecType, sizeof(T) * 8>::call(x); + } +}//namespace glm diff --git a/extensions/common/glm/detail/func_matrix.hpp b/extensions/common/glm/detail/func_matrix.hpp new file mode 100644 index 0000000000..4e3b121190 --- /dev/null +++ b/extensions/common/glm/detail/func_matrix.hpp @@ -0,0 +1,178 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_matrix.hpp +/// @date 2008-08-03 / 2011-06-15 +/// @author Christophe Riccio +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> +/// +/// @defgroup core_func_matrix Matrix functions +/// @ingroup core +/// +/// For each of the following built-in matrix functions, there is both a +/// single-precision floating point version, where all arguments and return values +/// are single precision, and a double-precision floating version, where all +/// arguments and return values are double precision. Only the single-precision +/// floating point version is shown. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/precision.hpp" +#include "../detail/setup.hpp" +#include "../detail/type_mat.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../mat2x2.hpp" +#include "../mat2x3.hpp" +#include "../mat2x4.hpp" +#include "../mat3x2.hpp" +#include "../mat3x3.hpp" +#include "../mat3x4.hpp" +#include "../mat4x2.hpp" +#include "../mat4x3.hpp" +#include "../mat4x4.hpp" + +namespace glm{ +namespace detail +{ + template <typename T, precision P> + struct outerProduct_trait<T, P, tvec2, tvec2> + { + typedef tmat2x2<T, P> type; + }; + + template <typename T, precision P> + struct outerProduct_trait<T, P, tvec2, tvec3> + { + typedef tmat2x3<T, P> type; + }; + + template <typename T, precision P> + struct outerProduct_trait<T, P, tvec2, tvec4> + { + typedef tmat2x4<T, P> type; + }; + + template <typename T, precision P> + struct outerProduct_trait<T, P, tvec3, tvec2> + { + typedef tmat3x2<T, P> type; + }; + + template <typename T, precision P> + struct outerProduct_trait<T, P, tvec3, tvec3> + { + typedef tmat3x3<T, P> type; + }; + + template <typename T, precision P> + struct outerProduct_trait<T, P, tvec3, tvec4> + { + typedef tmat3x4<T, P> type; + }; + + template <typename T, precision P> + struct outerProduct_trait<T, P, tvec4, tvec2> + { + typedef tmat4x2<T, P> type; + }; + + template <typename T, precision P> + struct outerProduct_trait<T, P, tvec4, tvec3> + { + typedef tmat4x3<T, P> type; + }; + + template <typename T, precision P> + struct outerProduct_trait<T, P, tvec4, tvec4> + { + typedef tmat4x4<T, P> type; + }; + +}//namespace detail + + /// @addtogroup core_func_matrix + /// @{ + + /// Multiply matrix x by matrix y component-wise, i.e., + /// result[i][j] is the scalar product of x[i][j] and y[i][j]. + /// + /// @tparam matType Floating-point matrix types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/matrixCompMult.xml">GLSL matrixCompMult man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> + template <typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_DECL matType<T, P> matrixCompMult(matType<T, P> const & x, matType<T, P> const & y); + + /// Treats the first parameter c as a column vector + /// and the second parameter r as a row vector + /// and does a linear algebraic matrix multiply c * r. + /// + /// @tparam matType Floating-point matrix types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/outerProduct.xml">GLSL outerProduct man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> + template <typename T, precision P, template <typename, precision> class vecTypeA, template <typename, precision> class vecTypeB> + GLM_FUNC_DECL typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type outerProduct(vecTypeA<T, P> const & c, vecTypeB<T, P> const & r); + + /// Returns the transposed matrix of x + /// + /// @tparam matType Floating-point matrix types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/transpose.xml">GLSL transpose man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> +# if((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2012)) + template <typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_DECL typename matType<T, P>::transpose_type transpose(matType<T, P> const & x); +# endif + + /// Return the determinant of a squared matrix. + /// + /// @tparam valType Floating-point scalar types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/determinant.xml">GLSL determinant man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> + template <typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_DECL T determinant(matType<T, P> const & m); + + /// Return the inverse of a squared matrix. + /// + /// @tparam valType Floating-point scalar types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/inverse.xml">GLSL inverse man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.6 Matrix Functions</a> + template <typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_DECL matType<T, P> inverse(matType<T, P> const & m); + + /// @} +}//namespace glm + +#include "func_matrix.inl" diff --git a/extensions/common/glm/detail/func_matrix.inl b/extensions/common/glm/detail/func_matrix.inl new file mode 100644 index 0000000000..b27efbc28c --- /dev/null +++ b/extensions/common/glm/detail/func_matrix.inl @@ -0,0 +1,310 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_matrix.inl +/// @date 2008-03-08 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "../geometric.hpp" +#include <limits> + +namespace glm{ +namespace detail +{ + template <template <class, precision> class matType, typename T, precision P> + struct compute_transpose{}; + + template <typename T, precision P> + struct compute_transpose<tmat2x2, T, P> + { + GLM_FUNC_QUALIFIER static tmat2x2<T, P> call(tmat2x2<T, P> const & m) + { + tmat2x2<T, P> result(uninitialize); + result[0][0] = m[0][0]; + result[0][1] = m[1][0]; + result[1][0] = m[0][1]; + result[1][1] = m[1][1]; + return result; + } + }; + + template <typename T, precision P> + struct compute_transpose<tmat2x3, T, P> + { + GLM_FUNC_QUALIFIER static tmat3x2<T, P> call(tmat2x3<T, P> const & m) + { + tmat3x2<T, P> result(uninitialize); + result[0][0] = m[0][0]; + result[0][1] = m[1][0]; + result[1][0] = m[0][1]; + result[1][1] = m[1][1]; + result[2][0] = m[0][2]; + result[2][1] = m[1][2]; + return result; + } + }; + + template <typename T, precision P> + struct compute_transpose<tmat2x4, T, P> + { + GLM_FUNC_QUALIFIER static tmat4x2<T, P> call(tmat2x4<T, P> const & m) + { + tmat4x2<T, P> result(uninitialize); + result[0][0] = m[0][0]; + result[0][1] = m[1][0]; + result[1][0] = m[0][1]; + result[1][1] = m[1][1]; + result[2][0] = m[0][2]; + result[2][1] = m[1][2]; + result[3][0] = m[0][3]; + result[3][1] = m[1][3]; + return result; + } + }; + + template <typename T, precision P> + struct compute_transpose<tmat3x2, T, P> + { + GLM_FUNC_QUALIFIER static tmat2x3<T, P> call(tmat3x2<T, P> const & m) + { + tmat2x3<T, P> result(uninitialize); + result[0][0] = m[0][0]; + result[0][1] = m[1][0]; + result[0][2] = m[2][0]; + result[1][0] = m[0][1]; + result[1][1] = m[1][1]; + result[1][2] = m[2][1]; + return result; + } + }; + + template <typename T, precision P> + struct compute_transpose<tmat3x3, T, P> + { + GLM_FUNC_QUALIFIER static tmat3x3<T, P> call(tmat3x3<T, P> const & m) + { + tmat3x3<T, P> result(uninitialize); + result[0][0] = m[0][0]; + result[0][1] = m[1][0]; + result[0][2] = m[2][0]; + + result[1][0] = m[0][1]; + result[1][1] = m[1][1]; + result[1][2] = m[2][1]; + + result[2][0] = m[0][2]; + result[2][1] = m[1][2]; + result[2][2] = m[2][2]; + return result; + } + }; + + template <typename T, precision P> + struct compute_transpose<tmat3x4, T, P> + { + GLM_FUNC_QUALIFIER static tmat4x3<T, P> call(tmat3x4<T, P> const & m) + { + tmat4x3<T, P> result(uninitialize); + result[0][0] = m[0][0]; + result[0][1] = m[1][0]; + result[0][2] = m[2][0]; + result[1][0] = m[0][1]; + result[1][1] = m[1][1]; + result[1][2] = m[2][1]; + result[2][0] = m[0][2]; + result[2][1] = m[1][2]; + result[2][2] = m[2][2]; + result[3][0] = m[0][3]; + result[3][1] = m[1][3]; + result[3][2] = m[2][3]; + return result; + } + }; + + template <typename T, precision P> + struct compute_transpose<tmat4x2, T, P> + { + GLM_FUNC_QUALIFIER static tmat2x4<T, P> call(tmat4x2<T, P> const & m) + { + tmat2x4<T, P> result(uninitialize); + result[0][0] = m[0][0]; + result[0][1] = m[1][0]; + result[0][2] = m[2][0]; + result[0][3] = m[3][0]; + result[1][0] = m[0][1]; + result[1][1] = m[1][1]; + result[1][2] = m[2][1]; + result[1][3] = m[3][1]; + return result; + } + }; + + template <typename T, precision P> + struct compute_transpose<tmat4x3, T, P> + { + GLM_FUNC_QUALIFIER static tmat3x4<T, P> call(tmat4x3<T, P> const & m) + { + tmat3x4<T, P> result(uninitialize); + result[0][0] = m[0][0]; + result[0][1] = m[1][0]; + result[0][2] = m[2][0]; + result[0][3] = m[3][0]; + result[1][0] = m[0][1]; + result[1][1] = m[1][1]; + result[1][2] = m[2][1]; + result[1][3] = m[3][1]; + result[2][0] = m[0][2]; + result[2][1] = m[1][2]; + result[2][2] = m[2][2]; + result[2][3] = m[3][2]; + return result; + } + }; + + template <typename T, precision P> + struct compute_transpose<tmat4x4, T, P> + { + GLM_FUNC_QUALIFIER static tmat4x4<T, P> call(tmat4x4<T, P> const & m) + { + tmat4x4<T, P> result(uninitialize); + result[0][0] = m[0][0]; + result[0][1] = m[1][0]; + result[0][2] = m[2][0]; + result[0][3] = m[3][0]; + + result[1][0] = m[0][1]; + result[1][1] = m[1][1]; + result[1][2] = m[2][1]; + result[1][3] = m[3][1]; + + result[2][0] = m[0][2]; + result[2][1] = m[1][2]; + result[2][2] = m[2][2]; + result[2][3] = m[3][2]; + + result[3][0] = m[0][3]; + result[3][1] = m[1][3]; + result[3][2] = m[2][3]; + result[3][3] = m[3][3]; + return result; + } + }; + + template <template <class, precision> class matType, typename T, precision P> + struct compute_determinant{}; + + template <typename T, precision P> + struct compute_determinant<tmat2x2, T, P> + { + GLM_FUNC_QUALIFIER static T call(tmat2x2<T, P> const & m) + { + return m[0][0] * m[1][1] - m[1][0] * m[0][1]; + } + }; + + template <typename T, precision P> + struct compute_determinant<tmat3x3, T, P> + { + GLM_FUNC_QUALIFIER static T call(tmat3x3<T, P> const & m) + { + return + + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]); + } + }; + + template <typename T, precision P> + struct compute_determinant<tmat4x4, T, P> + { + GLM_FUNC_QUALIFIER static T call(tmat4x4<T, P> const & m) + { + T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + tvec4<T, P> DetCof( + + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), + - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), + + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), + - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); + + return + m[0][0] * DetCof[0] + m[0][1] * DetCof[1] + + m[0][2] * DetCof[2] + m[0][3] * DetCof[3]; + } + }; +}//namespace detail + + template <typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_QUALIFIER matType<T, P> matrixCompMult(matType<T, P> const & x, matType<T, P> const & y) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'matrixCompMult' only accept floating-point inputs"); + + matType<T, P> result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(result); ++i) + result[i] = x[i] * y[i]; + return result; + } + + template<typename T, precision P, template <typename, precision> class vecTypeA, template <typename, precision> class vecTypeB> + GLM_FUNC_QUALIFIER typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type outerProduct(vecTypeA<T, P> const & c, vecTypeB<T, P> const & r) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'outerProduct' only accept floating-point inputs"); + + typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type m(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(m); ++i) + m[i] = c * r[i]; + return m; + } + + template <typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_QUALIFIER typename matType<T, P>::transpose_type transpose(matType<T, P> const & m) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'transpose' only accept floating-point inputs"); + return detail::compute_transpose<matType, T, P>::call(m); + } + + template <typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_QUALIFIER T determinant(matType<T, P> const & m) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'determinant' only accept floating-point inputs"); + return detail::compute_determinant<matType, T, P>::call(m); + } + + template <typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_QUALIFIER matType<T, P> inverse(matType<T, P> const & m) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'inverse' only accept floating-point inputs"); + return detail::compute_inverse(m); + } + +}//namespace glm diff --git a/extensions/common/glm/detail/func_noise.hpp b/extensions/common/glm/detail/func_noise.hpp new file mode 100644 index 0000000000..14b98d9f06 --- /dev/null +++ b/extensions/common/glm/detail/func_noise.hpp @@ -0,0 +1,93 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_noise.hpp +/// @date 2008-08-01 / 2011-06-18 +/// @author Christophe Riccio +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.13 Noise Functions</a> +/// +/// @defgroup core_func_noise Noise functions +/// @ingroup core +/// +/// Noise functions are stochastic functions that can be used to increase visual +/// complexity. Values returned by the following noise functions give the +/// appearance of randomness, but are not truly random. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "type_vec1.hpp" +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include "setup.hpp" + +namespace glm +{ + /// @addtogroup core_func_noise + /// @{ + + /// Returns a 1D noise value based on the input value x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/noise1.xml">GLSL noise1 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.13 Noise Functions</a> + template <typename genType> + GLM_FUNC_DECL typename genType::value_type noise1(genType const & x); + + /// Returns a 2D noise value based on the input value x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/noise2.xml">GLSL noise2 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.13 Noise Functions</a> + template <typename genType> + GLM_FUNC_DECL tvec2<typename genType::value_type, defaultp> noise2(genType const & x); + + /// Returns a 3D noise value based on the input value x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/noise3.xml">GLSL noise3 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.13 Noise Functions</a> + template <typename genType> + GLM_FUNC_DECL tvec3<typename genType::value_type, defaultp> noise3(genType const & x); + + /// Returns a 4D noise value based on the input value x. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/noise4.xml">GLSL noise4 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.13 Noise Functions</a> + template <typename genType> + GLM_FUNC_DECL tvec4<typename genType::value_type, defaultp> noise4(genType const & x); + + /// @} +}//namespace glm + +#include "func_noise.inl" diff --git a/extensions/common/glm/detail/func_noise.inl b/extensions/common/glm/detail/func_noise.inl new file mode 100644 index 0000000000..241e13effb --- /dev/null +++ b/extensions/common/glm/detail/func_noise.inl @@ -0,0 +1,388 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_noise.inl +/// @date 2008-08-01 / 2011-09-27 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "../detail/_noise.hpp" +#include "./func_common.hpp" + +namespace glm{ +namespace detail +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> grad4(T const & j, tvec4<T, P> const & ip) + { + tvec3<T, P> pXYZ = floor(fract(tvec3<T, P>(j) * tvec3<T, P>(ip)) * T(7)) * ip[2] - T(1); + T pW = static_cast<T>(1.5) - dot(abs(pXYZ), tvec3<T, P>(1)); + tvec4<T, P> s = tvec4<T, P>(lessThan(tvec4<T, P>(pXYZ, pW), tvec4<T, P>(0.0))); + pXYZ = pXYZ + (tvec3<T, P>(s) * T(2) - T(1)) * s.w; + return tvec4<T, P>(pXYZ, pW); + } +}//namespace detail + + template <typename T> + GLM_FUNC_QUALIFIER T noise1(T const & x) + { + return noise1(tvec2<T, defaultp>(x, T(0))); + } + + template <typename T> + GLM_FUNC_QUALIFIER tvec2<T, defaultp> noise2(T const & x) + { + return tvec2<T, defaultp>( + noise1(x + T(0.0)), + noise1(x + T(1.0))); + } + + template <typename T> + GLM_FUNC_QUALIFIER tvec3<T, defaultp> noise3(T const & x) + { + return tvec3<T, defaultp>( + noise1(x - T(1.0)), + noise1(x + T(0.0)), + noise1(x + T(1.0))); + } + + template <typename T> + GLM_FUNC_QUALIFIER tvec4<T, defaultp> noise4(T const & x) + { + return tvec4<T, defaultp>( + noise1(x - T(1.0)), + noise1(x + T(0.0)), + noise1(x + T(1.0)), + noise1(x + T(2.0))); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T noise1(tvec2<T, P> const & v) + { + tvec4<T, P> const C = tvec4<T, P>( + T( 0.211324865405187), // (3.0 - sqrt(3.0)) / 6.0 + T( 0.366025403784439), // 0.5 * (sqrt(3.0) - 1.0) + T(-0.577350269189626), // -1.0 + 2.0 * C.x + T( 0.024390243902439)); // 1.0 / 41.0 + + // First corner + tvec2<T, P> i = floor(v + dot(v, tvec2<T, P>(C[1]))); + tvec2<T, P> x0 = v - i + dot(i, tvec2<T, P>(C[0])); + + // Other corners + //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 + //i1.y = 1.0 - i1.x; + tvec2<T, P> i1 = (x0.x > x0.y) ? tvec2<T, P>(1, 0) : tvec2<T, P>(0, 1); + + // x0 = x0 - 0.0 + 0.0 * C.xx ; + // x1 = x0 - i1 + 1.0 * C.xx ; + // x2 = x0 - 1.0 + 2.0 * C.xx ; + tvec4<T, P> x12 = tvec4<T, P>(x0.x, x0.y, x0.x, x0.y) + tvec4<T, P>(C.x, C.x, C.z, C.z); + x12 = tvec4<T, P>(tvec2<T, P>(x12) - i1, x12.z, x12.w); + + // Permutations + i = mod(i, T(289)); // Avoid truncation effects in permutation + tvec3<T, P> p = detail::permute( + detail::permute(i.y + tvec3<T, P>(T(0), i1.y, T(1))) + i.x + tvec3<T, P>(T(0), i1.x, T(1))); + + tvec3<T, P> m = max(T(0.5) - tvec3<T, P>( + dot(x0, x0), + dot(tvec2<T, P>(x12.x, x12.y), tvec2<T, P>(x12.x, x12.y)), + dot(tvec2<T, P>(x12.z, x12.w), tvec2<T, P>(x12.z, x12.w))), T(0)); + + m = m * m; + m = m * m; + + // Gradients: 41 points uniformly over a line, mapped onto a diamond. + // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) + + tvec3<T, P> x = static_cast<T>(2) * fract(p * C.w) - T(1); + tvec3<T, P> h = abs(x) - T(0.5); + tvec3<T, P> ox = floor(x + T(0.5)); + tvec3<T, P> a0 = x - ox; + + // Normalise gradients implicitly by scaling m + // Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h ); + m *= static_cast<T>(1.79284291400159) - T(0.85373472095314) * (a0 * a0 + h * h); + + // Compute final noise value at P + tvec3<T, P> g; + g.x = a0.x * x0.x + h.x * x0.y; + //g.yz = a0.yz * x12.xz + h.yz * x12.yw; + g.y = a0.y * x12.x + h.y * x12.y; + g.z = a0.z * x12.z + h.z * x12.w; + return T(130) * dot(m, g); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T noise1(tvec3<T, P> const & v) + { + tvec2<T, P> const C(1.0 / 6.0, 1.0 / 3.0); + tvec4<T, P> const D(0.0, 0.5, 1.0, 2.0); + + // First corner + tvec3<T, P> i(floor(v + dot(v, tvec3<T, P>(C.y)))); + tvec3<T, P> x0(v - i + dot(i, tvec3<T, P>(C.x))); + + // Other corners + tvec3<T, P> g(step(tvec3<T, P>(x0.y, x0.z, x0.x), x0)); + tvec3<T, P> l(T(1) - g); + tvec3<T, P> i1(min(g, tvec3<T, P>(l.z, l.x, l.y))); + tvec3<T, P> i2(max(g, tvec3<T, P>(l.z, l.x, l.y))); + + // x0 = x0 - 0.0 + 0.0 * C.xxx; + // x1 = x0 - i1 + 1.0 * C.xxx; + // x2 = x0 - i2 + 2.0 * C.xxx; + // x3 = x0 - 1.0 + 3.0 * C.xxx; + tvec3<T, P> x1(x0 - i1 + C.x); + tvec3<T, P> x2(x0 - i2 + C.y); // 2.0*C.x = 1/3 = C.y + tvec3<T, P> x3(x0 - D.y); // -1.0+3.0*C.x = -0.5 = -D.y + + // Permutations + i = mod289(i); + tvec4<T, P> p(detail::permute(detail::permute(detail::permute( + i.z + tvec4<T, P>(T(0), i1.z, i2.z, T(1))) + + i.y + tvec4<T, P>(T(0), i1.y, i2.y, T(1))) + + i.x + tvec4<T, P>(T(0), i1.x, i2.x, T(1)))); + + // Gradients: 7x7 points over a square, mapped onto an octahedron. + // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) + T n_ = static_cast<T>(0.142857142857); // 1.0/7.0 + tvec3<T, P> ns(n_ * tvec3<T, P>(D.w, D.y, D.z) - tvec3<T, P>(D.x, D.z, D.x)); + + tvec4<T, P> j(p - T(49) * floor(p * ns.z * ns.z)); // mod(p,7*7) + + tvec4<T, P> x_(floor(j * ns.z)); + tvec4<T, P> y_(floor(j - T(7) * x_)); // mod(j,N) + + tvec4<T, P> x(x_ * ns.x + ns.y); + tvec4<T, P> y(y_ * ns.x + ns.y); + tvec4<T, P> h(T(1) - abs(x) - abs(y)); + + tvec4<T, P> b0(x.x, x.y, y.x, y.y); + tvec4<T, P> b1(x.z, x.w, y.z, y.w); + + // vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; + // vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; + tvec4<T, P> s0(floor(b0) * T(2) + T(1)); + tvec4<T, P> s1(floor(b1) * T(2) + T(1)); + tvec4<T, P> sh(-step(h, tvec4<T, P>(0.0))); + + tvec4<T, P> a0 = tvec4<T, P>(b0.x, b0.z, b0.y, b0.w) + tvec4<T, P>(s0.x, s0.z, s0.y, s0.w) * tvec4<T, P>(sh.x, sh.x, sh.y, sh.y); + tvec4<T, P> a1 = tvec4<T, P>(b1.x, b1.z, b1.y, b1.w) + tvec4<T, P>(s1.x, s1.z, s1.y, s1.w) * tvec4<T, P>(sh.z, sh.z, sh.w, sh.w); + + tvec3<T, P> p0(a0.x, a0.y, h.x); + tvec3<T, P> p1(a0.z, a0.w, h.y); + tvec3<T, P> p2(a1.x, a1.y, h.z); + tvec3<T, P> p3(a1.z, a1.w, h.w); + + // Normalise gradients + tvec4<T, P> norm = taylorInvSqrt(tvec4<T, P>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + + // Mix final noise value + tvec4<T, P> m = max(T(0.6) - tvec4<T, P>(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), T(0)); + m = m * m; + return T(42) * dot(m * m, tvec4<T, P>(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3))); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T noise1(tvec4<T, P> const & v) + { + tvec4<T, P> const C( + 0.138196601125011, // (5 - sqrt(5))/20 G4 + 0.276393202250021, // 2 * G4 + 0.414589803375032, // 3 * G4 + -0.447213595499958); // -1 + 4 * G4 + + // (sqrt(5) - 1)/4 = F4, used once below + T const F4 = static_cast<T>(0.309016994374947451); + + // First corner + tvec4<T, P> i = floor(v + dot(v, tvec4<T, P>(F4))); + tvec4<T, P> x0 = v - i + dot(i, tvec4<T, P>(C.x)); + + // Other corners + + // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) + tvec4<T, P> i0; + tvec3<T, P> isX = step(tvec3<T, P>(x0.y, x0.z, x0.w), tvec3<T, P>(x0.x)); + tvec3<T, P> isYZ = step(tvec3<T, P>(x0.z, x0.w, x0.w), tvec3<T, P>(x0.y, x0.y, x0.z)); + + // i0.x = dot(isX, vec3(1.0)); + //i0.x = isX.x + isX.y + isX.z; + //i0.yzw = static_cast<T>(1) - isX; + i0 = tvec4<T, P>(isX.x + isX.y + isX.z, T(1) - isX); + + // i0.y += dot(isYZ.xy, vec2(1.0)); + i0.y += isYZ.x + isYZ.y; + + //i0.zw += 1.0 - tvec2<T, P>(isYZ.x, isYZ.y); + i0.z += static_cast<T>(1) - isYZ.x; + i0.w += static_cast<T>(1) - isYZ.y; + i0.z += isYZ.z; + i0.w += static_cast<T>(1) - isYZ.z; + + // i0 now contains the unique values 0,1,2,3 in each channel + tvec4<T, P> i3 = clamp(i0, T(0), T(1)); + tvec4<T, P> i2 = clamp(i0 - T(1), T(0), T(1)); + tvec4<T, P> i1 = clamp(i0 - T(2), T(0), T(1)); + + // x0 = x0 - 0.0 + 0.0 * C.xxxx + // x1 = x0 - i1 + 0.0 * C.xxxx + // x2 = x0 - i2 + 0.0 * C.xxxx + // x3 = x0 - i3 + 0.0 * C.xxxx + // x4 = x0 - 1.0 + 4.0 * C.xxxx + tvec4<T, P> x1 = x0 - i1 + C.x; + tvec4<T, P> x2 = x0 - i2 + C.y; + tvec4<T, P> x3 = x0 - i3 + C.z; + tvec4<T, P> x4 = x0 + C.w; + + // Permutations + i = mod(i, T(289)); + T j0 = detail::permute(detail::permute(detail::permute(detail::permute(i.w) + i.z) + i.y) + i.x); + tvec4<T, P> j1 = detail::permute(detail::permute(detail::permute(detail::permute( + i.w + tvec4<T, P>(i1.w, i2.w, i3.w, T(1))) + + i.z + tvec4<T, P>(i1.z, i2.z, i3.z, T(1))) + + i.y + tvec4<T, P>(i1.y, i2.y, i3.y, T(1))) + + i.x + tvec4<T, P>(i1.x, i2.x, i3.x, T(1))); + + // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope + // 7*7*6 = 294, which is close to the ring size 17*17 = 289. + tvec4<T, P> ip = tvec4<T, P>(T(1) / T(294), T(1) / T(49), T(1) / T(7), T(0)); + + tvec4<T, P> p0 = detail::grad4(j0, ip); + tvec4<T, P> p1 = detail::grad4(j1.x, ip); + tvec4<T, P> p2 = detail::grad4(j1.y, ip); + tvec4<T, P> p3 = detail::grad4(j1.z, ip); + tvec4<T, P> p4 = detail::grad4(j1.w, ip); + + // Normalise gradients + tvec4<T, P> norm = detail::taylorInvSqrt(tvec4<T, P>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + p4 *= taylorInvSqrt(dot(p4, p4)); + + // Mix contributions from the five corners + tvec3<T, P> m0 = max(T(0.6) - tvec3<T, P>(dot(x0, x0), dot(x1, x1), dot(x2, x2)), T(0)); + tvec2<T, P> m1 = max(T(0.6) - tvec2<T, P>(dot(x3, x3), dot(x4, x4) ), T(0)); + m0 = m0 * m0; + m1 = m1 * m1; + + return T(49) * ( + dot(m0 * m0, tvec3<T, P>(dot(p0, x0), dot(p1, x1), dot(p2, x2))) + + dot(m1 * m1, tvec2<T, P>(dot(p3, x3), dot(p4, x4)))); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> noise2(tvec2<T, P> const & x) + { + return tvec2<T, P>( + noise1(x + tvec2<T, P>(0.0)), + noise1(tvec2<T, P>(0.0) - x)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> noise2(tvec3<T, P> const & x) + { + return tvec2<T, P>( + noise1(x + tvec3<T, P>(0.0)), + noise1(tvec3<T, P>(0.0) - x)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> noise2(tvec4<T, P> const & x) + { + return tvec2<T, P>( + noise1(x + tvec4<T, P>(0)), + noise1(tvec4<T, P>(0) - x)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> noise3(tvec2<T, P> const & x) + { + return tvec3<T, P>( + noise1(x - tvec2<T, P>(1.0)), + noise1(x + tvec2<T, P>(0.0)), + noise1(x + tvec2<T, P>(1.0))); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> noise3(tvec3<T, P> const & x) + { + return tvec3<T, P>( + noise1(x - tvec3<T, P>(1.0)), + noise1(x + tvec3<T, P>(0.0)), + noise1(x + tvec3<T, P>(1.0))); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> noise3(tvec4<T, P> const & x) + { + return tvec3<T, P>( + noise1(x - tvec4<T, P>(1)), + noise1(x + tvec4<T, P>(0)), + noise1(x + tvec4<T, P>(1))); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> noise4(tvec2<T, P> const & x) + { + return tvec4<T, P>( + noise1(x - tvec2<T, P>(1)), + noise1(x + tvec2<T, P>(0)), + noise1(x + tvec2<T, P>(1)), + noise1(x + tvec2<T, P>(2))); + } + + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> noise4(tvec3<T, P> const & x) + { + return tvec4<T, P>( + noise1(x - tvec3<T, P>(1)), + noise1(x + tvec3<T, P>(0)), + noise1(x + tvec3<T, P>(1)), + noise1(x + tvec3<T, P>(2))); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> noise4(tvec4<T, P> const & x) + { + return tvec4<T, P>( + noise1(x - tvec4<T, P>(1)), + noise1(x + tvec4<T, P>(0)), + noise1(x + tvec4<T, P>(1)), + noise1(x + tvec4<T, P>(2))); + } + +}//namespace glm diff --git a/extensions/common/glm/detail/func_packing.hpp b/extensions/common/glm/detail/func_packing.hpp new file mode 100644 index 0000000000..98edfa685f --- /dev/null +++ b/extensions/common/glm/detail/func_packing.hpp @@ -0,0 +1,197 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_packing.hpp +/// @date 2010-03-17 / 2011-06-15 +/// @author Christophe Riccio +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> +/// @see gtc_packing +/// +/// @defgroup core_func_packing Floating-Point Pack and Unpack Functions +/// @ingroup core +/// +/// These functions do not operate component-wise, rather as described in each case. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "type_vec2.hpp" +#include "type_vec4.hpp" + +namespace glm +{ + /// @addtogroup core_func_packing + /// @{ + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm2x16: round(clamp(c, 0, +1) * 65535.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm2x16.xml">GLSL packUnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint packUnorm2x16(vec2 const & v); + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm2x16: round(clamp(v, -1, +1) * 32767.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm2x16.xml">GLSL packSnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint packSnorm2x16(vec2 const & v); + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm4x8: round(clamp(c, 0, +1) * 255.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm4x8.xml">GLSL packUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint packUnorm4x8(vec4 const & v); + + /// First, converts each component of the normalized floating-point value v into 8- or 16-bit integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm4x8: round(clamp(c, -1, +1) * 127.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm4x8.xml">GLSL packSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint packSnorm4x8(vec4 const & v); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm2x16: f / 65535.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm2x16.xml">GLSL unpackUnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL vec2 unpackUnorm2x16(uint p); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm2x16: clamp(f / 32767.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm2x16.xml">GLSL unpackSnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL vec2 unpackSnorm2x16(uint p); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm4x8: f / 255.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm4x8.xml">GLSL unpackUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL vec4 unpackUnorm4x8(uint p); + + /// First, unpacks a single 32-bit unsigned integer p into a pair of 16-bit unsigned integers, four 8-bit unsigned integers, or four 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two- or four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm4x8: clamp(f / 127.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm4x8.xml">GLSL unpackSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL vec4 unpackSnorm4x8(uint p); + + /// Returns a double-precision value obtained by packing the components of v into a 64-bit value. + /// If an IEEE 754 Inf or NaN is created, it will not signal, and the resulting floating point value is unspecified. + /// Otherwise, the bit- level representation of v is preserved. + /// The first vector component specifies the 32 least significant bits; + /// the second component specifies the 32 most significant bits. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packDouble2x32.xml">GLSL packDouble2x32 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL double packDouble2x32(uvec2 const & v); + + /// Returns a two-component unsigned integer vector representation of v. + /// The bit-level representation of v is preserved. + /// The first component of the vector contains the 32 least significant bits of the double; + /// the second component consists the 32 most significant bits. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackDouble2x32.xml">GLSL unpackDouble2x32 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uvec2 unpackDouble2x32(double v); + + /// Returns an unsigned integer obtained by converting the components of a two-component floating-point vector + /// to the 16-bit floating-point representation found in the OpenGL Specification, + /// and then packing these two 16- bit integers into a 32-bit unsigned integer. + /// The first vector component specifies the 16 least-significant bits of the result; + /// the second component specifies the 16 most-significant bits. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packHalf2x16.xml">GLSL packHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint packHalf2x16(vec2 const & v); + + /// Returns a two-component floating-point vector with components obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values, + /// interpreting those values as 16-bit floating-point numbers according to the OpenGL Specification, + /// and converting them to 32-bit floating-point values. + /// The first component of the vector is obtained from the 16 least-significant bits of v; + /// the second component is obtained from the 16 most-significant bits of v. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackHalf2x16.xml">GLSL unpackHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL vec2 unpackHalf2x16(uint v); + + /// @} +}//namespace glm + +#include "func_packing.inl" diff --git a/extensions/common/glm/detail/func_packing.inl b/extensions/common/glm/detail/func_packing.inl new file mode 100644 index 0000000000..f853e4d101 --- /dev/null +++ b/extensions/common/glm/detail/func_packing.inl @@ -0,0 +1,119 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_packing.inl +/// @date 2010-03-17 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "func_common.hpp" +#include "type_half.hpp" +#include "../fwd.hpp" + +namespace glm +{ + GLM_FUNC_QUALIFIER uint packUnorm2x16(vec2 const & v) + { + u16vec2 const Topack(round(clamp(v, 0.0f, 1.0f) * 65535.0f)); + return reinterpret_cast<uint const &>(Topack); + } + + GLM_FUNC_QUALIFIER vec2 unpackUnorm2x16(uint p) + { + vec2 Unpack(reinterpret_cast<u16vec2 const &>(p)); + return Unpack * float(1.5259021896696421759365224689097e-5); // 1.0 / 65535.0 + } + + GLM_FUNC_QUALIFIER uint packSnorm2x16(vec2 const & v) + { + i16vec2 const Topack(round(clamp(v ,-1.0f, 1.0f) * 32767.0f)); + return reinterpret_cast<uint const &>(Topack); + } + + GLM_FUNC_QUALIFIER vec2 unpackSnorm2x16(uint p) + { + vec2 const Unpack(reinterpret_cast<i16vec2 const &>(p)); + return clamp( + Unpack * 3.0518509475997192297128208258309e-5f, //1.0f / 32767.0f, + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint packUnorm4x8(vec4 const & v) + { + u8vec4 const Topack(round(clamp(v, 0.0f, 1.0f) * 255.0f)); + return reinterpret_cast<uint const &>(Topack); + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm4x8(uint p) + { + vec4 const Unpack(reinterpret_cast<u8vec4 const&>(p)); + return Unpack * float(0.0039215686274509803921568627451); // 1 / 255 + } + + GLM_FUNC_QUALIFIER uint packSnorm4x8(vec4 const & v) + { + i8vec4 const Topack(round(clamp(v ,-1.0f, 1.0f) * 127.0f)); + return reinterpret_cast<uint const &>(Topack); + } + + GLM_FUNC_QUALIFIER glm::vec4 unpackSnorm4x8(uint p) + { + vec4 const Unpack(reinterpret_cast<i8vec4 const &>(p)); + return clamp( + Unpack * 0.0078740157480315f, // 1.0f / 127.0f + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER double packDouble2x32(uvec2 const & v) + { + return reinterpret_cast<double const &>(v); + } + + GLM_FUNC_QUALIFIER uvec2 unpackDouble2x32(double v) + { + return reinterpret_cast<uvec2 const &>(v); + } + + GLM_FUNC_QUALIFIER uint packHalf2x16(vec2 const & v) + { + i16vec2 const Unpack( + detail::toFloat16(v.x), + detail::toFloat16(v.y)); + + return reinterpret_cast<uint const &>(Unpack); + } + + GLM_FUNC_QUALIFIER vec2 unpackHalf2x16(uint v) + { + i16vec2 const Unpack(reinterpret_cast<i16vec2 const &>(v)); + + return vec2( + detail::toFloat32(Unpack.x), + detail::toFloat32(Unpack.y)); + } +}//namespace glm + diff --git a/extensions/common/glm/detail/func_trigonometric.hpp b/extensions/common/glm/detail/func_trigonometric.hpp new file mode 100644 index 0000000000..55680b9fc6 --- /dev/null +++ b/extensions/common/glm/detail/func_trigonometric.hpp @@ -0,0 +1,205 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_trigonometric.hpp +/// @date 2008-08-01 / 2011-06-15 +/// @author Christophe Riccio +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> +/// +/// @defgroup core_func_trigonometric Angle and Trigonometry Functions +/// @ingroup core +/// +/// Function parameters specified as angle are assumed to be in units of radians. +/// In no case will any of these functions result in a divide by zero error. If +/// the divisor of a ratio is 0, then results will be undefined. +/// +/// These all operate component-wise. The description is per component. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" +#include "precision.hpp" + +namespace glm +{ + /// @addtogroup core_func_trigonometric + /// @{ + + /// Converts degrees to radians and returns the result. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/radians.xml">GLSL radians man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> radians(vecType<T, P> const & degrees); + + /// Converts radians to degrees and returns the result. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/degrees.xml">GLSL degrees man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> degrees(vecType<T, P> const & radians); + + /// The standard trigonometric sine function. + /// The values returned by this function will range from [-1, 1]. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sin.xml">GLSL sin man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> sin(vecType<T, P> const & angle); + + /// The standard trigonometric cosine function. + /// The values returned by this function will range from [-1, 1]. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cos.xml">GLSL cos man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> cos(vecType<T, P> const & angle); + + /// The standard trigonometric tangent function. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/tan.xml">GLSL tan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> tan(vecType<T, P> const & angle); + + /// Arc sine. Returns an angle whose sine is x. + /// The range of values returned by this function is [-PI/2, PI/2]. + /// Results are undefined if |x| > 1. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/asin.xml">GLSL asin man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> asin(vecType<T, P> const & x); + + /// Arc cosine. Returns an angle whose sine is x. + /// The range of values returned by this function is [0, PI]. + /// Results are undefined if |x| > 1. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/acos.xml">GLSL acos man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> acos(vecType<T, P> const & x); + + /// Arc tangent. Returns an angle whose tangent is y/x. + /// The signs of x and y are used to determine what + /// quadrant the angle is in. The range of values returned + /// by this function is [-PI, PI]. Results are undefined + /// if x and y are both 0. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atan.xml">GLSL atan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> atan(vecType<T, P> const & y, vecType<T, P> const & x); + + /// Arc tangent. Returns an angle whose tangent is y_over_x. + /// The range of values returned by this function is [-PI/2, PI/2]. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atan.xml">GLSL atan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> atan(vecType<T, P> const & y_over_x); + + /// Returns the hyperbolic sine function, (exp(x) - exp(-x)) / 2 + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/sinh.xml">GLSL sinh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> sinh(vecType<T, P> const & angle); + + /// Returns the hyperbolic cosine function, (exp(x) + exp(-x)) / 2 + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/cosh.xml">GLSL cosh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> cosh(vecType<T, P> const & angle); + + /// Returns the hyperbolic tangent function, sinh(angle) / cosh(angle) + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/tanh.xml">GLSL tanh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> tanh(vecType<T, P> const & angle); + + /// Arc hyperbolic sine; returns the inverse of sinh. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/asinh.xml">GLSL asinh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> asinh(vecType<T, P> const & x); + + /// Arc hyperbolic cosine; returns the non-negative inverse + /// of cosh. Results are undefined if x < 1. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/acosh.xml">GLSL acosh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> acosh(vecType<T, P> const & x); + + /// Arc hyperbolic tangent; returns the inverse of tanh. + /// Results are undefined if abs(x) >= 1. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/atanh.xml">GLSL atanh man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.1 Angle and Trigonometry Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> atanh(vecType<T, P> const & x); + + /// @} +}//namespace glm + +#include "func_trigonometric.inl" diff --git a/extensions/common/glm/detail/func_trigonometric.inl b/extensions/common/glm/detail/func_trigonometric.inl new file mode 100644 index 0000000000..8f9c20df76 --- /dev/null +++ b/extensions/common/glm/detail/func_trigonometric.inl @@ -0,0 +1,224 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_trigonometric.inl +/// @date 2008-08-03 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "_vectorize.hpp" +#include <cmath> +#include <limits> + +namespace glm +{ + // radians + template <typename genType> + GLM_FUNC_QUALIFIER genType radians(genType degrees) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'radians' only accept floating-point input"); + + return degrees * static_cast<genType>(0.01745329251994329576923690768489); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> radians(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(radians, v); + } + + // degrees + template <typename genType> + GLM_FUNC_QUALIFIER genType degrees(genType radians) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'degrees' only accept floating-point input"); + + return radians * static_cast<genType>(57.295779513082320876798154814105); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> degrees(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(degrees, v); + } + + // sin + using ::std::sin; + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> sin(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(sin, v); + } + + // cos + using std::cos; + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> cos(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(cos, v); + } + + // tan + using std::tan; + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> tan(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(tan, v); + } + + // asin + using std::asin; + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> asin(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(asin, v); + } + + // acos + using std::acos; + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> acos(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(acos, v); + } + + // atan + template <typename genType> + GLM_FUNC_QUALIFIER genType atan(genType const & y, genType const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'atan' only accept floating-point input"); + + return ::std::atan2(y, x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> atan(vecType<T, P> const & a, vecType<T, P> const & b) + { + return detail::functor2<T, P, vecType>::call(atan2, a, b); + } + + using std::atan; + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> atan(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(atan, v); + } + + // sinh + using std::sinh; + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> sinh(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(sinh, v); + } + + // cosh + using std::cosh; + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> cosh(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(cosh, v); + } + + // tanh + using std::tanh; + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> tanh(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(tanh, v); + } + + // asinh +# if GLM_HAS_CXX11_STL + using std::asinh; +# else + template <typename genType> + GLM_FUNC_QUALIFIER genType asinh(genType const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'asinh' only accept floating-point input"); + + return (x < static_cast<genType>(0) ? static_cast<genType>(-1) : (x > static_cast<genType>(0) ? static_cast<genType>(1) : static_cast<genType>(0))) * log(abs(x) + sqrt(static_cast<genType>(1) + x * x)); + } +# endif + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> asinh(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(asinh, v); + } + + // acosh +# if GLM_HAS_CXX11_STL + using std::acosh; +# else + template <typename genType> + GLM_FUNC_QUALIFIER genType acosh(genType const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acosh' only accept floating-point input"); + + if(x < static_cast<genType>(1)) + return static_cast<genType>(0); + return log(x + sqrt(x * x - static_cast<genType>(1))); + } +# endif + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> acosh(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(acosh, v); + } + + // atanh +# if GLM_HAS_CXX11_STL + using std::atanh; +# else + template <typename genType> + GLM_FUNC_QUALIFIER genType atanh(genType const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'atanh' only accept floating-point input"); + + if(abs(x) >= static_cast<genType>(1)) + return 0; + return static_cast<genType>(0.5) * log((static_cast<genType>(1) + x) / (static_cast<genType>(1) - x)); + } +# endif + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> atanh(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(atanh, v); + } +}//namespace glm diff --git a/extensions/common/glm/detail/func_vector_relational.hpp b/extensions/common/glm/detail/func_vector_relational.hpp new file mode 100644 index 0000000000..dca585026c --- /dev/null +++ b/extensions/common/glm/detail/func_vector_relational.hpp @@ -0,0 +1,140 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_vector_relational.hpp +/// @date 2008-08-03 / 2011-06-15 +/// @author Christophe Riccio +/// +/// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> +/// +/// @defgroup core_func_vector_relational Vector Relational Functions +/// @ingroup core +/// +/// Relational and equality operators (<, <=, >, >=, ==, !=) are defined to +/// operate on scalars and produce scalar Boolean results. For vector results, +/// use the following built-in functions. +/// +/// In all cases, the sizes of all the input and return vectors for any particular +/// call must match. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "precision.hpp" +#include "setup.hpp" + +namespace glm +{ + /// @addtogroup core_func_vector_relational + /// @{ + + /// Returns the component-wise comparison result of x < y. + /// + /// @tparam vecType Floating-point or integer vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/lessThan.xml">GLSL lessThan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> lessThan(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Returns the component-wise comparison of result x <= y. + /// + /// @tparam vecType Floating-point or integer vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/lessThanEqual.xml">GLSL lessThanEqual man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> lessThanEqual(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Returns the component-wise comparison of result x > y. + /// + /// @tparam vecType Floating-point or integer vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/greaterThan.xml">GLSL greaterThan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> greaterThan(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Returns the component-wise comparison of result x >= y. + /// + /// @tparam vecType Floating-point or integer vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/greaterThanEqual.xml">GLSL greaterThanEqual man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> greaterThanEqual(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Returns the component-wise comparison of result x == y. + /// + /// @tparam vecType Floating-point, integer or boolean vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/equal.xml">GLSL equal man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> equal(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Returns the component-wise comparison of result x != y. + /// + /// @tparam vecType Floating-point, integer or boolean vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/notEqual.xml">GLSL notEqual man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> notEqual(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Returns true if any component of x is true. + /// + /// @tparam vecType Boolean vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/any.xml">GLSL any man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL bool any(vecType<bool, P> const & v); + + /// Returns true if all components of x are true. + /// + /// @tparam vecType Boolean vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/all.xml">GLSL all man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL bool all(vecType<bool, P> const & v); + + /// Returns the component-wise logical complement of x. + /// /!\ Because of language incompatibilities between C++ and GLSL, GLM defines the function not but not_ instead. + /// + /// @tparam vecType Boolean vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/not.xml">GLSL not man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.7 Vector Relational Functions</a> + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> not_(vecType<bool, P> const & v); + + /// @} +}//namespace glm + +#include "func_vector_relational.inl" diff --git a/extensions/common/glm/detail/func_vector_relational.inl b/extensions/common/glm/detail/func_vector_relational.inl new file mode 100644 index 0000000000..ac88c49702 --- /dev/null +++ b/extensions/common/glm/detail/func_vector_relational.inl @@ -0,0 +1,131 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/func_vector_relational.inl +/// @date 2008-08-03 / 2011-09-09 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include <limits> + +namespace glm +{ + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> lessThan(vecType<T, P> const & x, vecType<T, P> const & y) + { + assert(detail::component_count(x) == detail::component_count(y)); + + vecType<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] < y[i]; + + return Result; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> lessThanEqual(vecType<T, P> const & x, vecType<T, P> const & y) + { + assert(detail::component_count(x) == detail::component_count(y)); + + vecType<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] <= y[i]; + return Result; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> greaterThan(vecType<T, P> const & x, vecType<T, P> const & y) + { + assert(detail::component_count(x) == detail::component_count(y)); + + vecType<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] > y[i]; + return Result; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> greaterThanEqual(vecType<T, P> const & x, vecType<T, P> const & y) + { + assert(detail::component_count(x) == detail::component_count(y)); + + vecType<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] >= y[i]; + return Result; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> equal(vecType<T, P> const & x, vecType<T, P> const & y) + { + assert(detail::component_count(x) == detail::component_count(y)); + + vecType<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] == y[i]; + return Result; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> notEqual(vecType<T, P> const & x, vecType<T, P> const & y) + { + assert(detail::component_count(x) == detail::component_count(y)); + + vecType<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] != y[i]; + return Result; + } + + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER bool any(vecType<bool, P> const & v) + { + bool Result = false; + for(detail::component_count_t i = 0; i < detail::component_count(v); ++i) + Result = Result || v[i]; + return Result; + } + + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER bool all(vecType<bool, P> const & v) + { + bool Result = true; + for(detail::component_count_t i = 0; i < detail::component_count(v); ++i) + Result = Result && v[i]; + return Result; + } + + template <precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> not_(vecType<bool, P> const & v) + { + vecType<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(v); ++i) + Result[i] = !v[i]; + return Result; + } +}//namespace glm + diff --git a/extensions/common/glm/detail/glm.cpp b/extensions/common/glm/detail/glm.cpp new file mode 100644 index 0000000000..21a705efd3 --- /dev/null +++ b/extensions/common/glm/detail/glm.cpp @@ -0,0 +1,286 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/glm.cpp +/// @date 2013-04-22 / 2013-04-22 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include <glm/glm.hpp> +#include <glm/gtc/quaternion.hpp> +#include <glm/gtx/dual_quaternion.hpp> + +namespace glm +{ +// tvec1 type explicit instantiation +template struct tvec1<uint8, lowp>; +template struct tvec1<uint16, lowp>; +template struct tvec1<uint32, lowp>; +template struct tvec1<uint64, lowp>; +template struct tvec1<int8, lowp>; +template struct tvec1<int16, lowp>; +template struct tvec1<int32, lowp>; +template struct tvec1<int64, lowp>; +template struct tvec1<float32, lowp>; +template struct tvec1<float64, lowp>; + +template struct tvec1<uint8, mediump>; +template struct tvec1<uint16, mediump>; +template struct tvec1<uint32, mediump>; +template struct tvec1<uint64, mediump>; +template struct tvec1<int8, mediump>; +template struct tvec1<int16, mediump>; +template struct tvec1<int32, mediump>; +template struct tvec1<int64, mediump>; +template struct tvec1<float32, mediump>; +template struct tvec1<float64, mediump>; + +template struct tvec1<uint8, highp>; +template struct tvec1<uint16, highp>; +template struct tvec1<uint32, highp>; +template struct tvec1<uint64, highp>; +template struct tvec1<int8, highp>; +template struct tvec1<int16, highp>; +template struct tvec1<int32, highp>; +template struct tvec1<int64, highp>; +template struct tvec1<float32, highp>; +template struct tvec1<float64, highp>; + +// tvec2 type explicit instantiation +template struct tvec2<uint8, lowp>; +template struct tvec2<uint16, lowp>; +template struct tvec2<uint32, lowp>; +template struct tvec2<uint64, lowp>; +template struct tvec2<int8, lowp>; +template struct tvec2<int16, lowp>; +template struct tvec2<int32, lowp>; +template struct tvec2<int64, lowp>; +template struct tvec2<float32, lowp>; +template struct tvec2<float64, lowp>; + +template struct tvec2<uint8, mediump>; +template struct tvec2<uint16, mediump>; +template struct tvec2<uint32, mediump>; +template struct tvec2<uint64, mediump>; +template struct tvec2<int8, mediump>; +template struct tvec2<int16, mediump>; +template struct tvec2<int32, mediump>; +template struct tvec2<int64, mediump>; +template struct tvec2<float32, mediump>; +template struct tvec2<float64, mediump>; + +template struct tvec2<uint8, highp>; +template struct tvec2<uint16, highp>; +template struct tvec2<uint32, highp>; +template struct tvec2<uint64, highp>; +template struct tvec2<int8, highp>; +template struct tvec2<int16, highp>; +template struct tvec2<int32, highp>; +template struct tvec2<int64, highp>; +template struct tvec2<float32, highp>; +template struct tvec2<float64, highp>; + +// tvec3 type explicit instantiation +template struct tvec3<uint8, lowp>; +template struct tvec3<uint16, lowp>; +template struct tvec3<uint32, lowp>; +template struct tvec3<uint64, lowp>; +template struct tvec3<int8, lowp>; +template struct tvec3<int16, lowp>; +template struct tvec3<int32, lowp>; +template struct tvec3<int64, lowp>; +template struct tvec3<float32, lowp>; +template struct tvec3<float64, lowp>; + +template struct tvec3<uint8, mediump>; +template struct tvec3<uint16, mediump>; +template struct tvec3<uint32, mediump>; +template struct tvec3<uint64, mediump>; +template struct tvec3<int8, mediump>; +template struct tvec3<int16, mediump>; +template struct tvec3<int32, mediump>; +template struct tvec3<int64, mediump>; +template struct tvec3<float32, mediump>; +template struct tvec3<float64, mediump>; + +template struct tvec3<uint8, highp>; +template struct tvec3<uint16, highp>; +template struct tvec3<uint32, highp>; +template struct tvec3<uint64, highp>; +template struct tvec3<int8, highp>; +template struct tvec3<int16, highp>; +template struct tvec3<int32, highp>; +template struct tvec3<int64, highp>; +template struct tvec3<float32, highp>; +template struct tvec3<float64, highp>; + +// tvec4 type explicit instantiation +template struct tvec4<uint8, lowp>; +template struct tvec4<uint16, lowp>; +template struct tvec4<uint32, lowp>; +template struct tvec4<uint64, lowp>; +template struct tvec4<int8, lowp>; +template struct tvec4<int16, lowp>; +template struct tvec4<int32, lowp>; +template struct tvec4<int64, lowp>; +template struct tvec4<float32, lowp>; +template struct tvec4<float64, lowp>; + +template struct tvec4<uint8, mediump>; +template struct tvec4<uint16, mediump>; +template struct tvec4<uint32, mediump>; +template struct tvec4<uint64, mediump>; +template struct tvec4<int8, mediump>; +template struct tvec4<int16, mediump>; +template struct tvec4<int32, mediump>; +template struct tvec4<int64, mediump>; +template struct tvec4<float32, mediump>; +template struct tvec4<float64, mediump>; + +template struct tvec4<uint8, highp>; +template struct tvec4<uint16, highp>; +template struct tvec4<uint32, highp>; +template struct tvec4<uint64, highp>; +template struct tvec4<int8, highp>; +template struct tvec4<int16, highp>; +template struct tvec4<int32, highp>; +template struct tvec4<int64, highp>; +template struct tvec4<float32, highp>; +template struct tvec4<float64, highp>; + +// tmat2x2 type explicit instantiation +template struct tmat2x2<float32, lowp>; +template struct tmat2x2<float64, lowp>; + +template struct tmat2x2<float32, mediump>; +template struct tmat2x2<float64, mediump>; + +template struct tmat2x2<float32, highp>; +template struct tmat2x2<float64, highp>; + +// tmat2x3 type explicit instantiation +template struct tmat2x3<float32, lowp>; +template struct tmat2x3<float64, lowp>; + +template struct tmat2x3<float32, mediump>; +template struct tmat2x3<float64, mediump>; + +template struct tmat2x3<float32, highp>; +template struct tmat2x3<float64, highp>; + +// tmat2x4 type explicit instantiation +template struct tmat2x4<float32, lowp>; +template struct tmat2x4<float64, lowp>; + +template struct tmat2x4<float32, mediump>; +template struct tmat2x4<float64, mediump>; + +template struct tmat2x4<float32, highp>; +template struct tmat2x4<float64, highp>; + +// tmat3x2 type explicit instantiation +template struct tmat3x2<float32, lowp>; +template struct tmat3x2<float64, lowp>; + +template struct tmat3x2<float32, mediump>; +template struct tmat3x2<float64, mediump>; + +template struct tmat3x2<float32, highp>; +template struct tmat3x2<float64, highp>; + +// tmat3x3 type explicit instantiation +template struct tmat3x3<float32, lowp>; +template struct tmat3x3<float64, lowp>; + +template struct tmat3x3<float32, mediump>; +template struct tmat3x3<float64, mediump>; + +template struct tmat3x3<float32, highp>; +template struct tmat3x3<float64, highp>; + +// tmat3x4 type explicit instantiation +template struct tmat3x4<float32, lowp>; +template struct tmat3x4<float64, lowp>; + +template struct tmat3x4<float32, mediump>; +template struct tmat3x4<float64, mediump>; + +template struct tmat3x4<float32, highp>; +template struct tmat3x4<float64, highp>; + +// tmat4x2 type explicit instantiation +template struct tmat4x2<float32, lowp>; +template struct tmat4x2<float64, lowp>; + +template struct tmat4x2<float32, mediump>; +template struct tmat4x2<float64, mediump>; + +template struct tmat4x2<float32, highp>; +template struct tmat4x2<float64, highp>; + +// tmat4x3 type explicit instantiation +template struct tmat4x3<float32, lowp>; +template struct tmat4x3<float64, lowp>; + +template struct tmat4x3<float32, mediump>; +template struct tmat4x3<float64, mediump>; + +template struct tmat4x3<float32, highp>; +template struct tmat4x3<float64, highp>; + +// tmat4x4 type explicit instantiation +template struct tmat4x4<float32, lowp>; +template struct tmat4x4<float64, lowp>; + +template struct tmat4x4<float32, mediump>; +template struct tmat4x4<float64, mediump>; + +template struct tmat4x4<float32, highp>; +template struct tmat4x4<float64, highp>; + +// tquat type explicit instantiation +template struct tquat<float32, lowp>; +template struct tquat<float64, lowp>; + +template struct tquat<float32, mediump>; +template struct tquat<float64, mediump>; + +template struct tquat<float32, highp>; +template struct tquat<float64, highp>; + +//tdualquat type explicit instantiation +template struct tdualquat<float32, lowp>; +template struct tdualquat<float64, lowp>; + +template struct tdualquat<float32, mediump>; +template struct tdualquat<float64, mediump>; + +template struct tdualquat<float32, highp>; +template struct tdualquat<float64, highp>; + +}//namespace glm + diff --git a/extensions/common/glm/detail/intrinsic_common.hpp b/extensions/common/glm/detail/intrinsic_common.hpp new file mode 100644 index 0000000000..4ed9b4c8a5 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_common.hpp @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_common.hpp +/// @date 2009-05-11 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" + +#if(!(GLM_ARCH & GLM_ARCH_SSE2)) +# error "SSE2 instructions not supported or enabled" +#else + +namespace glm{ +namespace detail +{ + __m128 sse_abs_ps(__m128 x); + + __m128 sse_sgn_ps(__m128 x); + + //floor + __m128 sse_flr_ps(__m128 v); + + //trunc + __m128 sse_trc_ps(__m128 v); + + //round + __m128 sse_nd_ps(__m128 v); + + //roundEven + __m128 sse_rde_ps(__m128 v); + + __m128 sse_rnd_ps(__m128 x); + + __m128 sse_ceil_ps(__m128 v); + + __m128 sse_frc_ps(__m128 x); + + __m128 sse_mod_ps(__m128 x, __m128 y); + + __m128 sse_modf_ps(__m128 x, __m128i & i); + + //GLM_FUNC_QUALIFIER __m128 sse_min_ps(__m128 x, __m128 y) + + //GLM_FUNC_QUALIFIER __m128 sse_max_ps(__m128 x, __m128 y) + + __m128 sse_clp_ps(__m128 v, __m128 minVal, __m128 maxVal); + + __m128 sse_mix_ps(__m128 v1, __m128 v2, __m128 a); + + __m128 sse_stp_ps(__m128 edge, __m128 x); + + __m128 sse_ssp_ps(__m128 edge0, __m128 edge1, __m128 x); + + __m128 sse_nan_ps(__m128 x); + + __m128 sse_inf_ps(__m128 x); + +}//namespace detail +}//namespace glm + +#include "intrinsic_common.inl" + +#endif//GLM_ARCH diff --git a/extensions/common/glm/detail/intrinsic_common.inl b/extensions/common/glm/detail/intrinsic_common.inl new file mode 100644 index 0000000000..2c2f5d0f95 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_common.inl @@ -0,0 +1,313 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_common.inl +/// @date 2009-05-08 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail{ + +#if(GLM_COMPILER & GLM_COMPILER_VC) +#pragma warning(push) +#pragma warning(disable : 4510 4512 4610) +#endif + + union ieee754_QNAN + { + const float f; + struct i + { + const unsigned int mantissa:23, exp:8, sign:1; + }; + + ieee754_QNAN() : f(0.0)/*, mantissa(0x7FFFFF), exp(0xFF), sign(0x0)*/ {} + }; + +#if(GLM_COMPILER & GLM_COMPILER_VC) +#pragma warning(pop) +#endif + + static const __m128 GLM_VAR_USED zero = _mm_setzero_ps(); + static const __m128 GLM_VAR_USED one = _mm_set_ps1(1.0f); + static const __m128 GLM_VAR_USED minus_one = _mm_set_ps1(-1.0f); + static const __m128 GLM_VAR_USED two = _mm_set_ps1(2.0f); + static const __m128 GLM_VAR_USED three = _mm_set_ps1(3.0f); + static const __m128 GLM_VAR_USED pi = _mm_set_ps1(3.1415926535897932384626433832795f); + static const __m128 GLM_VAR_USED hundred_eighty = _mm_set_ps1(180.f); + static const __m128 GLM_VAR_USED pi_over_hundred_eighty = _mm_set_ps1(0.017453292519943295769236907684886f); + static const __m128 GLM_VAR_USED hundred_eighty_over_pi = _mm_set_ps1(57.295779513082320876798154814105f); + + static const ieee754_QNAN absMask; + static const __m128 GLM_VAR_USED abs4Mask = _mm_set_ps1(absMask.f); + + static const __m128 GLM_VAR_USED _epi32_sign_mask = _mm_castsi128_ps(_mm_set1_epi32(static_cast<int>(0x80000000))); + //static const __m128 GLM_VAR_USED _epi32_inv_sign_mask = _mm_castsi128_ps(_mm_set1_epi32(0x7FFFFFFF)); + //static const __m128 GLM_VAR_USED _epi32_mant_mask = _mm_castsi128_ps(_mm_set1_epi32(0x7F800000)); + //static const __m128 GLM_VAR_USED _epi32_inv_mant_mask = _mm_castsi128_ps(_mm_set1_epi32(0x807FFFFF)); + //static const __m128 GLM_VAR_USED _epi32_min_norm_pos = _mm_castsi128_ps(_mm_set1_epi32(0x00800000)); + static const __m128 GLM_VAR_USED _epi32_0 = _mm_set_ps1(0); + static const __m128 GLM_VAR_USED _epi32_1 = _mm_set_ps1(1); + static const __m128 GLM_VAR_USED _epi32_2 = _mm_set_ps1(2); + static const __m128 GLM_VAR_USED _epi32_3 = _mm_set_ps1(3); + static const __m128 GLM_VAR_USED _epi32_4 = _mm_set_ps1(4); + static const __m128 GLM_VAR_USED _epi32_5 = _mm_set_ps1(5); + static const __m128 GLM_VAR_USED _epi32_6 = _mm_set_ps1(6); + static const __m128 GLM_VAR_USED _epi32_7 = _mm_set_ps1(7); + static const __m128 GLM_VAR_USED _epi32_8 = _mm_set_ps1(8); + static const __m128 GLM_VAR_USED _epi32_9 = _mm_set_ps1(9); + static const __m128 GLM_VAR_USED _epi32_127 = _mm_set_ps1(127); + //static const __m128 GLM_VAR_USED _epi32_ninf = _mm_castsi128_ps(_mm_set1_epi32(0xFF800000)); + //static const __m128 GLM_VAR_USED _epi32_pinf = _mm_castsi128_ps(_mm_set1_epi32(0x7F800000)); + + static const __m128 GLM_VAR_USED _ps_1_3 = _mm_set_ps1(0.33333333333333333333333333333333f); + static const __m128 GLM_VAR_USED _ps_0p5 = _mm_set_ps1(0.5f); + static const __m128 GLM_VAR_USED _ps_1 = _mm_set_ps1(1.0f); + static const __m128 GLM_VAR_USED _ps_m1 = _mm_set_ps1(-1.0f); + static const __m128 GLM_VAR_USED _ps_2 = _mm_set_ps1(2.0f); + static const __m128 GLM_VAR_USED _ps_3 = _mm_set_ps1(3.0f); + static const __m128 GLM_VAR_USED _ps_127 = _mm_set_ps1(127.0f); + static const __m128 GLM_VAR_USED _ps_255 = _mm_set_ps1(255.0f); + static const __m128 GLM_VAR_USED _ps_2pow23 = _mm_set_ps1(8388608.0f); + + static const __m128 GLM_VAR_USED _ps_1_0_0_0 = _mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f); + static const __m128 GLM_VAR_USED _ps_0_1_0_0 = _mm_set_ps(0.0f, 1.0f, 0.0f, 0.0f); + static const __m128 GLM_VAR_USED _ps_0_0_1_0 = _mm_set_ps(0.0f, 0.0f, 1.0f, 0.0f); + static const __m128 GLM_VAR_USED _ps_0_0_0_1 = _mm_set_ps(0.0f, 0.0f, 0.0f, 1.0f); + + static const __m128 GLM_VAR_USED _ps_pi = _mm_set_ps1(3.1415926535897932384626433832795f); + static const __m128 GLM_VAR_USED _ps_pi2 = _mm_set_ps1(6.283185307179586476925286766560f); + static const __m128 GLM_VAR_USED _ps_2_pi = _mm_set_ps1(0.63661977236758134307553505349006f); + static const __m128 GLM_VAR_USED _ps_pi_2 = _mm_set_ps1(1.5707963267948966192313216916398f); + static const __m128 GLM_VAR_USED _ps_4_pi = _mm_set_ps1(1.2732395447351626861510701069801f); + static const __m128 GLM_VAR_USED _ps_pi_4 = _mm_set_ps1(0.78539816339744830961566084581988f); + + static const __m128 GLM_VAR_USED _ps_sincos_p0 = _mm_set_ps1(0.15707963267948963959e1f); + static const __m128 GLM_VAR_USED _ps_sincos_p1 = _mm_set_ps1(-0.64596409750621907082e0f); + static const __m128 GLM_VAR_USED _ps_sincos_p2 = _mm_set_ps1(0.7969262624561800806e-1f); + static const __m128 GLM_VAR_USED _ps_sincos_p3 = _mm_set_ps1(-0.468175413106023168e-2f); + static const __m128 GLM_VAR_USED _ps_tan_p0 = _mm_set_ps1(-1.79565251976484877988e7f); + static const __m128 GLM_VAR_USED _ps_tan_p1 = _mm_set_ps1(1.15351664838587416140e6f); + static const __m128 GLM_VAR_USED _ps_tan_p2 = _mm_set_ps1(-1.30936939181383777646e4f); + static const __m128 GLM_VAR_USED _ps_tan_q0 = _mm_set_ps1(-5.38695755929454629881e7f); + static const __m128 GLM_VAR_USED _ps_tan_q1 = _mm_set_ps1(2.50083801823357915839e7f); + static const __m128 GLM_VAR_USED _ps_tan_q2 = _mm_set_ps1(-1.32089234440210967447e6f); + static const __m128 GLM_VAR_USED _ps_tan_q3 = _mm_set_ps1(1.36812963470692954678e4f); + static const __m128 GLM_VAR_USED _ps_tan_poleval = _mm_set_ps1(3.68935e19f); + static const __m128 GLM_VAR_USED _ps_atan_t0 = _mm_set_ps1(-0.91646118527267623468e-1f); + static const __m128 GLM_VAR_USED _ps_atan_t1 = _mm_set_ps1(-0.13956945682312098640e1f); + static const __m128 GLM_VAR_USED _ps_atan_t2 = _mm_set_ps1(-0.94393926122725531747e2f); + static const __m128 GLM_VAR_USED _ps_atan_t3 = _mm_set_ps1(0.12888383034157279340e2f); + static const __m128 GLM_VAR_USED _ps_atan_s0 = _mm_set_ps1(0.12797564625607904396e1f); + static const __m128 GLM_VAR_USED _ps_atan_s1 = _mm_set_ps1(0.21972168858277355914e1f); + static const __m128 GLM_VAR_USED _ps_atan_s2 = _mm_set_ps1(0.68193064729268275701e1f); + static const __m128 GLM_VAR_USED _ps_atan_s3 = _mm_set_ps1(0.28205206687035841409e2f); + + static const __m128 GLM_VAR_USED _ps_exp_hi = _mm_set_ps1(88.3762626647949f); + static const __m128 GLM_VAR_USED _ps_exp_lo = _mm_set_ps1(-88.3762626647949f); + static const __m128 GLM_VAR_USED _ps_exp_rln2 = _mm_set_ps1(1.4426950408889634073599f); + static const __m128 GLM_VAR_USED _ps_exp_p0 = _mm_set_ps1(1.26177193074810590878e-4f); + static const __m128 GLM_VAR_USED _ps_exp_p1 = _mm_set_ps1(3.02994407707441961300e-2f); + static const __m128 GLM_VAR_USED _ps_exp_q0 = _mm_set_ps1(3.00198505138664455042e-6f); + static const __m128 GLM_VAR_USED _ps_exp_q1 = _mm_set_ps1(2.52448340349684104192e-3f); + static const __m128 GLM_VAR_USED _ps_exp_q2 = _mm_set_ps1(2.27265548208155028766e-1f); + static const __m128 GLM_VAR_USED _ps_exp_q3 = _mm_set_ps1(2.00000000000000000009e0f); + static const __m128 GLM_VAR_USED _ps_exp_c1 = _mm_set_ps1(6.93145751953125e-1f); + static const __m128 GLM_VAR_USED _ps_exp_c2 = _mm_set_ps1(1.42860682030941723212e-6f); + static const __m128 GLM_VAR_USED _ps_exp2_hi = _mm_set_ps1(127.4999961853f); + static const __m128 GLM_VAR_USED _ps_exp2_lo = _mm_set_ps1(-127.4999961853f); + static const __m128 GLM_VAR_USED _ps_exp2_p0 = _mm_set_ps1(2.30933477057345225087e-2f); + static const __m128 GLM_VAR_USED _ps_exp2_p1 = _mm_set_ps1(2.02020656693165307700e1f); + static const __m128 GLM_VAR_USED _ps_exp2_p2 = _mm_set_ps1(1.51390680115615096133e3f); + static const __m128 GLM_VAR_USED _ps_exp2_q0 = _mm_set_ps1(2.33184211722314911771e2f); + static const __m128 GLM_VAR_USED _ps_exp2_q1 = _mm_set_ps1(4.36821166879210612817e3f); + static const __m128 GLM_VAR_USED _ps_log_p0 = _mm_set_ps1(-7.89580278884799154124e-1f); + static const __m128 GLM_VAR_USED _ps_log_p1 = _mm_set_ps1(1.63866645699558079767e1f); + static const __m128 GLM_VAR_USED _ps_log_p2 = _mm_set_ps1(-6.41409952958715622951e1f); + static const __m128 GLM_VAR_USED _ps_log_q0 = _mm_set_ps1(-3.56722798256324312549e1f); + static const __m128 GLM_VAR_USED _ps_log_q1 = _mm_set_ps1(3.12093766372244180303e2f); + static const __m128 GLM_VAR_USED _ps_log_q2 = _mm_set_ps1(-7.69691943550460008604e2f); + static const __m128 GLM_VAR_USED _ps_log_c0 = _mm_set_ps1(0.693147180559945f); + static const __m128 GLM_VAR_USED _ps_log2_c0 = _mm_set_ps1(1.44269504088896340735992f); + +GLM_FUNC_QUALIFIER __m128 sse_abs_ps(__m128 x) +{ + return _mm_and_ps(glm::detail::abs4Mask, x); +} + +GLM_FUNC_QUALIFIER __m128 sse_sgn_ps(__m128 x) +{ + __m128 Neg = _mm_set1_ps(-1.0f); + __m128 Pos = _mm_set1_ps(1.0f); + + __m128 Cmp0 = _mm_cmplt_ps(x, zero); + __m128 Cmp1 = _mm_cmpgt_ps(x, zero); + + __m128 And0 = _mm_and_ps(Cmp0, Neg); + __m128 And1 = _mm_and_ps(Cmp1, Pos); + + return _mm_or_ps(And0, And1); +} + +//floor +GLM_FUNC_QUALIFIER __m128 sse_flr_ps(__m128 x) +{ + __m128 rnd0 = sse_rnd_ps(x); + __m128 cmp0 = _mm_cmplt_ps(x, rnd0); + __m128 and0 = _mm_and_ps(cmp0, glm::detail::_ps_1); + __m128 sub0 = _mm_sub_ps(rnd0, and0); + return sub0; +} + +//trunc +/* +GLM_FUNC_QUALIFIER __m128 _mm_trc_ps(__m128 v) +{ + return __m128(); +} +*/ +//round +GLM_FUNC_QUALIFIER __m128 sse_rnd_ps(__m128 x) +{ + __m128 and0 = _mm_and_ps(glm::detail::_epi32_sign_mask, x); + __m128 or0 = _mm_or_ps(and0, glm::detail::_ps_2pow23); + __m128 add0 = _mm_add_ps(x, or0); + __m128 sub0 = _mm_sub_ps(add0, or0); + return sub0; +} + +//roundEven +GLM_FUNC_QUALIFIER __m128 sse_rde_ps(__m128 x) +{ + __m128 and0 = _mm_and_ps(glm::detail::_epi32_sign_mask, x); + __m128 or0 = _mm_or_ps(and0, glm::detail::_ps_2pow23); + __m128 add0 = _mm_add_ps(x, or0); + __m128 sub0 = _mm_sub_ps(add0, or0); + return sub0; +} + +GLM_FUNC_QUALIFIER __m128 sse_ceil_ps(__m128 x) +{ + __m128 rnd0 = sse_rnd_ps(x); + __m128 cmp0 = _mm_cmpgt_ps(x, rnd0); + __m128 and0 = _mm_and_ps(cmp0, glm::detail::_ps_1); + __m128 add0 = _mm_add_ps(rnd0, and0); + return add0; +} + +GLM_FUNC_QUALIFIER __m128 sse_frc_ps(__m128 x) +{ + __m128 flr0 = sse_flr_ps(x); + __m128 sub0 = _mm_sub_ps(x, flr0); + return sub0; +} + +GLM_FUNC_QUALIFIER __m128 sse_mod_ps(__m128 x, __m128 y) +{ + __m128 div0 = _mm_div_ps(x, y); + __m128 flr0 = sse_flr_ps(div0); + __m128 mul0 = _mm_mul_ps(y, flr0); + __m128 sub0 = _mm_sub_ps(x, mul0); + return sub0; +} + +/// TODO +/* +GLM_FUNC_QUALIFIER __m128 sse_modf_ps(__m128 x, __m128i & i) +{ + __m128 empty; + return empty; +} +*/ + +//GLM_FUNC_QUALIFIER __m128 _mm_min_ps(__m128 x, __m128 y) + +//GLM_FUNC_QUALIFIER __m128 _mm_max_ps(__m128 x, __m128 y) + +GLM_FUNC_QUALIFIER __m128 sse_clp_ps(__m128 v, __m128 minVal, __m128 maxVal) +{ + __m128 min0 = _mm_min_ps(v, maxVal); + __m128 max0 = _mm_max_ps(min0, minVal); + return max0; +} + +GLM_FUNC_QUALIFIER __m128 sse_mix_ps(__m128 v1, __m128 v2, __m128 a) +{ + __m128 sub0 = _mm_sub_ps(glm::detail::one, a); + __m128 mul0 = _mm_mul_ps(v1, sub0); + __m128 mul1 = _mm_mul_ps(v2, a); + __m128 add0 = _mm_add_ps(mul0, mul1); + return add0; +} + +GLM_FUNC_QUALIFIER __m128 sse_stp_ps(__m128 edge, __m128 x) +{ + __m128 cmp = _mm_cmple_ps(x, edge); + if(_mm_movemask_ps(cmp) == 0) + return glm::detail::one; + else + return glm::detail::zero; +} + +GLM_FUNC_QUALIFIER __m128 sse_ssp_ps(__m128 edge0, __m128 edge1, __m128 x) +{ + __m128 sub0 = _mm_sub_ps(x, edge0); + __m128 sub1 = _mm_sub_ps(edge1, edge0); + __m128 div0 = _mm_sub_ps(sub0, sub1); + __m128 clp0 = sse_clp_ps(div0, glm::detail::zero, glm::detail::one); + __m128 mul0 = _mm_mul_ps(glm::detail::two, clp0); + __m128 sub2 = _mm_sub_ps(glm::detail::three, mul0); + __m128 mul1 = _mm_mul_ps(clp0, clp0); + __m128 mul2 = _mm_mul_ps(mul1, sub2); + return mul2; +} + +/// \todo +//GLM_FUNC_QUALIFIER __m128 sse_nan_ps(__m128 x) +//{ +// __m128 empty; +// return empty; +//} + +/// \todo +//GLM_FUNC_QUALIFIER __m128 sse_inf_ps(__m128 x) +//{ +// __m128 empty; +// return empty; +//} + +// SSE scalar reciprocal sqrt using rsqrt op, plus one Newton-Rhaphson iteration +// By Elan Ruskin, http://assemblyrequired.crashworks.org/ +GLM_FUNC_QUALIFIER __m128 sse_sqrt_wip_ss(__m128 const & x) +{ + __m128 const recip = _mm_rsqrt_ss(x); // "estimate" opcode + __m128 const half = _mm_set_ps1(0.5f); + __m128 const halfrecip = _mm_mul_ss(half, recip); + __m128 const threeminus_xrr = _mm_sub_ss(three, _mm_mul_ss(x, _mm_mul_ss (recip, recip))); + return _mm_mul_ss(halfrecip, threeminus_xrr); +} + +}//namespace detail +}//namespace glms + diff --git a/extensions/common/glm/detail/intrinsic_exponential.hpp b/extensions/common/glm/detail/intrinsic_exponential.hpp new file mode 100644 index 0000000000..25faffec80 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_exponential.hpp @@ -0,0 +1,77 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_exponential.hpp +/// @date 2009-05-11 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" + +#if(!(GLM_ARCH & GLM_ARCH_SSE2)) +# error "SSE2 instructions not supported or enabled" +#else + +namespace glm{ +namespace detail +{ +/* +GLM_FUNC_QUALIFIER __m128 sse_rsqrt_nr_ss(__m128 const x) +{ + __m128 recip = _mm_rsqrt_ss( x ); // "estimate" opcode + const static __m128 three = { 3, 3, 3, 3 }; // aligned consts for fast load + const static __m128 half = { 0.5,0.5,0.5,0.5 }; + __m128 halfrecip = _mm_mul_ss( half, recip ); + __m128 threeminus_xrr = _mm_sub_ss( three, _mm_mul_ss( x, _mm_mul_ss ( recip, recip ) ) ); + return _mm_mul_ss( halfrecip, threeminus_xrr ); +} + +GLM_FUNC_QUALIFIER __m128 sse_normalize_fast_ps( float * RESTRICT vOut, float * RESTRICT vIn ) +{ + __m128 x = _mm_load_ss(&vIn[0]); + __m128 y = _mm_load_ss(&vIn[1]); + __m128 z = _mm_load_ss(&vIn[2]); + + const __m128 l = // compute x*x + y*y + z*z + _mm_add_ss( + _mm_add_ss( _mm_mul_ss(x,x), + _mm_mul_ss(y,y) + ), + _mm_mul_ss( z, z ) + ); + + + const __m128 rsqt = _mm_rsqrt_nr_ss( l ); + _mm_store_ss( &vOut[0] , _mm_mul_ss( rsqt, x ) ); + _mm_store_ss( &vOut[1] , _mm_mul_ss( rsqt, y ) ); + _mm_store_ss( &vOut[2] , _mm_mul_ss( rsqt, z ) ); + + return _mm_mul_ss( l , rsqt ); +} +*/ +}//namespace detail +}//namespace glm + +#endif//GLM_ARCH diff --git a/extensions/common/glm/detail/intrinsic_exponential.inl b/extensions/common/glm/detail/intrinsic_exponential.inl new file mode 100644 index 0000000000..76d4a193d5 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_exponential.inl @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_exponential.inl +/// @date 2011-06-15 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// diff --git a/extensions/common/glm/detail/intrinsic_geometric.hpp b/extensions/common/glm/detail/intrinsic_geometric.hpp new file mode 100644 index 0000000000..5e442d44e6 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_geometric.hpp @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_geometric.hpp +/// @date 2009-05-08 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" + +#if(!(GLM_ARCH & GLM_ARCH_SSE2)) +# error "SSE2 instructions not supported or enabled" +#else + +#include "intrinsic_common.hpp" + +namespace glm{ +namespace detail +{ + //length + __m128 sse_len_ps(__m128 x); + + //distance + __m128 sse_dst_ps(__m128 p0, __m128 p1); + + //dot + __m128 sse_dot_ps(__m128 v1, __m128 v2); + + // SSE1 + __m128 sse_dot_ss(__m128 v1, __m128 v2); + + //cross + __m128 sse_xpd_ps(__m128 v1, __m128 v2); + + //normalize + __m128 sse_nrm_ps(__m128 v); + + //faceforward + __m128 sse_ffd_ps(__m128 N, __m128 I, __m128 Nref); + + //reflect + __m128 sse_rfe_ps(__m128 I, __m128 N); + + //refract + __m128 sse_rfa_ps(__m128 I, __m128 N, __m128 eta); + +}//namespace detail +}//namespace glm + +#include "intrinsic_geometric.inl" + +#endif//GLM_ARCH diff --git a/extensions/common/glm/detail/intrinsic_geometric.inl b/extensions/common/glm/detail/intrinsic_geometric.inl new file mode 100644 index 0000000000..e58d5c4315 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_geometric.inl @@ -0,0 +1,147 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_geometric.inl +/// @date 2009-05-08 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail{ + +//length +GLM_FUNC_QUALIFIER __m128 sse_len_ps(__m128 x) +{ + __m128 dot0 = sse_dot_ps(x, x); + __m128 sqt0 = _mm_sqrt_ps(dot0); + return sqt0; +} + +//distance +GLM_FUNC_QUALIFIER __m128 sse_dst_ps(__m128 p0, __m128 p1) +{ + __m128 sub0 = _mm_sub_ps(p0, p1); + __m128 len0 = sse_len_ps(sub0); + return len0; +} + +//dot +GLM_FUNC_QUALIFIER __m128 sse_dot_ps(__m128 v1, __m128 v2) +{ + +# if(GLM_ARCH & GLM_ARCH_AVX) + return _mm_dp_ps(v1, v2, 0xff); +# else + __m128 mul0 = _mm_mul_ps(v1, v2); + __m128 swp0 = _mm_shuffle_ps(mul0, mul0, _MM_SHUFFLE(2, 3, 0, 1)); + __m128 add0 = _mm_add_ps(mul0, swp0); + __m128 swp1 = _mm_shuffle_ps(add0, add0, _MM_SHUFFLE(0, 1, 2, 3)); + __m128 add1 = _mm_add_ps(add0, swp1); + return add1; +# endif +} + +// SSE1 +GLM_FUNC_QUALIFIER __m128 sse_dot_ss(__m128 v1, __m128 v2) +{ + __m128 mul0 = _mm_mul_ps(v1, v2); + __m128 mov0 = _mm_movehl_ps(mul0, mul0); + __m128 add0 = _mm_add_ps(mov0, mul0); + __m128 swp1 = _mm_shuffle_ps(add0, add0, 1); + __m128 add1 = _mm_add_ss(add0, swp1); + return add1; +} + +//cross +GLM_FUNC_QUALIFIER __m128 sse_xpd_ps(__m128 v1, __m128 v2) +{ + __m128 swp0 = _mm_shuffle_ps(v1, v1, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 swp1 = _mm_shuffle_ps(v1, v1, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 swp2 = _mm_shuffle_ps(v2, v2, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 swp3 = _mm_shuffle_ps(v2, v2, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 mul0 = _mm_mul_ps(swp0, swp3); + __m128 mul1 = _mm_mul_ps(swp1, swp2); + __m128 sub0 = _mm_sub_ps(mul0, mul1); + return sub0; +} + +//normalize +GLM_FUNC_QUALIFIER __m128 sse_nrm_ps(__m128 v) +{ + __m128 dot0 = sse_dot_ps(v, v); + __m128 isr0 = _mm_rsqrt_ps(dot0); + __m128 mul0 = _mm_mul_ps(v, isr0); + return mul0; +} + +//faceforward +GLM_FUNC_QUALIFIER __m128 sse_ffd_ps(__m128 N, __m128 I, __m128 Nref) +{ + //__m128 dot0 = _mm_dot_ps(v, v); + //__m128 neg0 = _mm_neg_ps(N); + //__m128 sgn0 = _mm_sgn_ps(dot0); + //__m128 mix0 = _mm_mix_ps(N, neg0, sgn0); + //return mix0; + + __m128 dot0 = sse_dot_ps(Nref, I); + __m128 sgn0 = sse_sgn_ps(dot0); + __m128 mul0 = _mm_mul_ps(sgn0, glm::detail::minus_one); + __m128 mul1 = _mm_mul_ps(N, mul0); + return mul1; +} + +//reflect +GLM_FUNC_QUALIFIER __m128 sse_rfe_ps(__m128 I, __m128 N) +{ + __m128 dot0 = sse_dot_ps(N, I); + __m128 mul0 = _mm_mul_ps(N, dot0); + __m128 mul1 = _mm_mul_ps(mul0, glm::detail::two); + __m128 sub0 = _mm_sub_ps(I, mul1); + return sub0; +} + +//refract +GLM_FUNC_QUALIFIER __m128 sse_rfa_ps(__m128 I, __m128 N, __m128 eta) +{ + __m128 dot0 = sse_dot_ps(N, I); + __m128 mul0 = _mm_mul_ps(eta, eta); + __m128 mul1 = _mm_mul_ps(dot0, dot0); + __m128 sub0 = _mm_sub_ps(glm::detail::one, mul0); + __m128 sub1 = _mm_sub_ps(glm::detail::one, mul1); + __m128 mul2 = _mm_mul_ps(sub0, sub1); + + if(_mm_movemask_ps(_mm_cmplt_ss(mul2, glm::detail::zero)) == 0) + return glm::detail::zero; + + __m128 sqt0 = _mm_sqrt_ps(mul2); + __m128 mul3 = _mm_mul_ps(eta, dot0); + __m128 add0 = _mm_add_ps(mul3, sqt0); + __m128 mul4 = _mm_mul_ps(add0, N); + __m128 mul5 = _mm_mul_ps(eta, I); + __m128 sub2 = _mm_sub_ps(mul5, mul4); + + return sub2; +} + +}//namespace detail +}//namespace glm diff --git a/extensions/common/glm/detail/intrinsic_integer.hpp b/extensions/common/glm/detail/intrinsic_integer.hpp new file mode 100644 index 0000000000..c1635d36f8 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_integer.hpp @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_integer.hpp +/// @date 2009-05-11 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "glm/glm.hpp" + +#if(!(GLM_ARCH & GLM_ARCH_SSE2)) +# error "SSE2 instructions not supported or enabled" +#else + +namespace glm{ +namespace detail +{ + __m128i _mm_bit_interleave_si128(__m128i x); + __m128i _mm_bit_interleave_si128(__m128i x, __m128i y); + +}//namespace detail +}//namespace glm + +#include "intrinsic_integer.inl" + +#endif//GLM_ARCH diff --git a/extensions/common/glm/detail/intrinsic_integer.inl b/extensions/common/glm/detail/intrinsic_integer.inl new file mode 100644 index 0000000000..1ea96b5917 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_integer.inl @@ -0,0 +1,139 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_integer.inl +/// @date 2009-05-08 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail +{ + inline __m128i _mm_bit_interleave_si128(__m128i x) + { + __m128i const Mask4 = _mm_set1_epi32(0x0000FFFF); + __m128i const Mask3 = _mm_set1_epi32(0x00FF00FF); + __m128i const Mask2 = _mm_set1_epi32(0x0F0F0F0F); + __m128i const Mask1 = _mm_set1_epi32(0x33333333); + __m128i const Mask0 = _mm_set1_epi32(0x55555555); + + __m128i Reg1; + __m128i Reg2; + + // REG1 = x; + // REG2 = y; + //Reg1 = _mm_unpacklo_epi64(x, y); + Reg1 = x; + + //REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFF); + //REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFF); + Reg2 = _mm_slli_si128(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask4); + + //REG1 = ((REG1 << 8) | REG1) & glm::uint64(0x00FF00FF00FF00FF); + //REG2 = ((REG2 << 8) | REG2) & glm::uint64(0x00FF00FF00FF00FF); + Reg2 = _mm_slli_si128(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask3); + + //REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0F); + //REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0F); + Reg2 = _mm_slli_epi32(Reg1, 4); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask2); + + //REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x3333333333333333); + //REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x3333333333333333); + Reg2 = _mm_slli_epi32(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask1); + + //REG1 = ((REG1 << 1) | REG1) & glm::uint64(0x5555555555555555); + //REG2 = ((REG2 << 1) | REG2) & glm::uint64(0x5555555555555555); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask0); + + //return REG1 | (REG2 << 1); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg2 = _mm_srli_si128(Reg2, 8); + Reg1 = _mm_or_si128(Reg1, Reg2); + + return Reg1; + } + + inline __m128i _mm_bit_interleave_si128(__m128i x, __m128i y) + { + __m128i const Mask4 = _mm_set1_epi32(0x0000FFFF); + __m128i const Mask3 = _mm_set1_epi32(0x00FF00FF); + __m128i const Mask2 = _mm_set1_epi32(0x0F0F0F0F); + __m128i const Mask1 = _mm_set1_epi32(0x33333333); + __m128i const Mask0 = _mm_set1_epi32(0x55555555); + + __m128i Reg1; + __m128i Reg2; + + // REG1 = x; + // REG2 = y; + Reg1 = _mm_unpacklo_epi64(x, y); + + //REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFF); + //REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFF); + Reg2 = _mm_slli_si128(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask4); + + //REG1 = ((REG1 << 8) | REG1) & glm::uint64(0x00FF00FF00FF00FF); + //REG2 = ((REG2 << 8) | REG2) & glm::uint64(0x00FF00FF00FF00FF); + Reg2 = _mm_slli_si128(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask3); + + //REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0F); + //REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0F); + Reg2 = _mm_slli_epi32(Reg1, 4); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask2); + + //REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x3333333333333333); + //REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x3333333333333333); + Reg2 = _mm_slli_epi32(Reg1, 2); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask1); + + //REG1 = ((REG1 << 1) | REG1) & glm::uint64(0x5555555555555555); + //REG2 = ((REG2 << 1) | REG2) & glm::uint64(0x5555555555555555); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg1 = _mm_or_si128(Reg2, Reg1); + Reg1 = _mm_and_si128(Reg1, Mask0); + + //return REG1 | (REG2 << 1); + Reg2 = _mm_slli_epi32(Reg1, 1); + Reg2 = _mm_srli_si128(Reg2, 8); + Reg1 = _mm_or_si128(Reg1, Reg2); + + return Reg1; + } +}//namespace detail +}//namespace glms diff --git a/extensions/common/glm/detail/intrinsic_matrix.hpp b/extensions/common/glm/detail/intrinsic_matrix.hpp new file mode 100644 index 0000000000..62e4f74c5a --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_matrix.hpp @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_common.hpp +/// @date 2009-06-05 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" + +#if(!(GLM_ARCH & GLM_ARCH_SSE2)) +# error "SSE2 instructions not supported or enabled" +#else + +#include "intrinsic_geometric.hpp" + +namespace glm{ +namespace detail +{ + void sse_add_ps(__m128 in1[4], __m128 in2[4], __m128 out[4]); + + void sse_sub_ps(__m128 in1[4], __m128 in2[4], __m128 out[4]); + + __m128 sse_mul_ps(__m128 m[4], __m128 v); + + __m128 sse_mul_ps(__m128 v, __m128 m[4]); + + void sse_mul_ps(__m128 const in1[4], __m128 const in2[4], __m128 out[4]); + + void sse_transpose_ps(__m128 const in[4], __m128 out[4]); + + void sse_inverse_ps(__m128 const in[4], __m128 out[4]); + + void sse_rotate_ps(__m128 const in[4], float Angle, float const v[3], __m128 out[4]); + + __m128 sse_det_ps(__m128 const m[4]); + + __m128 sse_slow_det_ps(__m128 const m[4]); + +}//namespace detail +}//namespace glm + +#include "intrinsic_matrix.inl" + +#endif//GLM_ARCH diff --git a/extensions/common/glm/detail/intrinsic_matrix.inl b/extensions/common/glm/detail/intrinsic_matrix.inl new file mode 100644 index 0000000000..7ab6bceed1 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_matrix.inl @@ -0,0 +1,1070 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_common.inl +/// @date 2009-06-05 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail{ + +static const __m128 GLM_VAR_USED _m128_rad_ps = _mm_set_ps1(3.141592653589793238462643383279f / 180.f); +static const __m128 GLM_VAR_USED _m128_deg_ps = _mm_set_ps1(180.f / 3.141592653589793238462643383279f); + +template <typename matType> +GLM_FUNC_QUALIFIER matType sse_comp_mul_ps +( + __m128 const in1[4], + __m128 const in2[4], + __m128 out[4] +) +{ + out[0] = _mm_mul_ps(in1[0], in2[0]); + out[1] = _mm_mul_ps(in1[1], in2[1]); + out[2] = _mm_mul_ps(in1[2], in2[2]); + out[3] = _mm_mul_ps(in1[3], in2[3]); +} + +GLM_FUNC_QUALIFIER void sse_add_ps(__m128 const in1[4], __m128 const in2[4], __m128 out[4]) +{ + { + out[0] = _mm_add_ps(in1[0], in2[0]); + out[1] = _mm_add_ps(in1[1], in2[1]); + out[2] = _mm_add_ps(in1[2], in2[2]); + out[3] = _mm_add_ps(in1[3], in2[3]); + } +} + +GLM_FUNC_QUALIFIER void sse_sub_ps(__m128 const in1[4], __m128 const in2[4], __m128 out[4]) +{ + { + out[0] = _mm_sub_ps(in1[0], in2[0]); + out[1] = _mm_sub_ps(in1[1], in2[1]); + out[2] = _mm_sub_ps(in1[2], in2[2]); + out[3] = _mm_sub_ps(in1[3], in2[3]); + } +} + +GLM_FUNC_QUALIFIER __m128 sse_mul_ps(__m128 const m[4], __m128 v) +{ + __m128 v0 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 v1 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 v2 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 v3 = _mm_shuffle_ps(v, v, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(m[0], v0); + __m128 m1 = _mm_mul_ps(m[1], v1); + __m128 m2 = _mm_mul_ps(m[2], v2); + __m128 m3 = _mm_mul_ps(m[3], v3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + return a2; +} + +GLM_FUNC_QUALIFIER __m128 sse_mul_ps(__m128 v, __m128 const m[4]) +{ + __m128 i0 = m[0]; + __m128 i1 = m[1]; + __m128 i2 = m[2]; + __m128 i3 = m[3]; + + __m128 m0 = _mm_mul_ps(v, i0); + __m128 m1 = _mm_mul_ps(v, i1); + __m128 m2 = _mm_mul_ps(v, i2); + __m128 m3 = _mm_mul_ps(v, i3); + + __m128 u0 = _mm_unpacklo_ps(m0, m1); + __m128 u1 = _mm_unpackhi_ps(m0, m1); + __m128 a0 = _mm_add_ps(u0, u1); + + __m128 u2 = _mm_unpacklo_ps(m2, m3); + __m128 u3 = _mm_unpackhi_ps(m2, m3); + __m128 a1 = _mm_add_ps(u2, u3); + + __m128 f0 = _mm_movelh_ps(a0, a1); + __m128 f1 = _mm_movehl_ps(a1, a0); + __m128 f2 = _mm_add_ps(f0, f1); + + return f2; +} + +GLM_FUNC_QUALIFIER void sse_mul_ps(__m128 const in1[4], __m128 const in2[4], __m128 out[4]) +{ + { + __m128 e0 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[0], in2[0], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[0] = a2; + } + + { + __m128 e0 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[1], in2[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[1] = a2; + } + + { + __m128 e0 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[2], in2[2], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[2] = a2; + } + + { + //(__m128&)_mm_shuffle_epi32(__m128i&)in2[0], _MM_SHUFFLE(3, 3, 3, 3)) + __m128 e0 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 e1 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 e2 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 e3 = _mm_shuffle_ps(in2[3], in2[3], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(in1[0], e0); + __m128 m1 = _mm_mul_ps(in1[1], e1); + __m128 m2 = _mm_mul_ps(in1[2], e2); + __m128 m3 = _mm_mul_ps(in1[3], e3); + + __m128 a0 = _mm_add_ps(m0, m1); + __m128 a1 = _mm_add_ps(m2, m3); + __m128 a2 = _mm_add_ps(a0, a1); + + out[3] = a2; + } +} + +GLM_FUNC_QUALIFIER void sse_transpose_ps(__m128 const in[4], __m128 out[4]) +{ + __m128 tmp0 = _mm_shuffle_ps(in[0], in[1], 0x44); + __m128 tmp2 = _mm_shuffle_ps(in[0], in[1], 0xEE); + __m128 tmp1 = _mm_shuffle_ps(in[2], in[3], 0x44); + __m128 tmp3 = _mm_shuffle_ps(in[2], in[3], 0xEE); + + out[0] = _mm_shuffle_ps(tmp0, tmp1, 0x88); + out[1] = _mm_shuffle_ps(tmp0, tmp1, 0xDD); + out[2] = _mm_shuffle_ps(tmp2, tmp3, 0x88); + out[3] = _mm_shuffle_ps(tmp2, tmp3, 0xDD); +} + +GLM_FUNC_QUALIFIER __m128 sse_slow_det_ps(__m128 const in[4]) +{ + __m128 Fac0; + { + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + // valType SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac0 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac1; + { + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + // valType SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac1 = _mm_sub_ps(Mul00, Mul01); + } + + + __m128 Fac2; + { + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + // valType SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac2 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac3; + { + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + // valType SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac3 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac4; + { + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + // valType SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac4 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac5; + { + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + // valType SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac5 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 SignA = _mm_set_ps( 1.0f,-1.0f, 1.0f,-1.0f); + __m128 SignB = _mm_set_ps(-1.0f, 1.0f,-1.0f, 1.0f); + + // m[1][0] + // m[0][0] + // m[0][0] + // m[0][0] + __m128 Temp0 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Vec0 = _mm_shuffle_ps(Temp0, Temp0, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][1] + // m[0][1] + // m[0][1] + // m[0][1] + __m128 Temp1 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Vec1 = _mm_shuffle_ps(Temp1, Temp1, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][2] + // m[0][2] + // m[0][2] + // m[0][2] + __m128 Temp2 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Vec2 = _mm_shuffle_ps(Temp2, Temp2, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][3] + // m[0][3] + // m[0][3] + // m[0][3] + __m128 Temp3 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Vec3 = _mm_shuffle_ps(Temp3, Temp3, _MM_SHUFFLE(2, 2, 2, 0)); + + // col0 + // + (Vec1[0] * Fac0[0] - Vec2[0] * Fac1[0] + Vec3[0] * Fac2[0]), + // - (Vec1[1] * Fac0[1] - Vec2[1] * Fac1[1] + Vec3[1] * Fac2[1]), + // + (Vec1[2] * Fac0[2] - Vec2[2] * Fac1[2] + Vec3[2] * Fac2[2]), + // - (Vec1[3] * Fac0[3] - Vec2[3] * Fac1[3] + Vec3[3] * Fac2[3]), + __m128 Mul00 = _mm_mul_ps(Vec1, Fac0); + __m128 Mul01 = _mm_mul_ps(Vec2, Fac1); + __m128 Mul02 = _mm_mul_ps(Vec3, Fac2); + __m128 Sub00 = _mm_sub_ps(Mul00, Mul01); + __m128 Add00 = _mm_add_ps(Sub00, Mul02); + __m128 Inv0 = _mm_mul_ps(SignB, Add00); + + // col1 + // - (Vec0[0] * Fac0[0] - Vec2[0] * Fac3[0] + Vec3[0] * Fac4[0]), + // + (Vec0[0] * Fac0[1] - Vec2[1] * Fac3[1] + Vec3[1] * Fac4[1]), + // - (Vec0[0] * Fac0[2] - Vec2[2] * Fac3[2] + Vec3[2] * Fac4[2]), + // + (Vec0[0] * Fac0[3] - Vec2[3] * Fac3[3] + Vec3[3] * Fac4[3]), + __m128 Mul03 = _mm_mul_ps(Vec0, Fac0); + __m128 Mul04 = _mm_mul_ps(Vec2, Fac3); + __m128 Mul05 = _mm_mul_ps(Vec3, Fac4); + __m128 Sub01 = _mm_sub_ps(Mul03, Mul04); + __m128 Add01 = _mm_add_ps(Sub01, Mul05); + __m128 Inv1 = _mm_mul_ps(SignA, Add01); + + // col2 + // + (Vec0[0] * Fac1[0] - Vec1[0] * Fac3[0] + Vec3[0] * Fac5[0]), + // - (Vec0[0] * Fac1[1] - Vec1[1] * Fac3[1] + Vec3[1] * Fac5[1]), + // + (Vec0[0] * Fac1[2] - Vec1[2] * Fac3[2] + Vec3[2] * Fac5[2]), + // - (Vec0[0] * Fac1[3] - Vec1[3] * Fac3[3] + Vec3[3] * Fac5[3]), + __m128 Mul06 = _mm_mul_ps(Vec0, Fac1); + __m128 Mul07 = _mm_mul_ps(Vec1, Fac3); + __m128 Mul08 = _mm_mul_ps(Vec3, Fac5); + __m128 Sub02 = _mm_sub_ps(Mul06, Mul07); + __m128 Add02 = _mm_add_ps(Sub02, Mul08); + __m128 Inv2 = _mm_mul_ps(SignB, Add02); + + // col3 + // - (Vec1[0] * Fac2[0] - Vec1[0] * Fac4[0] + Vec2[0] * Fac5[0]), + // + (Vec1[0] * Fac2[1] - Vec1[1] * Fac4[1] + Vec2[1] * Fac5[1]), + // - (Vec1[0] * Fac2[2] - Vec1[2] * Fac4[2] + Vec2[2] * Fac5[2]), + // + (Vec1[0] * Fac2[3] - Vec1[3] * Fac4[3] + Vec2[3] * Fac5[3])); + __m128 Mul09 = _mm_mul_ps(Vec0, Fac2); + __m128 Mul10 = _mm_mul_ps(Vec1, Fac4); + __m128 Mul11 = _mm_mul_ps(Vec2, Fac5); + __m128 Sub03 = _mm_sub_ps(Mul09, Mul10); + __m128 Add03 = _mm_add_ps(Sub03, Mul11); + __m128 Inv3 = _mm_mul_ps(SignA, Add03); + + __m128 Row0 = _mm_shuffle_ps(Inv0, Inv1, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row1 = _mm_shuffle_ps(Inv2, Inv3, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row2 = _mm_shuffle_ps(Row0, Row1, _MM_SHUFFLE(2, 0, 2, 0)); + + // valType Determinant = m[0][0] * Inverse[0][0] + // + m[0][1] * Inverse[1][0] + // + m[0][2] * Inverse[2][0] + // + m[0][3] * Inverse[3][0]; + __m128 Det0 = sse_dot_ps(in[0], Row2); + return Det0; +} + +GLM_FUNC_QUALIFIER __m128 sse_detd_ps +( + __m128 const m[4] +) +{ + // _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128( + + //T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + //T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + //T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + //T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + //T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + //T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + // First 2 columns + __m128 Swp2A = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[2]), _MM_SHUFFLE(0, 1, 1, 2))); + __m128 Swp3A = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[3]), _MM_SHUFFLE(3, 2, 3, 3))); + __m128 MulA = _mm_mul_ps(Swp2A, Swp3A); + + // Second 2 columns + __m128 Swp2B = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[2]), _MM_SHUFFLE(3, 2, 3, 3))); + __m128 Swp3B = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[3]), _MM_SHUFFLE(0, 1, 1, 2))); + __m128 MulB = _mm_mul_ps(Swp2B, Swp3B); + + // Columns subtraction + __m128 SubE = _mm_sub_ps(MulA, MulB); + + // Last 2 rows + __m128 Swp2C = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[2]), _MM_SHUFFLE(0, 0, 1, 2))); + __m128 Swp3C = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[3]), _MM_SHUFFLE(1, 2, 0, 0))); + __m128 MulC = _mm_mul_ps(Swp2C, Swp3C); + __m128 SubF = _mm_sub_ps(_mm_movehl_ps(MulC, MulC), MulC); + + //tvec4<T, P> DetCof( + // + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), + // - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), + // + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), + // - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); + + __m128 SubFacA = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(SubE), _MM_SHUFFLE(2, 1, 0, 0))); + __m128 SwpFacA = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[1]), _MM_SHUFFLE(0, 0, 0, 1))); + __m128 MulFacA = _mm_mul_ps(SwpFacA, SubFacA); + + __m128 SubTmpB = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(0, 0, 3, 1)); + __m128 SubFacB = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(SubTmpB), _MM_SHUFFLE(3, 1, 1, 0)));//SubF[0], SubE[3], SubE[3], SubE[1]; + __m128 SwpFacB = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[1]), _MM_SHUFFLE(1, 1, 2, 2))); + __m128 MulFacB = _mm_mul_ps(SwpFacB, SubFacB); + + __m128 SubRes = _mm_sub_ps(MulFacA, MulFacB); + + __m128 SubTmpC = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(1, 0, 2, 2)); + __m128 SubFacC = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(SubTmpC), _MM_SHUFFLE(3, 3, 2, 0))); + __m128 SwpFacC = _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(m[1]), _MM_SHUFFLE(2, 3, 3, 3))); + __m128 MulFacC = _mm_mul_ps(SwpFacC, SubFacC); + + __m128 AddRes = _mm_add_ps(SubRes, MulFacC); + __m128 DetCof = _mm_mul_ps(AddRes, _mm_setr_ps( 1.0f,-1.0f, 1.0f,-1.0f)); + + //return m[0][0] * DetCof[0] + // + m[0][1] * DetCof[1] + // + m[0][2] * DetCof[2] + // + m[0][3] * DetCof[3]; + + return sse_dot_ps(m[0], DetCof); +} + +GLM_FUNC_QUALIFIER __m128 sse_det_ps +( + __m128 const m[4] +) +{ + // _mm_castsi128_ps(_mm_shuffle_epi32(_mm_castps_si128(add) + + //T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + //T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + //T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + //T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + //T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + //T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + + // First 2 columns + __m128 Swp2A = _mm_shuffle_ps(m[2], m[2], _MM_SHUFFLE(0, 1, 1, 2)); + __m128 Swp3A = _mm_shuffle_ps(m[3], m[3], _MM_SHUFFLE(3, 2, 3, 3)); + __m128 MulA = _mm_mul_ps(Swp2A, Swp3A); + + // Second 2 columns + __m128 Swp2B = _mm_shuffle_ps(m[2], m[2], _MM_SHUFFLE(3, 2, 3, 3)); + __m128 Swp3B = _mm_shuffle_ps(m[3], m[3], _MM_SHUFFLE(0, 1, 1, 2)); + __m128 MulB = _mm_mul_ps(Swp2B, Swp3B); + + // Columns subtraction + __m128 SubE = _mm_sub_ps(MulA, MulB); + + // Last 2 rows + __m128 Swp2C = _mm_shuffle_ps(m[2], m[2], _MM_SHUFFLE(0, 0, 1, 2)); + __m128 Swp3C = _mm_shuffle_ps(m[3], m[3], _MM_SHUFFLE(1, 2, 0, 0)); + __m128 MulC = _mm_mul_ps(Swp2C, Swp3C); + __m128 SubF = _mm_sub_ps(_mm_movehl_ps(MulC, MulC), MulC); + + //tvec4<T, P> DetCof( + // + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02), + // - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04), + // + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05), + // - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05)); + + __m128 SubFacA = _mm_shuffle_ps(SubE, SubE, _MM_SHUFFLE(2, 1, 0, 0)); + __m128 SwpFacA = _mm_shuffle_ps(m[1], m[1], _MM_SHUFFLE(0, 0, 0, 1)); + __m128 MulFacA = _mm_mul_ps(SwpFacA, SubFacA); + + __m128 SubTmpB = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(0, 0, 3, 1)); + __m128 SubFacB = _mm_shuffle_ps(SubTmpB, SubTmpB, _MM_SHUFFLE(3, 1, 1, 0));//SubF[0], SubE[3], SubE[3], SubE[1]; + __m128 SwpFacB = _mm_shuffle_ps(m[1], m[1], _MM_SHUFFLE(1, 1, 2, 2)); + __m128 MulFacB = _mm_mul_ps(SwpFacB, SubFacB); + + __m128 SubRes = _mm_sub_ps(MulFacA, MulFacB); + + __m128 SubTmpC = _mm_shuffle_ps(SubE, SubF, _MM_SHUFFLE(1, 0, 2, 2)); + __m128 SubFacC = _mm_shuffle_ps(SubTmpC, SubTmpC, _MM_SHUFFLE(3, 3, 2, 0)); + __m128 SwpFacC = _mm_shuffle_ps(m[1], m[1], _MM_SHUFFLE(2, 3, 3, 3)); + __m128 MulFacC = _mm_mul_ps(SwpFacC, SubFacC); + + __m128 AddRes = _mm_add_ps(SubRes, MulFacC); + __m128 DetCof = _mm_mul_ps(AddRes, _mm_setr_ps( 1.0f,-1.0f, 1.0f,-1.0f)); + + //return m[0][0] * DetCof[0] + // + m[0][1] * DetCof[1] + // + m[0][2] * DetCof[2] + // + m[0][3] * DetCof[3]; + + return sse_dot_ps(m[0], DetCof); +} + +GLM_FUNC_QUALIFIER void sse_inverse_ps(__m128 const in[4], __m128 out[4]) +{ + __m128 Fac0; + { + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + // valType SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac0 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac1; + { + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + // valType SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac1 = _mm_sub_ps(Mul00, Mul01); + } + + + __m128 Fac2; + { + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + // valType SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac2 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac3; + { + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + // valType SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac3 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac4; + { + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + // valType SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac4 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac5; + { + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + // valType SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac5 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 SignA = _mm_set_ps( 1.0f,-1.0f, 1.0f,-1.0f); + __m128 SignB = _mm_set_ps(-1.0f, 1.0f,-1.0f, 1.0f); + + // m[1][0] + // m[0][0] + // m[0][0] + // m[0][0] + __m128 Temp0 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Vec0 = _mm_shuffle_ps(Temp0, Temp0, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][1] + // m[0][1] + // m[0][1] + // m[0][1] + __m128 Temp1 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Vec1 = _mm_shuffle_ps(Temp1, Temp1, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][2] + // m[0][2] + // m[0][2] + // m[0][2] + __m128 Temp2 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Vec2 = _mm_shuffle_ps(Temp2, Temp2, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][3] + // m[0][3] + // m[0][3] + // m[0][3] + __m128 Temp3 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Vec3 = _mm_shuffle_ps(Temp3, Temp3, _MM_SHUFFLE(2, 2, 2, 0)); + + // col0 + // + (Vec1[0] * Fac0[0] - Vec2[0] * Fac1[0] + Vec3[0] * Fac2[0]), + // - (Vec1[1] * Fac0[1] - Vec2[1] * Fac1[1] + Vec3[1] * Fac2[1]), + // + (Vec1[2] * Fac0[2] - Vec2[2] * Fac1[2] + Vec3[2] * Fac2[2]), + // - (Vec1[3] * Fac0[3] - Vec2[3] * Fac1[3] + Vec3[3] * Fac2[3]), + __m128 Mul00 = _mm_mul_ps(Vec1, Fac0); + __m128 Mul01 = _mm_mul_ps(Vec2, Fac1); + __m128 Mul02 = _mm_mul_ps(Vec3, Fac2); + __m128 Sub00 = _mm_sub_ps(Mul00, Mul01); + __m128 Add00 = _mm_add_ps(Sub00, Mul02); + __m128 Inv0 = _mm_mul_ps(SignB, Add00); + + // col1 + // - (Vec0[0] * Fac0[0] - Vec2[0] * Fac3[0] + Vec3[0] * Fac4[0]), + // + (Vec0[0] * Fac0[1] - Vec2[1] * Fac3[1] + Vec3[1] * Fac4[1]), + // - (Vec0[0] * Fac0[2] - Vec2[2] * Fac3[2] + Vec3[2] * Fac4[2]), + // + (Vec0[0] * Fac0[3] - Vec2[3] * Fac3[3] + Vec3[3] * Fac4[3]), + __m128 Mul03 = _mm_mul_ps(Vec0, Fac0); + __m128 Mul04 = _mm_mul_ps(Vec2, Fac3); + __m128 Mul05 = _mm_mul_ps(Vec3, Fac4); + __m128 Sub01 = _mm_sub_ps(Mul03, Mul04); + __m128 Add01 = _mm_add_ps(Sub01, Mul05); + __m128 Inv1 = _mm_mul_ps(SignA, Add01); + + // col2 + // + (Vec0[0] * Fac1[0] - Vec1[0] * Fac3[0] + Vec3[0] * Fac5[0]), + // - (Vec0[0] * Fac1[1] - Vec1[1] * Fac3[1] + Vec3[1] * Fac5[1]), + // + (Vec0[0] * Fac1[2] - Vec1[2] * Fac3[2] + Vec3[2] * Fac5[2]), + // - (Vec0[0] * Fac1[3] - Vec1[3] * Fac3[3] + Vec3[3] * Fac5[3]), + __m128 Mul06 = _mm_mul_ps(Vec0, Fac1); + __m128 Mul07 = _mm_mul_ps(Vec1, Fac3); + __m128 Mul08 = _mm_mul_ps(Vec3, Fac5); + __m128 Sub02 = _mm_sub_ps(Mul06, Mul07); + __m128 Add02 = _mm_add_ps(Sub02, Mul08); + __m128 Inv2 = _mm_mul_ps(SignB, Add02); + + // col3 + // - (Vec1[0] * Fac2[0] - Vec1[0] * Fac4[0] + Vec2[0] * Fac5[0]), + // + (Vec1[0] * Fac2[1] - Vec1[1] * Fac4[1] + Vec2[1] * Fac5[1]), + // - (Vec1[0] * Fac2[2] - Vec1[2] * Fac4[2] + Vec2[2] * Fac5[2]), + // + (Vec1[0] * Fac2[3] - Vec1[3] * Fac4[3] + Vec2[3] * Fac5[3])); + __m128 Mul09 = _mm_mul_ps(Vec0, Fac2); + __m128 Mul10 = _mm_mul_ps(Vec1, Fac4); + __m128 Mul11 = _mm_mul_ps(Vec2, Fac5); + __m128 Sub03 = _mm_sub_ps(Mul09, Mul10); + __m128 Add03 = _mm_add_ps(Sub03, Mul11); + __m128 Inv3 = _mm_mul_ps(SignA, Add03); + + __m128 Row0 = _mm_shuffle_ps(Inv0, Inv1, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row1 = _mm_shuffle_ps(Inv2, Inv3, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row2 = _mm_shuffle_ps(Row0, Row1, _MM_SHUFFLE(2, 0, 2, 0)); + + // valType Determinant = m[0][0] * Inverse[0][0] + // + m[0][1] * Inverse[1][0] + // + m[0][2] * Inverse[2][0] + // + m[0][3] * Inverse[3][0]; + __m128 Det0 = sse_dot_ps(in[0], Row2); + __m128 Rcp0 = _mm_div_ps(one, Det0); + //__m128 Rcp0 = _mm_rcp_ps(Det0); + + // Inverse /= Determinant; + out[0] = _mm_mul_ps(Inv0, Rcp0); + out[1] = _mm_mul_ps(Inv1, Rcp0); + out[2] = _mm_mul_ps(Inv2, Rcp0); + out[3] = _mm_mul_ps(Inv3, Rcp0); +} + +GLM_FUNC_QUALIFIER void sse_inverse_fast_ps(__m128 const in[4], __m128 out[4]) +{ + __m128 Fac0; + { + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + // valType SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + // valType SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac0 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac1; + { + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + // valType SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + // valType SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac1 = _mm_sub_ps(Mul00, Mul01); + } + + + __m128 Fac2; + { + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + // valType SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + // valType SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac2 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac3; + { + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + // valType SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + // valType SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac3 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac4; + { + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + // valType SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + // valType SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(2, 2, 2, 2)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac4 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 Fac5; + { + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + // valType SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + // valType SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + __m128 Swp0a = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Swp0b = _mm_shuffle_ps(in[3], in[2], _MM_SHUFFLE(0, 0, 0, 0)); + + __m128 Swp00 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Swp01 = _mm_shuffle_ps(Swp0a, Swp0a, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp02 = _mm_shuffle_ps(Swp0b, Swp0b, _MM_SHUFFLE(2, 0, 0, 0)); + __m128 Swp03 = _mm_shuffle_ps(in[2], in[1], _MM_SHUFFLE(1, 1, 1, 1)); + + __m128 Mul00 = _mm_mul_ps(Swp00, Swp01); + __m128 Mul01 = _mm_mul_ps(Swp02, Swp03); + Fac5 = _mm_sub_ps(Mul00, Mul01); + } + + __m128 SignA = _mm_set_ps( 1.0f,-1.0f, 1.0f,-1.0f); + __m128 SignB = _mm_set_ps(-1.0f, 1.0f,-1.0f, 1.0f); + + // m[1][0] + // m[0][0] + // m[0][0] + // m[0][0] + __m128 Temp0 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Vec0 = _mm_shuffle_ps(Temp0, Temp0, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][1] + // m[0][1] + // m[0][1] + // m[0][1] + __m128 Temp1 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Vec1 = _mm_shuffle_ps(Temp1, Temp1, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][2] + // m[0][2] + // m[0][2] + // m[0][2] + __m128 Temp2 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Vec2 = _mm_shuffle_ps(Temp2, Temp2, _MM_SHUFFLE(2, 2, 2, 0)); + + // m[1][3] + // m[0][3] + // m[0][3] + // m[0][3] + __m128 Temp3 = _mm_shuffle_ps(in[1], in[0], _MM_SHUFFLE(3, 3, 3, 3)); + __m128 Vec3 = _mm_shuffle_ps(Temp3, Temp3, _MM_SHUFFLE(2, 2, 2, 0)); + + // col0 + // + (Vec1[0] * Fac0[0] - Vec2[0] * Fac1[0] + Vec3[0] * Fac2[0]), + // - (Vec1[1] * Fac0[1] - Vec2[1] * Fac1[1] + Vec3[1] * Fac2[1]), + // + (Vec1[2] * Fac0[2] - Vec2[2] * Fac1[2] + Vec3[2] * Fac2[2]), + // - (Vec1[3] * Fac0[3] - Vec2[3] * Fac1[3] + Vec3[3] * Fac2[3]), + __m128 Mul00 = _mm_mul_ps(Vec1, Fac0); + __m128 Mul01 = _mm_mul_ps(Vec2, Fac1); + __m128 Mul02 = _mm_mul_ps(Vec3, Fac2); + __m128 Sub00 = _mm_sub_ps(Mul00, Mul01); + __m128 Add00 = _mm_add_ps(Sub00, Mul02); + __m128 Inv0 = _mm_mul_ps(SignB, Add00); + + // col1 + // - (Vec0[0] * Fac0[0] - Vec2[0] * Fac3[0] + Vec3[0] * Fac4[0]), + // + (Vec0[0] * Fac0[1] - Vec2[1] * Fac3[1] + Vec3[1] * Fac4[1]), + // - (Vec0[0] * Fac0[2] - Vec2[2] * Fac3[2] + Vec3[2] * Fac4[2]), + // + (Vec0[0] * Fac0[3] - Vec2[3] * Fac3[3] + Vec3[3] * Fac4[3]), + __m128 Mul03 = _mm_mul_ps(Vec0, Fac0); + __m128 Mul04 = _mm_mul_ps(Vec2, Fac3); + __m128 Mul05 = _mm_mul_ps(Vec3, Fac4); + __m128 Sub01 = _mm_sub_ps(Mul03, Mul04); + __m128 Add01 = _mm_add_ps(Sub01, Mul05); + __m128 Inv1 = _mm_mul_ps(SignA, Add01); + + // col2 + // + (Vec0[0] * Fac1[0] - Vec1[0] * Fac3[0] + Vec3[0] * Fac5[0]), + // - (Vec0[0] * Fac1[1] - Vec1[1] * Fac3[1] + Vec3[1] * Fac5[1]), + // + (Vec0[0] * Fac1[2] - Vec1[2] * Fac3[2] + Vec3[2] * Fac5[2]), + // - (Vec0[0] * Fac1[3] - Vec1[3] * Fac3[3] + Vec3[3] * Fac5[3]), + __m128 Mul06 = _mm_mul_ps(Vec0, Fac1); + __m128 Mul07 = _mm_mul_ps(Vec1, Fac3); + __m128 Mul08 = _mm_mul_ps(Vec3, Fac5); + __m128 Sub02 = _mm_sub_ps(Mul06, Mul07); + __m128 Add02 = _mm_add_ps(Sub02, Mul08); + __m128 Inv2 = _mm_mul_ps(SignB, Add02); + + // col3 + // - (Vec1[0] * Fac2[0] - Vec1[0] * Fac4[0] + Vec2[0] * Fac5[0]), + // + (Vec1[0] * Fac2[1] - Vec1[1] * Fac4[1] + Vec2[1] * Fac5[1]), + // - (Vec1[0] * Fac2[2] - Vec1[2] * Fac4[2] + Vec2[2] * Fac5[2]), + // + (Vec1[0] * Fac2[3] - Vec1[3] * Fac4[3] + Vec2[3] * Fac5[3])); + __m128 Mul09 = _mm_mul_ps(Vec0, Fac2); + __m128 Mul10 = _mm_mul_ps(Vec1, Fac4); + __m128 Mul11 = _mm_mul_ps(Vec2, Fac5); + __m128 Sub03 = _mm_sub_ps(Mul09, Mul10); + __m128 Add03 = _mm_add_ps(Sub03, Mul11); + __m128 Inv3 = _mm_mul_ps(SignA, Add03); + + __m128 Row0 = _mm_shuffle_ps(Inv0, Inv1, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row1 = _mm_shuffle_ps(Inv2, Inv3, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Row2 = _mm_shuffle_ps(Row0, Row1, _MM_SHUFFLE(2, 0, 2, 0)); + + // valType Determinant = m[0][0] * Inverse[0][0] + // + m[0][1] * Inverse[1][0] + // + m[0][2] * Inverse[2][0] + // + m[0][3] * Inverse[3][0]; + __m128 Det0 = sse_dot_ps(in[0], Row2); + __m128 Rcp0 = _mm_rcp_ps(Det0); + //__m128 Rcp0 = _mm_div_ps(one, Det0); + // Inverse /= Determinant; + out[0] = _mm_mul_ps(Inv0, Rcp0); + out[1] = _mm_mul_ps(Inv1, Rcp0); + out[2] = _mm_mul_ps(Inv2, Rcp0); + out[3] = _mm_mul_ps(Inv3, Rcp0); +} +/* +GLM_FUNC_QUALIFIER void sse_rotate_ps(__m128 const in[4], float Angle, float const v[3], __m128 out[4]) +{ + float a = glm::radians(Angle); + float c = cos(a); + float s = sin(a); + + glm::vec4 AxisA(v[0], v[1], v[2], float(0)); + __m128 AxisB = _mm_set_ps(AxisA.w, AxisA.z, AxisA.y, AxisA.x); + __m128 AxisC = detail::sse_nrm_ps(AxisB); + + __m128 Cos0 = _mm_set_ss(c); + __m128 CosA = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Sin0 = _mm_set_ss(s); + __m128 SinA = _mm_shuffle_ps(Sin0, Sin0, _MM_SHUFFLE(0, 0, 0, 0)); + + // tvec3<T, P> temp = (valType(1) - c) * axis; + __m128 Temp0 = _mm_sub_ps(one, CosA); + __m128 Temp1 = _mm_mul_ps(Temp0, AxisC); + + //Rotate[0][0] = c + temp[0] * axis[0]; + //Rotate[0][1] = 0 + temp[0] * axis[1] + s * axis[2]; + //Rotate[0][2] = 0 + temp[0] * axis[2] - s * axis[1]; + __m128 Axis0 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 TmpA0 = _mm_mul_ps(Axis0, AxisC); + __m128 CosA0 = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(1, 1, 1, 0)); + __m128 TmpA1 = _mm_add_ps(CosA0, TmpA0); + __m128 SinA0 = SinA;//_mm_set_ps(0.0f, s, -s, 0.0f); + __m128 TmpA2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(3, 1, 2, 3)); + __m128 TmpA3 = _mm_mul_ps(SinA0, TmpA2); + __m128 TmpA4 = _mm_add_ps(TmpA1, TmpA3); + + //Rotate[1][0] = 0 + temp[1] * axis[0] - s * axis[2]; + //Rotate[1][1] = c + temp[1] * axis[1]; + //Rotate[1][2] = 0 + temp[1] * axis[2] + s * axis[0]; + __m128 Axis1 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 TmpB0 = _mm_mul_ps(Axis1, AxisC); + __m128 CosA1 = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(1, 1, 0, 1)); + __m128 TmpB1 = _mm_add_ps(CosA1, TmpB0); + __m128 SinB0 = SinA;//_mm_set_ps(-s, 0.0f, s, 0.0f); + __m128 TmpB2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(3, 0, 3, 2)); + __m128 TmpB3 = _mm_mul_ps(SinA0, TmpB2); + __m128 TmpB4 = _mm_add_ps(TmpB1, TmpB3); + + //Rotate[2][0] = 0 + temp[2] * axis[0] + s * axis[1]; + //Rotate[2][1] = 0 + temp[2] * axis[1] - s * axis[0]; + //Rotate[2][2] = c + temp[2] * axis[2]; + __m128 Axis2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 TmpC0 = _mm_mul_ps(Axis2, AxisC); + __m128 CosA2 = _mm_shuffle_ps(Cos0, Cos0, _MM_SHUFFLE(1, 0, 1, 1)); + __m128 TmpC1 = _mm_add_ps(CosA2, TmpC0); + __m128 SinC0 = SinA;//_mm_set_ps(s, -s, 0.0f, 0.0f); + __m128 TmpC2 = _mm_shuffle_ps(AxisC, AxisC, _MM_SHUFFLE(3, 3, 0, 1)); + __m128 TmpC3 = _mm_mul_ps(SinA0, TmpC2); + __m128 TmpC4 = _mm_add_ps(TmpC1, TmpC3); + + __m128 Result[4]; + Result[0] = TmpA4; + Result[1] = TmpB4; + Result[2] = TmpC4; + Result[3] = _mm_set_ps(1, 0, 0, 0); + + //tmat4x4<valType> Result(uninitialize); + //Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2]; + //Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2]; + //Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2]; + //Result[3] = m[3]; + //return Result; + sse_mul_ps(in, Result, out); +} +*/ +GLM_FUNC_QUALIFIER void sse_outer_ps(__m128 const & c, __m128 const & r, __m128 out[4]) +{ + out[0] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(0, 0, 0, 0))); + out[1] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(1, 1, 1, 1))); + out[2] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(2, 2, 2, 2))); + out[3] = _mm_mul_ps(c, _mm_shuffle_ps(r, r, _MM_SHUFFLE(3, 3, 3, 3))); +} + +}//namespace detail +}//namespace glm diff --git a/extensions/common/glm/detail/intrinsic_trigonometric.hpp b/extensions/common/glm/detail/intrinsic_trigonometric.hpp new file mode 100644 index 0000000000..f344fa1a88 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_trigonometric.hpp @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_trigonometric.hpp +/// @date 2009-06-09 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" + +#if(!(GLM_ARCH & GLM_ARCH_SSE2)) +# error "SSE2 instructions not supported or enabled" +#else + +namespace glm{ +namespace detail +{ + +}//namespace detail +}//namespace glm + +#include "intrinsic_trigonometric.inl" + +#endif//GLM_ARCH diff --git a/extensions/common/glm/detail/intrinsic_trigonometric.inl b/extensions/common/glm/detail/intrinsic_trigonometric.inl new file mode 100644 index 0000000000..badf934621 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_trigonometric.inl @@ -0,0 +1,27 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_trigonometric.inl +/// @date 2011-06-15 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// diff --git a/extensions/common/glm/detail/intrinsic_vector_relational.hpp b/extensions/common/glm/detail/intrinsic_vector_relational.hpp new file mode 100644 index 0000000000..1aca073374 --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_vector_relational.hpp @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_vector_relational.hpp +/// @date 2009-06-09 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" + +#if(!(GLM_ARCH & GLM_ARCH_SSE2)) +# error "SSE2 instructions not supported or enabled" +#else + +namespace glm{ +namespace detail +{ + +}//namespace detail +}//namespace glm + +#include "intrinsic_vector_relational.inl" + +#endif//GLM_ARCH diff --git a/extensions/common/glm/detail/intrinsic_vector_relational.inl b/extensions/common/glm/detail/intrinsic_vector_relational.inl new file mode 100644 index 0000000000..4b230826db --- /dev/null +++ b/extensions/common/glm/detail/intrinsic_vector_relational.inl @@ -0,0 +1,366 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/intrinsic_vector_relational.inl +/// @date 2009-06-09 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// +// +//// lessThan +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec2<T, P>::bool_type lessThan +//( +// tvec2<T, P> const & x, +// tvec2<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec2<bool>::bool_type(x.x < y.x, x.y < y.y); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec3<T, P>::bool_type lessThan +//( +// tvec3<T, P> const & x, +// tvec3<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec3<bool>::bool_type(x.x < y.x, x.y < y.y, x.z < y.z); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec4<T, P>::bool_type lessThan +//( +// tvec4<T, P> const & x, +// tvec4<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec4<bool>::bool_type(x.x < y.x, x.y < y.y, x.z < y.z, x.w < y.w); +//} +// +//// lessThanEqual +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec2<T, P>::bool_type lessThanEqual +//( +// tvec2<T, P> const & x, +// tvec2<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec2<bool>::bool_type(x.x <= y.x, x.y <= y.y); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec3<T, P>::bool_type lessThanEqual +//( +// tvec3<T, P> const & x, +// tvec3<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec3<bool>::bool_type(x.x <= y.x, x.y <= y.y, x.z <= y.z); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec4<T, P>::bool_type lessThanEqual +//( +// tvec4<T, P> const & x, +// tvec4<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec4<bool>::bool_type(x.x <= y.x, x.y <= y.y, x.z <= y.z, x.w <= y.w); +//} +// +//// greaterThan +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec2<T, P>::bool_type greaterThan +//( +// tvec2<T, P> const & x, +// tvec2<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec2<bool>::bool_type(x.x > y.x, x.y > y.y); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec3<T, P>::bool_type greaterThan +//( +// tvec3<T, P> const & x, +// tvec3<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec3<bool>::bool_type(x.x > y.x, x.y > y.y, x.z > y.z); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec4<T, P>::bool_type greaterThan +//( +// tvec4<T, P> const & x, +// tvec4<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec4<bool>::bool_type(x.x > y.x, x.y > y.y, x.z > y.z, x.w > y.w); +//} +// +//// greaterThanEqual +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec2<T, P>::bool_type greaterThanEqual +//( +// tvec2<T, P> const & x, +// tvec2<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec2<bool>::bool_type(x.x >= y.x, x.y >= y.y); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec3<T, P>::bool_type greaterThanEqual +//( +// tvec3<T, P> const & x, +// tvec3<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec3<bool>::bool_type(x.x >= y.x, x.y >= y.y, x.z >= y.z); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec4<T, P>::bool_type greaterThanEqual +//( +// tvec4<T, P> const & x, +// tvec4<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint); +// +// return typename tvec4<bool>::bool_type(x.x >= y.x, x.y >= y.y, x.z >= y.z, x.w >= y.w); +//} +// +//// equal +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec2<T, P>::bool_type equal +//( +// tvec2<T, P> const & x, +// tvec2<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint || +// detail::type<valType>::is_bool); +// +// return typename tvec2<T, P>::bool_type(x.x == y.x, x.y == y.y); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec3<T, P>::bool_type equal +//( +// tvec3<T, P> const & x, +// tvec3<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint || +// detail::type<valType>::is_bool); +// +// return typename tvec3<T, P>::bool_type(x.x == y.x, x.y == y.y, x.z == y.z); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec4<T, P>::bool_type equal +//( +// tvec4<T, P> const & x, +// tvec4<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint || +// detail::type<valType>::is_bool); +// +// return typename tvec4<T, P>::bool_type(x.x == y.x, x.y == y.y, x.z == y.z, x.w == y.w); +//} +// +//// notEqual +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec2<T, P>::bool_type notEqual +//( +// tvec2<T, P> const & x, +// tvec2<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint || +// detail::type<valType>::is_bool); +// +// return typename tvec2<T, P>::bool_type(x.x != y.x, x.y != y.y); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec3<T, P>::bool_type notEqual +//( +// tvec3<T, P> const & x, +// tvec3<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint || +// detail::type<valType>::is_bool); +// +// return typename tvec3<T, P>::bool_type(x.x != y.x, x.y != y.y, x.z != y.z); +//} +// +//template <typename valType> +//GLM_FUNC_QUALIFIER typename tvec4<T, P>::bool_type notEqual +//( +// tvec4<T, P> const & x, +// tvec4<T, P> const & y +//) +//{ +// GLM_STATIC_ASSERT( +// detail::type<valType>::is_float || +// detail::type<valType>::is_int || +// detail::type<valType>::is_uint || +// detail::type<valType>::is_bool); +// +// return typename tvec4<T, P>::bool_type(x.x != y.x, x.y != y.y, x.z != y.z, x.w != y.w); +//} +// +//// any +//GLM_FUNC_QUALIFIER bool any(tvec2<bool> const & x) +//{ +// return x.x || x.y; +//} +// +//GLM_FUNC_QUALIFIER bool any(tvec3<bool> const & x) +//{ +// return x.x || x.y || x.z; +//} +// +//GLM_FUNC_QUALIFIER bool any(tvec4<bool> const & x) +//{ +// return x.x || x.y || x.z || x.w; +//} +// +//// all +//GLM_FUNC_QUALIFIER bool all(const tvec2<bool>& x) +//{ +// return x.x && x.y; +//} +// +//GLM_FUNC_QUALIFIER bool all(const tvec3<bool>& x) +//{ +// return x.x && x.y && x.z; +//} +// +//GLM_FUNC_QUALIFIER bool all(const tvec4<bool>& x) +//{ +// return x.x && x.y && x.z && x.w; +//} +// +//// not +//GLM_FUNC_QUALIFIER tvec2<bool>::bool_type not_ +//( +// tvec2<bool> const & v +//) +//{ +// return tvec2<bool>::bool_type(!v.x, !v.y); +//} +// +//GLM_FUNC_QUALIFIER tvec3<bool>::bool_type not_ +//( +// tvec3<bool> const & v +//) +//{ +// return tvec3<bool>::bool_type(!v.x, !v.y, !v.z); +//} +// +//GLM_FUNC_QUALIFIER tvec4<bool>::bool_type not_ +//( +// tvec4<bool> const & v +//) +//{ +// return tvec4<bool>::bool_type(!v.x, !v.y, !v.z, !v.w); +//} \ No newline at end of file diff --git a/extensions/common/glm/detail/precision.hpp b/extensions/common/glm/detail/precision.hpp new file mode 100644 index 0000000000..ac46528235 --- /dev/null +++ b/extensions/common/glm/detail/precision.hpp @@ -0,0 +1,44 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/precision.hpp +/// @date 2013-04-01 / 2013-04-01 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +namespace glm +{ + enum precision + { + highp, + mediump, + lowp, + defaultp = highp + }; +}//namespace glm diff --git a/extensions/common/glm/detail/setup.hpp b/extensions/common/glm/detail/setup.hpp new file mode 100644 index 0000000000..c54e7bf982 --- /dev/null +++ b/extensions/common/glm/detail/setup.hpp @@ -0,0 +1,962 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/setup.hpp +/// @date 2006-11-13 / 2014-10-05 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include <cassert> +#include <cstddef> + +/////////////////////////////////////////////////////////////////////////////////// +// Version + +#define GLM_VERSION 96 +#define GLM_VERSION_MAJOR 0 +#define GLM_VERSION_MINOR 9 +#define GLM_VERSION_PATCH 6 +#define GLM_VERSION_REVISION 3 + +#if(defined(GLM_MESSAGES) && !defined(GLM_MESSAGE_VERSION_DISPLAYED)) +# define GLM_MESSAGE_VERSION_DISPLAYED +# pragma message ("GLM: version 0.9.6.3") +#endif//GLM_MESSAGE + +/////////////////////////////////////////////////////////////////////////////////// +// Platform + +#define GLM_PLATFORM_UNKNOWN 0x00000000 +#define GLM_PLATFORM_WINDOWS 0x00010000 +#define GLM_PLATFORM_LINUX 0x00020000 +#define GLM_PLATFORM_APPLE 0x00040000 +//#define GLM_PLATFORM_IOS 0x00080000 +#define GLM_PLATFORM_ANDROID 0x00100000 +#define GLM_PLATFORM_CHROME_NACL 0x00200000 +#define GLM_PLATFORM_UNIX 0x00400000 +#define GLM_PLATFORM_QNXNTO 0x00800000 +#define GLM_PLATFORM_WINCE 0x01000000 + +#ifdef GLM_FORCE_PLATFORM_UNKNOWN +# define GLM_PLATFORM GLM_PLATFORM_UNKNOWN +#elif defined(__QNXNTO__) +# define GLM_PLATFORM GLM_PLATFORM_QNXNTO +#elif defined(__APPLE__) +# define GLM_PLATFORM GLM_PLATFORM_APPLE +#elif defined(WINCE) +# define GLM_PLATFORM GLM_PLATFORM_WINCE +#elif defined(_WIN32) +# define GLM_PLATFORM GLM_PLATFORM_WINDOWS +#elif defined(__native_client__) +# define GLM_PLATFORM GLM_PLATFORM_CHROME_NACL +#elif defined(__ANDROID__) +# define GLM_PLATFORM GLM_PLATFORM_ANDROID +#elif defined(__linux) +# define GLM_PLATFORM GLM_PLATFORM_LINUX +#elif defined(__unix) +# define GLM_PLATFORM GLM_PLATFORM_UNIX +#else +# define GLM_PLATFORM GLM_PLATFORM_UNKNOWN +#endif// + +// Report platform detection +#if(defined(GLM_MESSAGES) && !defined(GLM_MESSAGE_PLATFORM_DISPLAYED)) +# define GLM_MESSAGE_PLATFORM_DISPLAYED +# if(GLM_PLATFORM & GLM_PLATFORM_QNXNTO) +# pragma message("GLM: QNX platform detected") +//# elif(GLM_PLATFORM & GLM_PLATFORM_IOS) +//# pragma message("GLM: iOS platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_APPLE) +# pragma message("GLM: Apple platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_WINCE) +# pragma message("GLM: WinCE platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_WINDOWS) +# pragma message("GLM: Windows platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_CHROME_NACL) +# pragma message("GLM: Native Client detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) +# pragma message("GLM: Android platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_LINUX) +# pragma message("GLM: Linux platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_UNIX) +# pragma message("GLM: UNIX platform detected") +# elif(GLM_PLATFORM & GLM_PLATFORM_UNKNOWN) +# pragma message("GLM: platform unknown") +# else +# pragma message("GLM: platform not detected") +# endif +#endif//GLM_MESSAGE + +/////////////////////////////////////////////////////////////////////////////////// +// Compiler + +// User defines: GLM_FORCE_COMPILER_UNKNOWN +// TODO ? __llvm__ + +#define GLM_COMPILER_UNKNOWN 0x00000000 + +// Intel +#define GLM_COMPILER_INTEL 0x00100000 +#define GLM_COMPILER_INTEL12 0x00100010 +#define GLM_COMPILER_INTEL12_1 0x00100020 +#define GLM_COMPILER_INTEL13 0x00100030 +#define GLM_COMPILER_INTEL14 0x00100040 +#define GLM_COMPILER_INTEL15 0x00100050 + +// Visual C++ defines +#define GLM_COMPILER_VC 0x01000000 +#define GLM_COMPILER_VC2010 0x01000090 +#define GLM_COMPILER_VC2012 0x010000A0 +#define GLM_COMPILER_VC2013 0x010000B0 +#define GLM_COMPILER_VC2015 0x010000C0 + +// GCC defines +#define GLM_COMPILER_GCC 0x02000000 +#define GLM_COMPILER_GCC44 0x020000B0 +#define GLM_COMPILER_GCC45 0x020000C0 +#define GLM_COMPILER_GCC46 0x020000D0 +#define GLM_COMPILER_GCC47 0x020000E0 +#define GLM_COMPILER_GCC48 0x020000F0 +#define GLM_COMPILER_GCC49 0x02000100 +#define GLM_COMPILER_GCC50 0x02000200 + +// CUDA +#define GLM_COMPILER_CUDA 0x10000000 +#define GLM_COMPILER_CUDA40 0x10000040 +#define GLM_COMPILER_CUDA41 0x10000050 +#define GLM_COMPILER_CUDA42 0x10000060 +#define GLM_COMPILER_CUDA50 0x10000070 +#define GLM_COMPILER_CUDA60 0x10000080 +#define GLM_COMPILER_CUDA65 0x10000090 + +// LLVM +#define GLM_COMPILER_LLVM 0x20000000 +#define GLM_COMPILER_LLVM32 0x20000030 +#define GLM_COMPILER_LLVM33 0x20000040 +#define GLM_COMPILER_LLVM34 0x20000050 +#define GLM_COMPILER_LLVM35 0x20000060 + +// Apple Clang +#define GLM_COMPILER_APPLE_CLANG 0x40000000 +#define GLM_COMPILER_APPLE_CLANG40 0x40000010 +#define GLM_COMPILER_APPLE_CLANG41 0x40000020 +#define GLM_COMPILER_APPLE_CLANG42 0x40000030 +#define GLM_COMPILER_APPLE_CLANG50 0x40000040 +#define GLM_COMPILER_APPLE_CLANG51 0x40000050 +#define GLM_COMPILER_APPLE_CLANG60 0x40000060 + +// Build model +#define GLM_MODEL_32 0x00000010 +#define GLM_MODEL_64 0x00000020 + +// Force generic C++ compiler +#ifdef GLM_FORCE_COMPILER_UNKNOWN +# define GLM_COMPILER GLM_COMPILER_UNKNOWN + +#elif defined(__INTEL_COMPILER) +# if __INTEL_COMPILER == 1200 +# define GLM_COMPILER GLM_COMPILER_INTEL12 +# elif __INTEL_COMPILER == 1210 +# define GLM_COMPILER GLM_COMPILER_INTEL12_1 +# elif __INTEL_COMPILER == 1300 +# define GLM_COMPILER GLM_COMPILER_INTEL13 +# elif __INTEL_COMPILER == 1400 +# define GLM_COMPILER GLM_COMPILER_INTEL14 +# elif __INTEL_COMPILER >= 1500 +# define GLM_COMPILER GLM_COMPILER_INTEL15 +# else +# define GLM_COMPILER GLM_COMPILER_INTEL +# endif + +// CUDA +#elif defined(__CUDACC__) +# if !defined(CUDA_VERSION) && !defined(GLM_FORCE_CUDA) +# include <cuda.h> // make sure version is defined since nvcc does not define it itself! +# endif +# if CUDA_VERSION < 3000 +# error "GLM requires CUDA 3.0 or higher" +# else +# define GLM_COMPILER GLM_COMPILER_CUDA +# endif + +// Visual C++ +#elif defined(_MSC_VER) +# if _MSC_VER < 1600 +# error "GLM requires Visual C++ 2010 or higher" +# elif _MSC_VER == 1600 +# define GLM_COMPILER GLM_COMPILER_VC2010 +# elif _MSC_VER == 1700 +# define GLM_COMPILER GLM_COMPILER_VC2012 +# elif _MSC_VER == 1800 +# define GLM_COMPILER GLM_COMPILER_VC2013 +# elif _MSC_VER >= 1900 +# define GLM_COMPILER GLM_COMPILER_VC2015 +# else//_MSC_VER +# define GLM_COMPILER GLM_COMPILER_VC +# endif//_MSC_VER + +// Clang +#elif defined(__clang__) +# if GLM_PLATFORM & GLM_PLATFORM_APPLE +# if __clang_major__ == 4 && __clang_minor__ == 0 +# define GLM_COMPILER GLM_COMPILER_APPLE_CLANG40 +# elif __clang_major__ == 4 && __clang_minor__ == 1 +# define GLM_COMPILER GLM_COMPILER_APPLE_CLANG41 +# elif __clang_major__ == 4 && __clang_minor__ == 2 +# define GLM_COMPILER GLM_COMPILER_APPLE_CLANG42 +# elif __clang_major__ == 5 && __clang_minor__ == 0 +# define GLM_COMPILER GLM_COMPILER_APPLE_CLANG50 +# elif __clang_major__ == 5 && __clang_minor__ == 1 +# define GLM_COMPILER GLM_COMPILER_APPLE_CLANG51 +# elif __clang_major__ >= 6 +# define GLM_COMPILER GLM_COMPILER_APPLE_CLANG60 +# endif +# else +# if __clang_major__ == 3 && __clang_minor__ == 0 +# define GLM_COMPILER GLM_COMPILER_LLVM30 +# elif __clang_major__ == 3 && __clang_minor__ == 1 +# define GLM_COMPILER GLM_COMPILER_LLVM31 +# elif __clang_major__ == 3 && __clang_minor__ == 2 +# define GLM_COMPILER GLM_COMPILER_LLVM32 +# elif __clang_major__ == 3 && __clang_minor__ == 3 +# define GLM_COMPILER GLM_COMPILER_LLVM33 +# elif __clang_major__ == 3 && __clang_minor__ == 4 +# define GLM_COMPILER GLM_COMPILER_LLVM34 +# elif __clang_major__ == 3 && __clang_minor__ == 5 +# define GLM_COMPILER GLM_COMPILER_LLVM35 +# else +# define GLM_COMPILER GLM_COMPILER_LLVM35 +# endif +# endif + +// G++ +#elif defined(__GNUC__) || defined(__MINGW32__) +# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 2) +# define GLM_COMPILER (GLM_COMPILER_GCC42) +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 3) +# define GLM_COMPILER (GLM_COMPILER_GCC43) +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 4) +# define GLM_COMPILER (GLM_COMPILER_GCC44) +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 5) +# define GLM_COMPILER (GLM_COMPILER_GCC45) +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 6) +# define GLM_COMPILER (GLM_COMPILER_GCC46) +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 7) +# define GLM_COMPILER (GLM_COMPILER_GCC47) +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) +# define GLM_COMPILER (GLM_COMPILER_GCC48) +# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9) +# define GLM_COMPILER (GLM_COMPILER_GCC49) +# elif (__GNUC__ > 4 ) +# define GLM_COMPILER (GLM_COMPILER_GCC50) +# else +# define GLM_COMPILER (GLM_COMPILER_GCC) +# endif + +#else +# define GLM_COMPILER GLM_COMPILER_UNKNOWN +#endif + +#ifndef GLM_COMPILER +#error "GLM_COMPILER undefined, your compiler may not be supported by GLM. Add #define GLM_COMPILER 0 to ignore this message." +#endif//GLM_COMPILER + +// Report compiler detection +#if defined(GLM_MESSAGES) && !defined(GLM_MESSAGE_COMPILER_DISPLAYED) +# define GLM_MESSAGE_COMPILER_DISPLAYED +# if GLM_COMPILER & GLM_COMPILER_CUDA +# pragma message("GLM: CUDA compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_VC +# pragma message("GLM: Visual C++ compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_APPLE_CLANG +# pragma message("GLM: Clang compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_LLVM +# pragma message("GLM: LLVM compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_INTEL +# pragma message("GLM: Intel Compiler detected") +# elif GLM_COMPILER & GLM_COMPILER_GCC +# pragma message("GLM: GCC compiler detected") +# else +# pragma message("GLM: Compiler not detected") +# endif +#endif//GLM_MESSAGE + +/////////////////////////////////////////////////////////////////////////////////// +// Build model + +#if defined(__arch64__) || defined(__LP64__) || defined(_M_X64) || defined(__ppc64__) || defined(__x86_64__) +# define GLM_MODEL GLM_MODEL_64 +#elif defined(__i386__) || defined(__ppc__) +# define GLM_MODEL GLM_MODEL_32 +#else +# define GLM_MODEL GLM_MODEL_32 +#endif// + +#if !defined(GLM_MODEL) && GLM_COMPILER != 0 +# error "GLM_MODEL undefined, your compiler may not be supported by GLM. Add #define GLM_MODEL 0 to ignore this message." +#endif//GLM_MODEL + +#if defined(GLM_MESSAGES) && !defined(GLM_MESSAGE_MODEL_DISPLAYED) +# define GLM_MESSAGE_MODEL_DISPLAYED +# if(GLM_MODEL == GLM_MODEL_64) +# pragma message("GLM: 64 bits model") +# elif(GLM_MODEL == GLM_MODEL_32) +# pragma message("GLM: 32 bits model") +# endif//GLM_MODEL +#endif//GLM_MESSAGE + +/////////////////////////////////////////////////////////////////////////////////// +// C++ Version + +// User defines: GLM_FORCE_CXX98, GLM_FORCE_CXX03, GLM_FORCE_CXX11, GLM_FORCE_CXX14 + +#define GLM_LANG_CXX98_FLAG (1 << 1) +#define GLM_LANG_CXX03_FLAG (1 << 2) +#define GLM_LANG_CXX0X_FLAG (1 << 3) +#define GLM_LANG_CXX11_FLAG (1 << 4) +#define GLM_LANG_CXX1Y_FLAG (1 << 5) +#define GLM_LANG_CXX14_FLAG (1 << 6) +#define GLM_LANG_CXX1Z_FLAG (1 << 7) +#define GLM_LANG_CXXMS_FLAG (1 << 8) +#define GLM_LANG_CXXGNU_FLAG (1 << 9) + +#define GLM_LANG_CXX98 GLM_LANG_CXX98_FLAG +#define GLM_LANG_CXX03 (GLM_LANG_CXX98 | GLM_LANG_CXX03_FLAG) +#define GLM_LANG_CXX0X (GLM_LANG_CXX03 | GLM_LANG_CXX0X_FLAG) +#define GLM_LANG_CXX11 (GLM_LANG_CXX0X | GLM_LANG_CXX11_FLAG) +#define GLM_LANG_CXX1Y (GLM_LANG_CXX11 | GLM_LANG_CXX1Y_FLAG) +#define GLM_LANG_CXX14 (GLM_LANG_CXX1Y | GLM_LANG_CXX14_FLAG) +#define GLM_LANG_CXX1Z (GLM_LANG_CXX14 | GLM_LANG_CXX1Z_FLAG) +#define GLM_LANG_CXXMS GLM_LANG_CXXMS_FLAG +#define GLM_LANG_CXXGNU GLM_LANG_CXXGNU_FLAG + +#if defined(GLM_FORCE_CXX14) +# undef GLM_FORCE_CXX11 +# undef GLM_FORCE_CXX03 +# undef GLM_FORCE_CXX98 +# define GLM_LANG GLM_LANG_CXX14 +#elif defined(GLM_FORCE_CXX11) +# undef GLM_FORCE_CXX03 +# undef GLM_FORCE_CXX98 +# define GLM_LANG GLM_LANG_CXX11 +#elif defined(GLM_FORCE_CXX03) +# undef GLM_FORCE_CXX98 +# define GLM_LANG GLM_LANG_CXX03 +#elif defined(GLM_FORCE_CXX98) +# define GLM_LANG GLM_LANG_CXX98 +#else +# if GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM) +# if __cplusplus >= 201402L // GLM_COMPILER_LLVM34 + -std=c++14 +# define GLM_LANG GLM_LANG_CXX14 +# elif __has_feature(cxx_decltype_auto) && __has_feature(cxx_aggregate_nsdmi) // GLM_COMPILER_LLVM33 + -std=c++1y +# define GLM_LANG GLM_LANG_CXX1Y +# elif __cplusplus >= 201103L // GLM_COMPILER_LLVM33 + -std=c++11 +# define GLM_LANG GLM_LANG_CXX11 +# elif __has_feature(cxx_static_assert) // GLM_COMPILER_LLVM29 + -std=c++11 +# define GLM_LANG GLM_LANG_CXX0X +# elif __cplusplus >= 199711L +# define GLM_LANG GLM_LANG_CXX98 +# else +# define GLM_LANG GLM_LANG_CXX +# endif +# elif GLM_COMPILER & GLM_COMPILER_GCC +# if __cplusplus >= 201402L +# define GLM_LANG GLM_LANG_CXX14 +# elif __cplusplus >= 201103L +# define GLM_LANG GLM_LANG_CXX11 +# elif defined(__GXX_EXPERIMENTAL_CXX0X__) +# define GLM_LANG GLM_LANG_CXX0X +# else +# define GLM_LANG GLM_LANG_CXX98 +# endif +# elif GLM_COMPILER & GLM_COMPILER_VC +# ifdef _MSC_EXTENSIONS +# if __cplusplus >= 201402L +# define GLM_LANG (GLM_LANG_CXX14 | GLM_LANG_CXXMS_FLAG) +//# elif GLM_COMPILER >= GLM_COMPILER_VC2015 +//# define GLM_LANG (GLM_LANG_CXX1Y | GLM_LANG_CXXMS_FLAG) +# elif __cplusplus >= 201103L +# define GLM_LANG (GLM_LANG_CXX11 | GLM_LANG_CXXMS_FLAG) +# elif GLM_COMPILER >= GLM_COMPILER_VC2010 +# define GLM_LANG (GLM_LANG_CXX0X | GLM_LANG_CXXMS_FLAG) +# elif __cplusplus >= 199711L +# define GLM_LANG (GLM_LANG_CXX98 | GLM_LANG_CXXMS_FLAG) +# else +# define GLM_LANG (GLM_LANG_CXX | GLM_LANG_CXXMS_FLAG) +# endif +# else +# if __cplusplus >= 201402L +# define GLM_LANG GLM_LANG_CXX14 +//# elif GLM_COMPILER >= GLM_COMPILER_VC2015 +//# define GLM_LANG GLM_LANG_CXX1Y +# elif __cplusplus >= 201103L +# define GLM_LANG GLM_LANG_CXX11 +# elif GLM_COMPILER >= GLM_COMPILER_VC2010 +# define GLM_LANG GLM_LANG_CXX0X +# elif __cplusplus >= 199711L +# define GLM_LANG GLM_LANG_CXX98 +# else +# define GLM_LANG GLM_LANG_CXX +# endif +# endif +# elif GLM_COMPILER & GLM_COMPILER_INTEL +# ifdef _MSC_EXTENSIONS +# if __cplusplus >= 201402L +# define GLM_LANG (GLM_LANG_CXX14 | GLM_LANG_CXXMS_FLAG) +# elif __cplusplus >= 201103L +# define GLM_LANG (GLM_LANG_CXX11 | GLM_LANG_CXXMS_FLAG) +# elif GLM_COMPILER >= GLM_COMPILER_INTEL13 +# define GLM_LANG (GLM_LANG_CXX0X | GLM_LANG_CXXMS_FLAG) +# elif __cplusplus >= 199711L +# define GLM_LANG (GLM_LANG_CXX98 | GLM_LANG_CXXMS_FLAG) +# else +# define GLM_LANG (GLM_LANG_CXX | GLM_LANG_CXXMS_FLAG) +# endif +# else +# if __cplusplus >= 201402L +# define GLM_LANG (GLM_LANG_CXX14 | GLM_LANG_CXXMS_FLAG) +# elif __cplusplus >= 201103L +# define GLM_LANG (GLM_LANG_CXX11 | GLM_LANG_CXXMS_FLAG) +# elif GLM_COMPILER >= GLM_COMPILER_INTEL13 +# define GLM_LANG (GLM_LANG_CXX0X | GLM_LANG_CXXMS_FLAG) +# elif __cplusplus >= 199711L +# define GLM_LANG (GLM_LANG_CXX98 | GLM_LANG_CXXMS_FLAG) +# else +# define GLM_LANG (GLM_LANG_CXX | GLM_LANG_CXXMS_FLAG) +# endif +# endif +# else // Unkown compiler +# if __cplusplus >= 201402L +# define GLM_LANG GLM_LANG_CXX14 +# elif __cplusplus >= 201103L +# define GLM_LANG GLM_LANG_CXX11 +# elif __cplusplus >= 199711L +# define GLM_LANG GLM_LANG_CXX98 +# else +# define GLM_LANG GLM_LANG_CXX // Good luck with that! +# endif +# ifndef GLM_FORCE_PURE +# define GLM_FORCE_PURE +# endif +# endif +#endif + +#if defined(GLM_MESSAGES) && !defined(GLM_MESSAGE_LANG_DISPLAYED) +# define GLM_MESSAGE_LANG_DISPLAYED + +# if GLM_LANG & GLM_LANG_CXX1Z_FLAG +# pragma message("GLM: C++1z") +# elif GLM_LANG & GLM_LANG_CXX14_FLAG +# pragma message("GLM: C++14") +# elif GLM_LANG & GLM_LANG_CXX1Y_FLAG +# pragma message("GLM: C++1y") +# elif GLM_LANG & GLM_LANG_CXX11_FLAG +# pragma message("GLM: C++11") +# elif GLM_LANG & GLM_LANG_CXX0X_FLAG +# pragma message("GLM: C++0x") +# elif GLM_LANG & GLM_LANG_CXX03_FLAG +# pragma message("GLM: C++03") +# elif GLM_LANG & GLM_LANG_CXX98_FLAG +# pragma message("GLM: C++98") +# else +# pragma message("GLM: C++ language undetected") +# endif//GLM_LANG + +# if GLM_LANG & (GLM_LANG_CXXGNU_FLAG | GLM_LANG_CXXMS_FLAG) +# pragma message("GLM: Language extensions enabled") +# endif//GLM_LANG +#endif//GLM_MESSAGE + +/////////////////////////////////////////////////////////////////////////////////// +// Has of C++ features + +// http://clang.llvm.org/cxx_status.html +// http://gcc.gnu.org/projects/cxx0x.html +// http://msdn.microsoft.com/en-us/library/vstudio/hh567368(v=vs.120).aspx + +#if GLM_PLATFORM == GLM_PLATFORM_ANDROID +# define GLM_HAS_CXX11_STL 0 +#elif GLM_COMPILER & (GLM_COMPILER_LLVM | GLM_COMPILER_APPLE_CLANG) +# define GLM_HAS_CXX11_STL __has_include(<__config>) +#else +# define GLM_HAS_CXX11_STL ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && \ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC48)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2013))) +#endif + +// N1720 +#if GLM_COMPILER & (GLM_COMPILER_LLVM | GLM_COMPILER_APPLE_CLANG) +# define GLM_HAS_STATIC_ASSERT __has_feature(cxx_static_assert) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_STATIC_ASSERT 1 +#else +# define GLM_HAS_STATIC_ASSERT (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC43)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2010))) +#endif + +// N1988 +#if GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_EXTENDED_INTEGER_TYPE 1 +#else +# define GLM_HAS_EXTENDED_INTEGER_TYPE (\ + ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2012)) || \ + ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC43)) || \ + ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_COMPILER & GLM_COMPILER_LLVM) && (GLM_COMPILER >= GLM_COMPILER_LLVM30)) || \ + ((GLM_LANG & GLM_LANG_CXX0X_FLAG) && (GLM_COMPILER & GLM_COMPILER_APPLE_CLANG) && (GLM_COMPILER >= GLM_COMPILER_APPLE_CLANG40))) +#endif + +// N2235 +#if GLM_COMPILER & (GLM_COMPILER_LLVM | GLM_COMPILER_APPLE_CLANG) +# define GLM_HAS_CONSTEXPR __has_feature(cxx_constexpr) +# define GLM_HAS_CONSTEXPR_PARTIAL GLM_HAS_CONSTEXPR +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_CONSTEXPR 1 +# define GLM_HAS_CONSTEXPR_PARTIAL GLM_HAS_CONSTEXPR +#else +# define GLM_HAS_CONSTEXPR (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC46))) +# define GLM_HAS_CONSTEXPR_PARTIAL GLM_HAS_CONSTEXPR || ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2015)) +#endif + +// N2672 +#if GLM_COMPILER & (GLM_COMPILER_LLVM | GLM_COMPILER_APPLE_CLANG) +# define GLM_HAS_INITIALIZER_LISTS __has_feature(cxx_generalized_initializers) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_INITIALIZER_LISTS 1 +#else +# define GLM_HAS_INITIALIZER_LISTS (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC44)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2013))) +#endif + +// N2544 Unrestricted unions +#if GLM_COMPILER & (GLM_COMPILER_LLVM | GLM_COMPILER_APPLE_CLANG) +# define GLM_HAS_UNRESTRICTED_UNIONS __has_feature(cxx_unrestricted_unions) +#elif GLM_LANG & (GLM_LANG_CXX11_FLAG | GLM_LANG_CXXMS_FLAG) +# define GLM_HAS_UNRESTRICTED_UNIONS 1 +#else +# define GLM_HAS_UNRESTRICTED_UNIONS (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC46))) +#endif + +// N2346 +#if GLM_COMPILER & (GLM_COMPILER_LLVM | GLM_COMPILER_APPLE_CLANG) +# define GLM_HAS_DEFAULTED_FUNCTIONS __has_feature(cxx_defaulted_functions) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_DEFAULTED_FUNCTIONS 1 +#else +# define GLM_HAS_DEFAULTED_FUNCTIONS (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC44)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2013))) +#endif + +// N2118 +#if GLM_COMPILER & (GLM_COMPILER_LLVM | GLM_COMPILER_APPLE_CLANG) +# define GLM_HAS_RVALUE_REFERENCES __has_feature(cxx_rvalue_references) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_RVALUE_REFERENCES 1 +#else +# define GLM_HAS_RVALUE_REFERENCES (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC43)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2012))) +#endif + +// N2437 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2437.pdf +#if GLM_COMPILER & (GLM_COMPILER_LLVM | GLM_COMPILER_APPLE_CLANG) +# define GLM_HAS_EXPLICIT_CONVERSION_OPERATORS __has_feature(cxx_explicit_conversions) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_EXPLICIT_CONVERSION_OPERATORS 1 +#else +# define GLM_HAS_EXPLICIT_CONVERSION_OPERATORS (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC45)) || \ + ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL14)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2013))) +#endif + +// N2258 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf +#if GLM_COMPILER & (GLM_COMPILER_LLVM | GLM_COMPILER_APPLE_CLANG) +# define GLM_HAS_TEMPLATE_ALIASES __has_feature(cxx_alias_templates) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_TEMPLATE_ALIASES 1 +#else +# define GLM_HAS_TEMPLATE_ALIASES (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL12_1)) || \ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC47)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2013))) +#endif + +// N2930 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2930.html +#if GLM_COMPILER & (GLM_COMPILER_LLVM | GLM_COMPILER_APPLE_CLANG) +# define GLM_HAS_RANGE_FOR __has_feature(cxx_range_for) +#elif GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_RANGE_FOR 1 +#else +# define GLM_HAS_RANGE_FOR (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC46)) || \ + ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_COMPILER >= GLM_COMPILER_INTEL13)) || \ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2012))) +#endif + +// +#if GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_ASSIGNABLE 1 +#else +# define GLM_HAS_ASSIGNABLE (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_GCC) && (GLM_COMPILER >= GLM_COMPILER_GCC49))) +#endif + +// +#define GLM_HAS_TRIVIAL_QUERIES 0//( \ + //((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2013))) + +// +#if GLM_LANG & GLM_LANG_CXX11_FLAG +# define GLM_HAS_MAKE_SIGNED 1 +#else +# define GLM_HAS_MAKE_SIGNED (GLM_LANG & GLM_LANG_CXX0X_FLAG) && (\ + ((GLM_COMPILER & GLM_COMPILER_VC) && (GLM_COMPILER >= GLM_COMPILER_VC2013))) +#endif + +// +#if GLM_ARCH == GLM_ARCH_PURE +# define GLM_HAS_BITSCAN_WINDOWS 0 +#else +# define GLM_HAS_BITSCAN_WINDOWS (GLM_PLATFORM & GLM_PLATFORM_WINDOWS) && (\ + (GLM_COMPILER & (GLM_COMPILER_VC | GLM_COMPILER_LLVM | GLM_COMPILER_INTEL)) +#endif + +// OpenMP +#ifdef _OPENMP +# if GLM_COMPILER & GLM_COMPILER_GCC +# if GLM_COMPILER >= GLM_COMPILER_GCC47 +# define GLM_HAS_OPENMP 31 +# elif GLM_COMPILER >= GLM_COMPILER_GCC44 +# define GLM_HAS_OPENMP 30 +# elif GLM_COMPILER >= GLM_COMPILER_GCC42 +# define GLM_HAS_OPENMP 25 +# endif +# endif// GLM_COMPILER & GLM_COMPILER_GCC + +# if GLM_COMPILER & GLM_COMPILER_VC +# if GLM_COMPILER >= GLM_COMPILER_VC2010 +# define GLM_HAS_OPENMP 20 +# endif +# endif// GLM_COMPILER & GLM_COMPILER_VC +#endif + +// Not standard +#define GLM_HAS_ANONYMOUS_UNION (GLM_LANG & GLM_LANG_CXXMS_FLAG) + +/////////////////////////////////////////////////////////////////////////////////// +// Platform + +// User defines: GLM_FORCE_PURE GLM_FORCE_SSE2 GLM_FORCE_SSE3 GLM_FORCE_AVX GLM_FORCE_AVX2 + +#define GLM_ARCH_PURE 0x0000 +#define GLM_ARCH_ARM 0x0001 +#define GLM_ARCH_X86 0x0002 +#define GLM_ARCH_SSE2 0x0004 +#define GLM_ARCH_SSE3 0x0008 +#define GLM_ARCH_SSE4 0x0010 +#define GLM_ARCH_AVX 0x0020 +#define GLM_ARCH_AVX2 0x0040 + +#if defined(GLM_FORCE_PURE) +# define GLM_ARCH GLM_ARCH_PURE +#elif defined(GLM_FORCE_AVX2) +# define GLM_ARCH (GLM_ARCH_AVX2 | GLM_ARCH_AVX | GLM_ARCH_SSE4 | GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +#elif defined(GLM_FORCE_AVX) +# define GLM_ARCH (GLM_ARCH_AVX | GLM_ARCH_SSE4 | GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +#elif defined(GLM_FORCE_SSE4) +# define GLM_ARCH (GLM_ARCH_SSE4 | GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +#elif defined(GLM_FORCE_SSE3) +# define GLM_ARCH (GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +#elif defined(GLM_FORCE_SSE2) +# define GLM_ARCH (GLM_ARCH_SSE2) +#elif (GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM | GLM_COMPILER_GCC)) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_LINUX)) +# if(__AVX2__) +# define GLM_ARCH (GLM_ARCH_AVX2 | GLM_ARCH_AVX | GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +# elif(__AVX__) +# define GLM_ARCH (GLM_ARCH_AVX | GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +# elif(__SSE3__) +# define GLM_ARCH (GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +# elif(__SSE2__) +# define GLM_ARCH (GLM_ARCH_SSE2) +# else +# define GLM_ARCH GLM_ARCH_PURE +# endif +#elif (GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)) +# if defined(_M_ARM_FP) +# define GLM_ARCH (GLM_ARCH_ARM) +# elif defined(__AVX2__) +# define GLM_ARCH (GLM_ARCH_AVX2 | GLM_ARCH_AVX | GLM_ARCH_SSE4 | GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +# elif defined(__AVX__) +# define GLM_ARCH (GLM_ARCH_AVX | GLM_ARCH_SSE4 | GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +# elif _M_IX86_FP == 2 +# define GLM_ARCH (GLM_ARCH_SSE2) +# else +# define GLM_ARCH (GLM_ARCH_PURE) +# endif +#elif (GLM_COMPILER & GLM_COMPILER_GCC) && (defined(__i386__) || defined(__x86_64__)) +# if defined(__AVX2__) +# define GLM_ARCH (GLM_ARCH_AVX2 | GLM_ARCH_AVX | GLM_ARCH_SSE4 | GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +# elif defined(__AVX__) +# define GLM_ARCH (GLM_ARCH_AVX | GLM_ARCH_SSE4 | GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +# elif defined(__SSE4_1__ ) +# define GLM_ARCH (GLM_ARCH_SSE4 | GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +# elif defined(__SSE3__) +# define GLM_ARCH (GLM_ARCH_SSE3 | GLM_ARCH_SSE2) +# elif defined(__SSE2__) +# define GLM_ARCH (GLM_ARCH_SSE2) +# else +# define GLM_ARCH (GLM_ARCH_PURE) +# endif +#else +# define GLM_ARCH GLM_ARCH_PURE +#endif + +// With MinGW-W64, including intrinsic headers before intrin.h will produce some errors. The problem is +// that windows.h (and maybe other headers) will silently include intrin.h, which of course causes problems. +// To fix, we just explicitly include intrin.h here. +#if defined(__MINGW64__) && (GLM_ARCH != GLM_ARCH_PURE) +# include <intrin.h> +#endif + +#if GLM_ARCH & GLM_ARCH_AVX2 +# include <immintrin.h> +#endif//GLM_ARCH +#if GLM_ARCH & GLM_ARCH_AVX +# include <immintrin.h> +#endif//GLM_ARCH +#if GLM_ARCH & GLM_ARCH_SSE4 +# include <smmintrin.h> +#endif//GLM_ARCH +#if GLM_ARCH & GLM_ARCH_SSE3 +# include <pmmintrin.h> +#endif//GLM_ARCH +#if GLM_ARCH & GLM_ARCH_SSE2 +# include <emmintrin.h> +# if(GLM_COMPILER == GLM_COMPILER_VC2005) // VC2005 is missing some intrinsics, workaround + inline float _mm_cvtss_f32(__m128 A) { return A.m128_f32[0]; } + inline __m128 _mm_castpd_ps(__m128d PD) { union { __m128 ps; __m128d pd; } c; c.pd = PD; return c.ps; } + inline __m128d _mm_castps_pd(__m128 PS) { union { __m128 ps; __m128d pd; } c; c.ps = PS; return c.pd; } + inline __m128i _mm_castps_si128(__m128 PS) { union { __m128 ps; __m128i pi; } c; c.ps = PS; return c.pi; } + inline __m128 _mm_castsi128_ps(__m128i PI) { union { __m128 ps; __m128i pi; } c; c.pi = PI; return c.ps; } +# endif +#endif//GLM_ARCH + +#if defined(GLM_MESSAGES) && !defined(GLM_MESSAGE_ARCH_DISPLAYED) +# define GLM_MESSAGE_ARCH_DISPLAYED +# if(GLM_ARCH == GLM_ARCH_PURE) +# pragma message("GLM: Platform independent code") +# elif(GLM_ARCH & GLM_ARCH_ARM) +# pragma message("GLM: ARM instruction set") +# elif(GLM_ARCH & GLM_ARCH_AVX2) +# pragma message("GLM: AVX2 instruction set") +# elif(GLM_ARCH & GLM_ARCH_AVX) +# pragma message("GLM: AVX instruction set") +# elif(GLM_ARCH & GLM_ARCH_SSE3) +# pragma message("GLM: SSE3 instruction set") +# elif(GLM_ARCH & GLM_ARCH_SSE2) +# pragma message("GLM: SSE2 instruction set") +# endif//GLM_ARCH +#endif//GLM_MESSAGE + +/////////////////////////////////////////////////////////////////////////////////// +// Static assert + +#if GLM_HAS_STATIC_ASSERT +# define GLM_STATIC_ASSERT(x, message) static_assert(x, message) +#elif defined(BOOST_STATIC_ASSERT) +# define GLM_STATIC_ASSERT(x, message) BOOST_STATIC_ASSERT(x) +#elif GLM_COMPILER & GLM_COMPILER_VC +# define GLM_STATIC_ASSERT(x, message) typedef char __CASSERT__##__LINE__[(x) ? 1 : -1] +#else +# define GLM_STATIC_ASSERT(x, message) +# define GLM_STATIC_ASSERT_NULL +#endif//GLM_LANG + +/////////////////////////////////////////////////////////////////////////////////// +// Qualifiers + +#if GLM_COMPILER & GLM_COMPILER_CUDA +# define GLM_CUDA_FUNC_DEF __device__ __host__ +# define GLM_CUDA_FUNC_DECL __device__ __host__ +#else +# define GLM_CUDA_FUNC_DEF +# define GLM_CUDA_FUNC_DECL +#endif + +#if GLM_COMPILER & GLM_COMPILER_GCC +# define GLM_VAR_USED __attribute__ ((unused)) +#else +# define GLM_VAR_USED +#endif + +#if defined(GLM_FORCE_INLINE) +# if GLM_COMPILER & GLM_COMPILER_VC +# define GLM_INLINE __forceinline +# define GLM_NEVER_INLINE __declspec((noinline)) +# elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM) +# define GLM_INLINE inline __attribute__((__always_inline__)) +# define GLM_NEVER_INLINE __attribute__((__noinline__)) +# else +# define GLM_INLINE inline +# define GLM_NEVER_INLINE +# endif//GLM_COMPILER +#else +# define GLM_INLINE inline +# define GLM_NEVER_INLINE +#endif//defined(GLM_FORCE_INLINE) + +#define GLM_FUNC_DECL GLM_CUDA_FUNC_DECL +#define GLM_FUNC_QUALIFIER GLM_CUDA_FUNC_DEF GLM_INLINE + +/////////////////////////////////////////////////////////////////////////////////// +// Swizzle operators + +// User defines: GLM_SWIZZLE + +#if defined(GLM_MESSAGES) && !defined(GLM_MESSAGE_SWIZZLE_DISPLAYED) +# define GLM_MESSAGE_SWIZZLE_DISPLAYED +# if defined(GLM_SWIZZLE) +# pragma message("GLM: Swizzling operators enabled") +# else +# pragma message("GLM: Swizzling operators disabled, #define GLM_SWIZZLE to enable swizzle operators") +# endif +#endif//GLM_MESSAGE + +/////////////////////////////////////////////////////////////////////////////////// +// Qualifiers + +#if (GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS)) +# define GLM_DEPRECATED __declspec(deprecated) +# define GLM_ALIGN(x) __declspec(align(x)) +# define GLM_ALIGNED_STRUCT(x) struct __declspec(align(x)) +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef __declspec(align(alignment)) type name +# define GLM_RESTRICT __declspec(restrict) +# define GLM_RESTRICT_VAR __restrict +#elif GLM_COMPILER & (GLM_COMPILER_GCC | GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM | GLM_COMPILER_CUDA | GLM_COMPILER_INTEL) +# define GLM_DEPRECATED __attribute__((__deprecated__)) +# define GLM_ALIGN(x) __attribute__((aligned(x))) +# define GLM_ALIGNED_STRUCT(x) struct __attribute__((aligned(x))) +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef type name __attribute__((aligned(alignment))) +# define GLM_RESTRICT __restrict__ +# define GLM_RESTRICT_VAR __restrict__ +#else +# define GLM_DEPRECATED +# define GLM_ALIGN +# define GLM_ALIGNED_STRUCT(x) struct +# define GLM_ALIGNED_TYPEDEF(type, name, alignment) typedef type name +# define GLM_RESTRICT +# define GLM_RESTRICT_VAR +#endif//GLM_COMPILER + +#if GLM_HAS_CONSTEXPR +# define GLM_CONSTEXPR constexpr +#else +# define GLM_CONSTEXPR +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Length type + +// User defines: GLM_FORCE_SIZE_T_LENGTH GLM_FORCE_SIZE_FUNC + +namespace glm +{ + using std::size_t; +# if defined(GLM_FORCE_SIZE_T_LENGTH) || defined(GLM_FORCE_SIZE_FUNC) + typedef size_t length_t; +# else + typedef int length_t; +# endif + +namespace detail +{ +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t component_count_t; +# else + typedef length_t component_count_t; +# endif + + template <typename genType> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR component_count_t component_count(genType const & m) + { +# ifdef GLM_FORCE_SIZE_FUNC + return m.size(); +# else + return m.length(); +# endif + } +}//namespace detail +}//namespace glm + +#if defined(GLM_MESSAGES) && !defined(GLM_MESSAGE_FORCE_SIZE_T_LENGTH) +# define GLM_MESSAGE_FORCE_SIZE_T_LENGTH +# if defined GLM_FORCE_SIZE_FUNC +# pragma message("GLM: .length() is replaced by .size() and returns a std::size_t") +# elif defined GLM_FORCE_SIZE_T_LENGTH +# pragma message("GLM: .length() returns glm::length_t, a typedef of std::size_t") +# else +# pragma message("GLM: .length() returns glm::length_t, a typedef of int following the GLSL specification") +# endif +#endif//GLM_MESSAGE + +/////////////////////////////////////////////////////////////////////////////////// +// countof + +#ifndef __has_feature +# define __has_feature(x) 0 // Compatibility with non-clang compilers. +#endif + +#if GLM_HAS_CONSTEXPR_PARTIAL + namespace glm + { + template <typename T, std::size_t N> + constexpr std::size_t countof(T const (&)[N]) + { + return N; + } + }//namespace glm +# define GLM_COUNTOF(arr) glm::countof(arr) +#elif _MSC_VER +# define GLM_COUNTOF(arr) _countof(arr) +#else +# define GLM_COUNTOF(arr) sizeof(arr) / sizeof(arr[0]) +#endif + +/////////////////////////////////////////////////////////////////////////////////// +// Uninitialize constructors + +namespace glm +{ + enum ctor{uninitialize}; +}//namespace glm diff --git a/extensions/common/glm/detail/type_float.hpp b/extensions/common/glm/detail/type_float.hpp new file mode 100644 index 0000000000..378aa58bf4 --- /dev/null +++ b/extensions/common/glm/detail/type_float.hpp @@ -0,0 +1,96 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_float.hpp +/// @date 2008-08-22 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" + +namespace glm{ +namespace detail +{ + typedef float float32; + typedef double float64; +}//namespace detail + + typedef float lowp_float_t; + typedef float mediump_float_t; + typedef double highp_float_t; + + /// @addtogroup core_precision + /// @{ + + /// Low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.4 Floats</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef lowp_float_t lowp_float; + + /// Medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.4 Floats</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef mediump_float_t mediump_float; + + /// High precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.4 Floats</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef highp_float_t highp_float; + +#if(!defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + typedef mediump_float float_t; +#elif(defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + typedef highp_float float_t; +#elif(!defined(GLM_PRECISION_HIGHP_FLOAT) && defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + typedef mediump_float float_t; +#elif(!defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && defined(GLM_PRECISION_LOWP_FLOAT)) + typedef lowp_float float_t; +#else +# error "GLM error: multiple default precision requested for floating-point types" +#endif + + typedef float float32; + typedef double float64; + +//////////////////// +// check type sizes +#ifndef GLM_STATIC_ASSERT_NULL + GLM_STATIC_ASSERT(sizeof(glm::float32) == 4, "float32 size isn't 4 bytes on this platform"); + GLM_STATIC_ASSERT(sizeof(glm::float64) == 8, "float64 size isn't 8 bytes on this platform"); +#endif//GLM_STATIC_ASSERT_NULL + + /// @} + +}//namespace glm diff --git a/extensions/common/glm/detail/type_gentype.hpp b/extensions/common/glm/detail/type_gentype.hpp new file mode 100644 index 0000000000..6c21a09d6c --- /dev/null +++ b/extensions/common/glm/detail/type_gentype.hpp @@ -0,0 +1,224 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_gentype.hpp +/// @date 2008-10-05 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +namespace glm +{ + enum profile + { + nice, + fast, + simd + }; + + typedef std::size_t sizeType; + +namespace detail +{ + template + < + typename VALTYPE, + template <typename> class TYPE + > + struct genType + { + public: + enum ctor{null}; + + typedef VALTYPE value_type; + typedef VALTYPE & value_reference; + typedef VALTYPE * value_pointer; + typedef VALTYPE const * value_const_pointer; + typedef TYPE<bool> bool_type; + + typedef sizeType size_type; + static bool is_vector(); + static bool is_matrix(); + + typedef TYPE<VALTYPE> type; + typedef TYPE<VALTYPE> * pointer; + typedef TYPE<VALTYPE> const * const_pointer; + typedef TYPE<VALTYPE> const * const const_pointer_const; + typedef TYPE<VALTYPE> * const pointer_const; + typedef TYPE<VALTYPE> & reference; + typedef TYPE<VALTYPE> const & const_reference; + typedef TYPE<VALTYPE> const & param_type; + + ////////////////////////////////////// + // Address (Implementation details) + + value_const_pointer value_address() const{return value_pointer(this);} + value_pointer value_address(){return value_pointer(this);} + + //protected: + // enum kind + // { + // GEN_TYPE, + // VEC_TYPE, + // MAT_TYPE + // }; + + // typedef typename TYPE::kind kind; + }; + + template + < + typename VALTYPE, + template <typename> class TYPE + > + bool genType<VALTYPE, TYPE>::is_vector() + { + return true; + } +/* + template <typename valTypeT, unsigned int colT, unsigned int rowT, profile proT = nice> + class base + { + public: + ////////////////////////////////////// + // Traits + + typedef sizeType size_type; + typedef valTypeT value_type; + + typedef base<value_type, colT, rowT> class_type; + + typedef base<bool, colT, rowT> bool_type; + typedef base<value_type, rowT, 1> col_type; + typedef base<value_type, colT, 1> row_type; + typedef base<value_type, rowT, colT> transpose_type; + + static size_type col_size(); + static size_type row_size(); + static size_type value_size(); + static bool is_scalar(); + static bool is_vector(); + static bool is_matrix(); + + private: + // Data + col_type value[colT]; + + public: + ////////////////////////////////////// + // Constructors + base(); + base(class_type const & m); + + explicit base(T const & x); + explicit base(value_type const * const x); + explicit base(col_type const * const x); + + ////////////////////////////////////// + // Conversions + template <typename vU, uint cU, uint rU, profile pU> + explicit base(base<vU, cU, rU, pU> const & m); + + ////////////////////////////////////// + // Accesses + col_type& operator[](size_type i); + col_type const & operator[](size_type i) const; + + ////////////////////////////////////// + // Unary updatable operators + class_type& operator= (class_type const & x); + class_type& operator+= (T const & x); + class_type& operator+= (class_type const & x); + class_type& operator-= (T const & x); + class_type& operator-= (class_type const & x); + class_type& operator*= (T const & x); + class_type& operator*= (class_type const & x); + class_type& operator/= (T const & x); + class_type& operator/= (class_type const & x); + class_type& operator++ (); + class_type& operator-- (); + }; +*/ + + //template <typename T> + //struct traits + //{ + // static const bool is_signed = false; + // static const bool is_float = false; + // static const bool is_vector = false; + // static const bool is_matrix = false; + // static const bool is_genType = false; + // static const bool is_genIType = false; + // static const bool is_genUType = false; + //}; + + //template <> + //struct traits<half> + //{ + // static const bool is_float = true; + // static const bool is_genType = true; + //}; + + //template <> + //struct traits<float> + //{ + // static const bool is_float = true; + // static const bool is_genType = true; + //}; + + //template <> + //struct traits<double> + //{ + // static const bool is_float = true; + // static const bool is_genType = true; + //}; + + //template <typename genType> + //struct desc + //{ + // typedef genType type; + // typedef genType * pointer; + // typedef genType const* const_pointer; + // typedef genType const *const const_pointer_const; + // typedef genType *const pointer_const; + // typedef genType & reference; + // typedef genType const& const_reference; + // typedef genType const& param_type; + + // typedef typename genType::value_type value_type; + // typedef typename genType::size_type size_type; + // static const typename size_type value_size; + //}; + + //template <typename genType> + //const typename desc<genType>::size_type desc<genType>::value_size = genType::value_size(); + +}//namespace detail +}//namespace glm + +//#include "type_gentype.inl" diff --git a/extensions/common/glm/detail/type_gentype.inl b/extensions/common/glm/detail/type_gentype.inl new file mode 100644 index 0000000000..684caa4360 --- /dev/null +++ b/extensions/common/glm/detail/type_gentype.inl @@ -0,0 +1,370 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_gentype.inl +/// @date 2008-10-05 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail{ + +///////////////////////////////// +// Static functions + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::size_type base<vT, cT, rT, pT>::col_size() +{ + return cT; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::size_type base<vT, cT, rT, pT>::row_size() +{ + return rT; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::size_type base<vT, cT, rT, pT>::value_size() +{ + return rT * cT; +} + +template <typename vT, uint cT, uint rT, profile pT> +bool base<vT, cT, rT, pT>::is_scalar() +{ + return rT == 1 && cT == 1; +} + +template <typename vT, uint cT, uint rT, profile pT> +bool base<vT, cT, rT, pT>::is_vector() +{ + return rT == 1; +} + +template <typename vT, uint cT, uint rT, profile pT> +bool base<vT, cT, rT, pT>::is_matrix() +{ + return rT != 1; +} + +///////////////////////////////// +// Constructor + +template <typename vT, uint cT, uint rT, profile pT> +base<vT, cT, rT, pT>::base() +{ + memset(&this->value, 0, cT * rT * sizeof(vT)); +} + +template <typename vT, uint cT, uint rT, profile pT> +base<vT, cT, rT, pT>::base +( + typename base<vT, cT, rT, pT>::class_type const & m +) +{ + for + ( + typename genType<vT, cT, rT, pT>::size_type i = typename base<vT, cT, rT, pT>::size_type(0); + i < base<vT, cT, rT, pT>::col_size(); + ++i + ) + { + this->value[i] = m[i]; + } +} + +template <typename vT, uint cT, uint rT, profile pT> +base<vT, cT, rT, pT>::base +( + typename base<vT, cT, rT, pT>::T const & x +) +{ + if(rT == 1) // vector + { + for + ( + typename base<vT, cT, rT, pT>::size_type i = typename base<vT, cT, rT, pT>::size_type(0); + i < base<vT, cT, rT, pT>::col_size(); + ++i + ) + { + this->value[i][rT] = x; + } + } + else // matrix + { + memset(&this->value, 0, cT * rT * sizeof(vT)); + + typename base<vT, cT, rT, pT>::size_type stop = cT < rT ? cT : rT; + + for + ( + typename base<vT, cT, rT, pT>::size_type i = typename base<vT, cT, rT, pT>::size_type(0); + i < stop; + ++i + ) + { + this->value[i][i] = x; + } + } +} + +template <typename vT, uint cT, uint rT, profile pT> +base<vT, cT, rT, pT>::base +( + typename base<vT, cT, rT, pT>::value_type const * const x +) +{ + memcpy(&this->value, &x.value, cT * rT * sizeof(vT)); +} + +template <typename vT, uint cT, uint rT, profile pT> +base<vT, cT, rT, pT>::base +( + typename base<vT, cT, rT, pT>::col_type const * const x +) +{ + for + ( + typename base<vT, cT, rT, pT>::size_type i = typename base<vT, cT, rT, pT>::size_type(0); + i < base<vT, cT, rT, pT>::col_size(); + ++i + ) + { + this->value[i] = x[i]; + } +} + +template <typename vT, uint cT, uint rT, profile pT> +template <typename vU, uint cU, uint rU, profile pU> +base<vT, cT, rT, pT>::base +( + base<vU, cU, rU, pU> const & m +) +{ + for + ( + typename base<vT, cT, rT, pT>::size_type i = typename base<vT, cT, rT, pT>::size_type(0); + i < base<vT, cT, rT, pT>::col_size(); + ++i + ) + { + this->value[i] = base<vT, cT, rT, pT>(m[i]); + } +} + +////////////////////////////////////// +// Accesses + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::col_type& base<vT, cT, rT, pT>::operator[] +( + typename base<vT, cT, rT, pT>::size_type i +) +{ + return this->value[i]; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::col_type const & base<vT, cT, rT, pT>::operator[] +( + typename base<vT, cT, rT, pT>::size_type i +) const +{ + return this->value[i]; +} + +////////////////////////////////////// +// Unary updatable operators + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::class_type& base<vT, cT, rT, pT>::operator= +( + typename base<vT, cT, rT, pT>::class_type const & x +) +{ + memcpy(&this->value, &x.value, cT * rT * sizeof(vT)); + return *this; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::class_type& base<vT, cT, rT, pT>::operator+= +( + typename base<vT, cT, rT, pT>::T const & x +) +{ + typename base<vT, cT, rT, pT>::size_type stop_col = x.col_size(); + typename base<vT, cT, rT, pT>::size_type stop_row = x.row_size(); + + for(typename base<vT, cT, rT, pT>::size_type j = 0; j < stop_col; ++j) + for(typename base<vT, cT, rT, pT>::size_type i = 0; i < stop_row; ++i) + this->value[j][i] += x; + + return *this; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::class_type& base<vT, cT, rT, pT>::operator+= +( + typename base<vT, cT, rT, pT>::class_type const & x +) +{ + typename base<vT, cT, rT, pT>::size_type stop_col = x.col_size(); + typename base<vT, cT, rT, pT>::size_type stop_row = x.row_size(); + + for(typename base<vT, cT, rT, pT>::size_type j = 0; j < stop_col; ++j) + for(typename base<vT, cT, rT, pT>::size_type i = 0; i < stop_row; ++i) + this->value[j][i] += x[j][i]; + + return *this; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::class_type& base<vT, cT, rT, pT>::operator-= +( + typename base<vT, cT, rT, pT>::T const & x +) +{ + typename base<vT, cT, rT, pT>::size_type stop_col = x.col_size(); + typename base<vT, cT, rT, pT>::size_type stop_row = x.row_size(); + + for(typename base<vT, cT, rT, pT>::size_type j = 0; j < stop_col; ++j) + for(typename base<vT, cT, rT, pT>::size_type i = 0; i < stop_row; ++i) + this->value[j][i] -= x; + + return *this; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::class_type& base<vT, cT, rT, pT>::operator-= +( + typename base<vT, cT, rT, pT>::class_type const & x +) +{ + typename base<vT, cT, rT, pT>::size_type stop_col = x.col_size(); + typename base<vT, cT, rT, pT>::size_type stop_row = x.row_size(); + + for(typename base<vT, cT, rT, pT>::size_type j = 0; j < stop_col; ++j) + for(typename base<vT, cT, rT, pT>::size_type i = 0; i < stop_row; ++i) + this->value[j][i] -= x[j][i]; + + return *this; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::class_type& base<vT, cT, rT, pT>::operator*= +( + typename base<vT, cT, rT, pT>::T const & x +) +{ + typename base<vT, cT, rT, pT>::size_type stop_col = x.col_size(); + typename base<vT, cT, rT, pT>::size_type stop_row = x.row_size(); + + for(typename base<vT, cT, rT, pT>::size_type j = 0; j < stop_col; ++j) + for(typename base<vT, cT, rT, pT>::size_type i = 0; i < stop_row; ++i) + this->value[j][i] *= x; + + return *this; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::class_type& base<vT, cT, rT, pT>::operator*= +( + typename base<vT, cT, rT, pT>::class_type const & x +) +{ + typename base<vT, cT, rT, pT>::size_type stop_col = x.col_size(); + typename base<vT, cT, rT, pT>::size_type stop_row = x.row_size(); + + for(typename base<vT, cT, rT, pT>::size_type j = 0; j < stop_col; ++j) + for(typename base<vT, cT, rT, pT>::size_type i = 0; i < stop_row; ++i) + this->value[j][i] *= x[j][i]; + + return *this; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::class_type& base<vT, cT, rT, pT>::operator/= +( + typename base<vT, cT, rT, pT>::T const & x +) +{ + typename base<vT, cT, rT, pT>::size_type stop_col = x.col_size(); + typename base<vT, cT, rT, pT>::size_type stop_row = x.row_size(); + + for(typename base<vT, cT, rT, pT>::size_type j = 0; j < stop_col; ++j) + for(typename base<vT, cT, rT, pT>::size_type i = 0; i < stop_row; ++i) + this->value[j][i] /= x; + + return *this; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::class_type& base<vT, cT, rT, pT>::operator/= +( + typename base<vT, cT, rT, pT>::class_type const & x +) +{ + typename base<vT, cT, rT, pT>::size_type stop_col = x.col_size(); + typename base<vT, cT, rT, pT>::size_type stop_row = x.row_size(); + + for(typename base<vT, cT, rT, pT>::size_type j = 0; j < stop_col; ++j) + for(typename base<vT, cT, rT, pT>::size_type i = 0; i < stop_row; ++i) + this->value[j][i] /= x[j][i]; + + return *this; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::class_type& base<vT, cT, rT, pT>::operator++ () +{ + typename base<vT, cT, rT, pT>::size_type stop_col = col_size(); + typename base<vT, cT, rT, pT>::size_type stop_row = row_size(); + + for(typename base<vT, cT, rT, pT>::size_type j = 0; j < stop_col; ++j) + for(typename base<vT, cT, rT, pT>::size_type i = 0; i < stop_row; ++i) + ++this->value[j][i]; + + return *this; +} + +template <typename vT, uint cT, uint rT, profile pT> +typename base<vT, cT, rT, pT>::class_type& base<vT, cT, rT, pT>::operator-- () +{ + typename base<vT, cT, rT, pT>::size_type stop_col = col_size(); + typename base<vT, cT, rT, pT>::size_type stop_row = row_size(); + + for(typename base<vT, cT, rT, pT>::size_type j = 0; j < stop_col; ++j) + for(typename base<vT, cT, rT, pT>::size_type i = 0; i < stop_row; ++i) + --this->value[j][i]; + + return *this; +} + +} //namespace detail +} //namespace glm diff --git a/extensions/common/glm/detail/type_half.hpp b/extensions/common/glm/detail/type_half.hpp new file mode 100644 index 0000000000..feb371623f --- /dev/null +++ b/extensions/common/glm/detail/type_half.hpp @@ -0,0 +1,48 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_half.hpp +/// @date 2008-08-17 / 2011-09-20 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" + +namespace glm{ +namespace detail +{ + typedef short hdata; + + GLM_FUNC_DECL float toFloat32(hdata value); + GLM_FUNC_DECL hdata toFloat16(float const & value); + +}//namespace detail +}//namespace glm + +#include "type_half.inl" diff --git a/extensions/common/glm/detail/type_half.inl b/extensions/common/glm/detail/type_half.inl new file mode 100644 index 0000000000..4632bd48e0 --- /dev/null +++ b/extensions/common/glm/detail/type_half.inl @@ -0,0 +1,277 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// +/// This half implementation is based on OpenEXR which is Copyright (c) 2002, +/// Industrial Light & Magic, a division of Lucas Digital Ltd. LLC +/// +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_half.inl +/// @date 2008-08-17 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail +{ + GLM_FUNC_QUALIFIER float overflow() + { + volatile float f = 1e10; + + for(int i = 0; i < 10; ++i) + f *= f; // this will overflow before the for loop terminates + return f; + } + + union uif32 + { + GLM_FUNC_QUALIFIER uif32() : + i(0) + {} + + GLM_FUNC_QUALIFIER uif32(float f) : + f(f) + {} + + GLM_FUNC_QUALIFIER uif32(uint32 i) : + i(i) + {} + + float f; + uint32 i; + }; + + GLM_FUNC_QUALIFIER float toFloat32(hdata value) + { + int s = (value >> 15) & 0x00000001; + int e = (value >> 10) & 0x0000001f; + int m = value & 0x000003ff; + + if(e == 0) + { + if(m == 0) + { + // + // Plus or minus zero + // + + detail::uif32 result; + result.i = (unsigned int)(s << 31); + return result.f; + } + else + { + // + // Denormalized number -- renormalize it + // + + while(!(m & 0x00000400)) + { + m <<= 1; + e -= 1; + } + + e += 1; + m &= ~0x00000400; + } + } + else if(e == 31) + { + if(m == 0) + { + // + // Positive or negative infinity + // + + uif32 result; + result.i = (unsigned int)((s << 31) | 0x7f800000); + return result.f; + } + else + { + // + // Nan -- preserve sign and significand bits + // + + uif32 result; + result.i = (unsigned int)((s << 31) | 0x7f800000 | (m << 13)); + return result.f; + } + } + + // + // Normalized number + // + + e = e + (127 - 15); + m = m << 13; + + // + // Assemble s, e and m. + // + + uif32 Result; + Result.i = (unsigned int)((s << 31) | (e << 23) | m); + return Result.f; + } + + GLM_FUNC_QUALIFIER hdata toFloat16(float const & f) + { + uif32 Entry; + Entry.f = f; + int i = (int)Entry.i; + + // + // Our floating point number, f, is represented by the bit + // pattern in integer i. Disassemble that bit pattern into + // the sign, s, the exponent, e, and the significand, m. + // Shift s into the position where it will go in in the + // resulting half number. + // Adjust e, accounting for the different exponent bias + // of float and half (127 versus 15). + // + + int s = (i >> 16) & 0x00008000; + int e = ((i >> 23) & 0x000000ff) - (127 - 15); + int m = i & 0x007fffff; + + // + // Now reassemble s, e and m into a half: + // + + if(e <= 0) + { + if(e < -10) + { + // + // E is less than -10. The absolute value of f is + // less than half_MIN (f may be a small normalized + // float, a denormalized float or a zero). + // + // We convert f to a half zero. + // + + return hdata(s); + } + + // + // E is between -10 and 0. F is a normalized float, + // whose magnitude is less than __half_NRM_MIN. + // + // We convert f to a denormalized half. + // + + m = (m | 0x00800000) >> (1 - e); + + // + // Round to nearest, round "0.5" up. + // + // Rounding may cause the significand to overflow and make + // our number normalized. Because of the way a half's bits + // are laid out, we don't have to treat this case separately; + // the code below will handle it correctly. + // + + if(m & 0x00001000) + m += 0x00002000; + + // + // Assemble the half from s, e (zero) and m. + // + + return hdata(s | (m >> 13)); + } + else if(e == 0xff - (127 - 15)) + { + if(m == 0) + { + // + // F is an infinity; convert f to a half + // infinity with the same sign as f. + // + + return hdata(s | 0x7c00); + } + else + { + // + // F is a NAN; we produce a half NAN that preserves + // the sign bit and the 10 leftmost bits of the + // significand of f, with one exception: If the 10 + // leftmost bits are all zero, the NAN would turn + // into an infinity, so we have to set at least one + // bit in the significand. + // + + m >>= 13; + + return hdata(s | 0x7c00 | m | (m == 0)); + } + } + else + { + // + // E is greater than zero. F is a normalized float. + // We try to convert f to a normalized half. + // + + // + // Round to nearest, round "0.5" up + // + + if(m & 0x00001000) + { + m += 0x00002000; + + if(m & 0x00800000) + { + m = 0; // overflow in significand, + e += 1; // adjust exponent + } + } + + // + // Handle exponent overflow + // + + if (e > 30) + { + overflow(); // Cause a hardware floating point overflow; + + return hdata(s | 0x7c00); + // if this returns, the half becomes an + } // infinity with the same sign as f. + + // + // Assemble the half from s, e and m. + // + + return hdata(s | (e << 10) | (m >> 13)); + } + } + +}//namespace detail +}//namespace glm diff --git a/extensions/common/glm/detail/type_int.hpp b/extensions/common/glm/detail/type_int.hpp new file mode 100644 index 0000000000..367b3d15e8 --- /dev/null +++ b/extensions/common/glm/detail/type_int.hpp @@ -0,0 +1,326 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_int.hpp +/// @date 2008-08-22 / 2013-03-30 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "setup.hpp" +#if GLM_HAS_MAKE_SIGNED +# include <type_traits> +#endif + +#if GLM_HAS_EXTENDED_INTEGER_TYPE +# include <cstdint> +#endif + +namespace glm{ +namespace detail +{ +# if GLM_HAS_EXTENDED_INTEGER_TYPE + typedef std::int8_t int8; + typedef std::int16_t int16; + typedef std::int32_t int32; + typedef std::int64_t int64; + + typedef std::uint8_t uint8; + typedef std::uint16_t uint16; + typedef std::uint32_t uint32; + typedef std::uint64_t uint64; +# else +# if(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) // C99 detected, 64 bit types available + typedef int64_t sint64; + typedef uint64_t uint64; +# elif GLM_COMPILER & GLM_COMPILER_VC + typedef signed __int64 sint64; + typedef unsigned __int64 uint64; +# elif GLM_COMPILER & GLM_COMPILER_GCC + __extension__ typedef signed long long sint64; + __extension__ typedef unsigned long long uint64; +# else//unknown compiler + typedef signed long long sint64; + typedef unsigned long long uint64; +# endif//GLM_COMPILER + + typedef signed char int8; + typedef signed short int16; + typedef signed int int32; + typedef sint64 int64; + + typedef unsigned char uint8; + typedef unsigned short uint16; + typedef unsigned int uint32; + typedef uint64 uint64; +#endif// + + typedef signed int lowp_int_t; + typedef signed int mediump_int_t; + typedef signed int highp_int_t; + + typedef unsigned int lowp_uint_t; + typedef unsigned int mediump_uint_t; + typedef unsigned int highp_uint_t; + +# if GLM_HAS_MAKE_SIGNED + using std::make_signed; + using std::make_unsigned; + +# else//GLM_HAS_MAKE_SIGNED + template <typename genType> + struct make_signed + {}; + + template <> + struct make_signed<char> + { + typedef char type; + }; + + template <> + struct make_signed<short> + { + typedef short type; + }; + + template <> + struct make_signed<int> + { + typedef int type; + }; + + template <> + struct make_signed<long> + { + typedef long type; + }; + + template <> + struct make_signed<long long> + { + typedef long long type; + }; + + template <> + struct make_signed<unsigned char> + { + typedef char type; + }; + + template <> + struct make_signed<unsigned short> + { + typedef short type; + }; + + template <> + struct make_signed<unsigned int> + { + typedef int type; + }; + + template <> + struct make_signed<unsigned long> + { + typedef long type; + }; + + template <> + struct make_signed<unsigned long long> + { + typedef long long type; + }; + + template <typename genType> + struct make_unsigned + {}; + + template <> + struct make_unsigned<char> + { + typedef unsigned char type; + }; + + template <> + struct make_unsigned<short> + { + typedef unsigned short type; + }; + + template <> + struct make_unsigned<int> + { + typedef unsigned int type; + }; + + template <> + struct make_unsigned<long> + { + typedef unsigned long type; + }; + + template <> + struct make_unsigned<long long> + { + typedef unsigned long long type; + }; + + template <> + struct make_unsigned<unsigned char> + { + typedef unsigned char type; + }; + + template <> + struct make_unsigned<unsigned short> + { + typedef unsigned short type; + }; + + template <> + struct make_unsigned<unsigned int> + { + typedef unsigned int type; + }; + + template <> + struct make_unsigned<unsigned long> + { + typedef unsigned long type; + }; + + template <> + struct make_unsigned<unsigned long long> + { + typedef unsigned long long type; + }; +# endif//GLM_HAS_MAKE_SIGNED +}//namespace detail + + typedef detail::int8 int8; + typedef detail::int16 int16; + typedef detail::int32 int32; + typedef detail::int64 int64; + + typedef detail::uint8 uint8; + typedef detail::uint16 uint16; + typedef detail::uint32 uint32; + typedef detail::uint64 uint64; + + /// @addtogroup core_precision + /// @{ + + /// Low precision signed integer. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.3 Integers</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef detail::lowp_int_t lowp_int; + + /// Medium precision signed integer. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.3 Integers</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef detail::mediump_int_t mediump_int; + + /// High precision signed integer. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.3 Integers</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef detail::highp_int_t highp_int; + + /// Low precision unsigned integer. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.3 Integers</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef detail::lowp_uint_t lowp_uint; + + /// Medium precision unsigned integer. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.3 Integers</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef detail::mediump_uint_t mediump_uint; + + /// High precision unsigned integer. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.3 Integers</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef detail::highp_uint_t highp_uint; + +#if(!defined(GLM_PRECISION_HIGHP_INT) && !defined(GLM_PRECISION_MEDIUMP_INT) && !defined(GLM_PRECISION_LOWP_INT)) + typedef mediump_int int_t; +#elif(defined(GLM_PRECISION_HIGHP_INT) && !defined(GLM_PRECISION_MEDIUMP_INT) && !defined(GLM_PRECISION_LOWP_INT)) + typedef highp_int int_t; +#elif(!defined(GLM_PRECISION_HIGHP_INT) && defined(GLM_PRECISION_MEDIUMP_INT) && !defined(GLM_PRECISION_LOWP_INT)) + typedef mediump_int int_t; +#elif(!defined(GLM_PRECISION_HIGHP_INT) && !defined(GLM_PRECISION_MEDIUMP_INT) && defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_int int_t; +#else +# error "GLM error: multiple default precision requested for signed interger types" +#endif + +#if(!defined(GLM_PRECISION_HIGHP_UINT) && !defined(GLM_PRECISION_MEDIUMP_UINT) && !defined(GLM_PRECISION_LOWP_UINT)) + typedef mediump_uint uint_t; +#elif(defined(GLM_PRECISION_HIGHP_UINT) && !defined(GLM_PRECISION_MEDIUMP_UINT) && !defined(GLM_PRECISION_LOWP_UINT)) + typedef highp_uint uint_t; +#elif(!defined(GLM_PRECISION_HIGHP_UINT) && defined(GLM_PRECISION_MEDIUMP_UINT) && !defined(GLM_PRECISION_LOWP_UINT)) + typedef mediump_uint uint_t; +#elif(!defined(GLM_PRECISION_HIGHP_UINT) && !defined(GLM_PRECISION_MEDIUMP_UINT) && defined(GLM_PRECISION_LOWP_UINT)) + typedef lowp_uint uint_t; +#else +# error "GLM error: multiple default precision requested for unsigned interger types" +#endif + + /// Unsigned integer type. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.3 Integers</a> + typedef unsigned int uint; + + /// @} + +//////////////////// +// check type sizes +#ifndef GLM_STATIC_ASSERT_NULL + GLM_STATIC_ASSERT(sizeof(glm::int8) == 1, "int8 size isn't 1 byte on this platform"); + GLM_STATIC_ASSERT(sizeof(glm::int16) == 2, "int16 size isn't 2 bytes on this platform"); + GLM_STATIC_ASSERT(sizeof(glm::int32) == 4, "int32 size isn't 4 bytes on this platform"); + GLM_STATIC_ASSERT(sizeof(glm::int64) == 8, "int64 size isn't 8 bytes on this platform"); + + GLM_STATIC_ASSERT(sizeof(glm::uint8) == 1, "uint8 size isn't 1 byte on this platform"); + GLM_STATIC_ASSERT(sizeof(glm::uint16) == 2, "uint16 size isn't 2 bytes on this platform"); + GLM_STATIC_ASSERT(sizeof(glm::uint32) == 4, "uint32 size isn't 4 bytes on this platform"); + GLM_STATIC_ASSERT(sizeof(glm::uint64) == 8, "uint64 size isn't 8 bytes on this platform"); +#endif//GLM_STATIC_ASSERT_NULL + +}//namespace glm diff --git a/extensions/common/glm/detail/type_mat.hpp b/extensions/common/glm/detail/type_mat.hpp new file mode 100644 index 0000000000..65280d590a --- /dev/null +++ b/extensions/common/glm/detail/type_mat.hpp @@ -0,0 +1,793 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat.hpp +/// @date 2010-01-26 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "precision.hpp" + +namespace glm{ +namespace detail +{ + template <typename T, precision P, template <class, precision> class colType, template <class, precision> class rowType> + struct outerProduct_trait{}; +}//namespace detail + + template <typename T, precision P> struct tvec2; + template <typename T, precision P> struct tvec3; + template <typename T, precision P> struct tvec4; + template <typename T, precision P> struct tmat2x2; + template <typename T, precision P> struct tmat2x3; + template <typename T, precision P> struct tmat2x4; + template <typename T, precision P> struct tmat3x2; + template <typename T, precision P> struct tmat3x3; + template <typename T, precision P> struct tmat3x4; + template <typename T, precision P> struct tmat4x2; + template <typename T, precision P> struct tmat4x3; + template <typename T, precision P> struct tmat4x4; + + /// @addtogroup core_precision + /// @{ + + /// 2 columns of 2 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, lowp> lowp_mat2; + + /// 2 columns of 2 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, mediump> mediump_mat2; + + /// 2 columns of 2 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, highp> highp_mat2; + + /// 2 columns of 2 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, lowp> lowp_mat2x2; + + /// 2 columns of 2 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, mediump> mediump_mat2x2; + + /// 2 columns of 2 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, highp> highp_mat2x2; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 2 columns of 3 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x3<float, lowp> lowp_mat2x3; + + /// 2 columns of 3 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x3<float, mediump> mediump_mat2x3; + + /// 2 columns of 3 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x3<float, highp> highp_mat2x3; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 2 columns of 4 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x4<float, lowp> lowp_mat2x4; + + /// 2 columns of 4 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x4<float, mediump> mediump_mat2x4; + + /// 2 columns of 4 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x4<float, highp> highp_mat2x4; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 3 columns of 2 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x2<float, lowp> lowp_mat3x2; + + /// 3 columns of 2 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x2<float, mediump> mediump_mat3x2; + + /// 3 columns of 2 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x2<float, highp> highp_mat3x2; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 3 columns of 3 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, lowp> lowp_mat3; + + /// 3 columns of 3 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, mediump> mediump_mat3; + + /// 3 columns of 3 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, highp> highp_mat3; + + /// 3 columns of 3 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, lowp> lowp_mat3x3; + + /// 3 columns of 3 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, mediump> mediump_mat3x3; + + /// 3 columns of 3 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, highp> highp_mat3x3; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 3 columns of 4 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x4<float, lowp> lowp_mat3x4; + + /// 3 columns of 4 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x4<float, mediump> mediump_mat3x4; + + /// 3 columns of 4 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x4<float, highp> highp_mat3x4; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 4 columns of 2 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x2<float, lowp> lowp_mat4x2; + + /// 4 columns of 2 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x2<float, mediump> mediump_mat4x2; + + /// 4 columns of 2 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x2<float, highp> highp_mat4x2; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 4 columns of 3 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x3<float, lowp> lowp_mat4x3; + + /// 4 columns of 3 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x3<float, mediump> mediump_mat4x3; + + /// 4 columns of 3 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x3<float, highp> highp_mat4x3; + + /// @} + + + /// @addtogroup core_precision + /// @{ + + /// 4 columns of 4 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, lowp> lowp_mat4; + + /// 4 columns of 4 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, mediump> mediump_mat4; + + /// 4 columns of 4 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, highp> highp_mat4; + + /// 4 columns of 4 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, lowp> lowp_mat4x4; + + /// 4 columns of 4 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, mediump> mediump_mat4x4; + + /// 4 columns of 4 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, highp> highp_mat4x4; + + /// @} + + /// @addtogroup core_types + /// @{ + + ////////////////////////// + // Float definition + +#if(defined(GLM_PRECISION_LOWP_FLOAT)) + typedef lowp_mat2x2 mat2x2; + typedef lowp_mat2x3 mat2x3; + typedef lowp_mat2x4 mat2x4; + typedef lowp_mat3x2 mat3x2; + typedef lowp_mat3x3 mat3x3; + typedef lowp_mat3x4 mat3x4; + typedef lowp_mat4x2 mat4x2; + typedef lowp_mat4x3 mat4x3; + typedef lowp_mat4x4 mat4x4; +#elif(defined(GLM_PRECISION_MEDIUMP_FLOAT)) + typedef mediump_mat2x2 mat2x2; + typedef mediump_mat2x3 mat2x3; + typedef mediump_mat2x4 mat2x4; + typedef mediump_mat3x2 mat3x2; + typedef mediump_mat3x3 mat3x3; + typedef mediump_mat3x4 mat3x4; + typedef mediump_mat4x2 mat4x2; + typedef mediump_mat4x3 mat4x3; + typedef mediump_mat4x4 mat4x4; +#else + //! 2 columns of 2 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_mat2x2 mat2x2; + + //! 2 columns of 3 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_mat2x3 mat2x3; + + //! 2 columns of 4 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_mat2x4 mat2x4; + + //! 3 columns of 2 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_mat3x2 mat3x2; + + //! 3 columns of 3 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_mat3x3 mat3x3; + + //! 3 columns of 4 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_mat3x4 mat3x4; + + //! 4 columns of 2 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_mat4x2 mat4x2; + + //! 4 columns of 3 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_mat4x3 mat4x3; + + //! 4 columns of 4 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_mat4x4 mat4x4; + +#endif//GLM_PRECISION + + //! 2 columns of 2 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef mat2x2 mat2; + + //! 3 columns of 3 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef mat3x3 mat3; + + //! 4 columns of 4 components matrix of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef mat4x4 mat4; + + ////////////////////////// + // Double definition + + /// @addtogroup core_precision + /// @{ + + /// 2 columns of 2 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<double, lowp> lowp_dmat2; + + /// 2 columns of 2 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<double, mediump> mediump_dmat2; + + /// 2 columns of 2 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<double, highp> highp_dmat2; + + /// 2 columns of 2 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<double, lowp> lowp_dmat2x2; + + /// 2 columns of 2 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<double, mediump> mediump_dmat2x2; + + /// 2 columns of 2 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<double, highp> highp_dmat2x2; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 2 columns of 3 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x3<double, lowp> lowp_dmat2x3; + + /// 2 columns of 3 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x3<double, mediump> mediump_dmat2x3; + + /// 2 columns of 3 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x3<double, highp> highp_dmat2x3; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 2 columns of 4 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x4<double, lowp> lowp_dmat2x4; + + /// 2 columns of 4 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x4<double, mediump> mediump_dmat2x4; + + /// 2 columns of 4 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x4<double, highp> highp_dmat2x4; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 3 columns of 2 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x2<double, lowp> lowp_dmat3x2; + + /// 3 columns of 2 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x2<double, mediump> mediump_dmat3x2; + + /// 3 columns of 2 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x2<double, highp> highp_dmat3x2; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 3 columns of 3 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, lowp> lowp_dmat3; + + /// 3 columns of 3 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<double, mediump> mediump_dmat3; + + /// 3 columns of 3 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<double, highp> highp_dmat3; + + /// 3 columns of 3 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<double, lowp> lowp_dmat3x3; + + /// 3 columns of 3 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<double, mediump> mediump_dmat3x3; + + /// 3 columns of 3 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<double, highp> highp_dmat3x3; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 3 columns of 4 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x4<double, lowp> lowp_dmat3x4; + + /// 3 columns of 4 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x4<double, mediump> mediump_dmat3x4; + + /// 3 columns of 4 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x4<double, highp> highp_dmat3x4; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 4 columns of 2 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x2<double, lowp> lowp_dmat4x2; + + /// 4 columns of 2 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x2<double, mediump> mediump_dmat4x2; + + /// 4 columns of 2 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x2<double, highp> highp_dmat4x2; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 4 columns of 3 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x3<double, lowp> lowp_dmat4x3; + + /// 4 columns of 3 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x3<double, mediump> mediump_dmat4x3; + + /// 4 columns of 3 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x3<double, highp> highp_dmat4x3; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 4 columns of 4 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<double, lowp> lowp_dmat4; + + /// 4 columns of 4 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<double, mediump> mediump_dmat4; + + /// 4 columns of 4 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<double, highp> highp_dmat4; + + /// 4 columns of 4 components matrix of low precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<double, lowp> lowp_dmat4x4; + + /// 4 columns of 4 components matrix of medium precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<double, mediump> mediump_dmat4x4; + + /// 4 columns of 4 components matrix of high precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<double, highp> highp_dmat4x4; + + /// @} + +#if(defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef lowp_dmat2x2 dmat2x2; + typedef lowp_dmat2x3 dmat2x3; + typedef lowp_dmat2x4 dmat2x4; + typedef lowp_dmat3x2 dmat3x2; + typedef lowp_dmat3x3 dmat3x3; + typedef lowp_dmat3x4 dmat3x4; + typedef lowp_dmat4x2 dmat4x2; + typedef lowp_dmat4x3 dmat4x3; + typedef lowp_dmat4x4 dmat4x4; +#elif(defined(GLM_PRECISION_MEDIUMP_DOUBLE)) + typedef mediump_dmat2x2 dmat2x2; + typedef mediump_dmat2x3 dmat2x3; + typedef mediump_dmat2x4 dmat2x4; + typedef mediump_dmat3x2 dmat3x2; + typedef mediump_dmat3x3 dmat3x3; + typedef mediump_dmat3x4 dmat3x4; + typedef mediump_dmat4x2 dmat4x2; + typedef mediump_dmat4x3 dmat4x3; + typedef mediump_dmat4x4 dmat4x4; +#else //defined(GLM_PRECISION_HIGHP_DOUBLE) + + //! 2 * 2 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat2x2 dmat2; + + //! 3 * 3 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat3x3 dmat3; + + //! 4 * 4 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat4x4 dmat4; + + //! 2 * 2 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat2x2 dmat2x2; + + //! 2 * 3 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat2x3 dmat2x3; + + //! 2 * 4 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat2x4 dmat2x4; + + //! 3 * 2 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat3x2 dmat3x2; + + /// 3 * 3 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat3x3 dmat3x3; + + /// 3 * 4 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat3x4 dmat3x4; + + /// 4 * 2 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat4x2 dmat4x2; + + /// 4 * 3 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat4x3 dmat4x3; + + /// 4 * 4 matrix of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + typedef highp_dmat4x4 dmat4x4; + +#endif//GLM_PRECISION + + /// @} +}//namespace glm diff --git a/extensions/common/glm/detail/type_mat.inl b/extensions/common/glm/detail/type_mat.inl new file mode 100644 index 0000000000..6680af3357 --- /dev/null +++ b/extensions/common/glm/detail/type_mat.inl @@ -0,0 +1,32 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat.inl +/// @date 2011-06-15 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + diff --git a/extensions/common/glm/detail/type_mat2x2.hpp b/extensions/common/glm/detail/type_mat2x2.hpp new file mode 100644 index 0000000000..b4714cdb29 --- /dev/null +++ b/extensions/common/glm/detail/type_mat2x2.hpp @@ -0,0 +1,223 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat2x2.hpp +/// @date 2005-01-27 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../fwd.hpp" +#include "type_vec2.hpp" +#include "type_mat.hpp" +#include <limits> +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tmat2x2 + { + typedef tvec2<T, P> col_type; + typedef tvec2<T, P> row_type; + typedef tmat2x2<T, P> type; + typedef tmat2x2<T, P> transpose_type; + typedef T value_type; + + template <typename U, precision Q> + friend tvec2<U, Q> operator/(tmat2x2<U, Q> const & m, tvec2<U, Q> const & v); + template <typename U, precision Q> + friend tvec2<U, Q> operator/(tvec2<U, Q> const & v, tmat2x2<U, Q> const & m); + + private: + /// @cond DETAIL + col_type value[2]; + /// @endcond + + public: + ////////////////////////////////////// + // Constructors + GLM_FUNC_DECL tmat2x2(); + GLM_FUNC_DECL tmat2x2(tmat2x2<T, P> const & m); + template <precision Q> + GLM_FUNC_DECL tmat2x2(tmat2x2<T, Q> const & m); + + GLM_FUNC_DECL explicit tmat2x2(ctor); + GLM_FUNC_DECL explicit tmat2x2(T const & x); + GLM_FUNC_DECL tmat2x2( + T const & x1, T const & y1, + T const & x2, T const & y2); + GLM_FUNC_DECL tmat2x2( + col_type const & v1, + col_type const & v2); + + ////////////////////////////////////// + // Conversions + template <typename U, typename V, typename M, typename N> + GLM_FUNC_DECL tmat2x2( + U const & x1, V const & y1, + M const & x2, N const & y2); + + template <typename U, typename V> + GLM_FUNC_DECL tmat2x2( + tvec2<U, P> const & v1, + tvec2<V, P> const & v2); + + ////////////////////////////////////// + // Matrix conversions + +# ifdef GLM_FORCE_EXPLICIT_CTOR + template <typename U, precision Q> + GLM_FUNC_DECL explicit tmat2x2(tmat2x2<U, Q> const & m); +# else + template <typename U, precision Q> + GLM_FUNC_DECL tmat2x2(tmat2x2<U, Q> const & m); +# endif + + GLM_FUNC_DECL explicit tmat2x2(tmat3x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x2(tmat4x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x2(tmat2x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x2(tmat3x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x2(tmat2x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x2(tmat4x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x2(tmat3x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x2(tmat4x3<T, P> const & x); + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_t size() const; + + GLM_FUNC_DECL col_type & operator[](size_type i); + GLM_FUNC_DECL col_type const & operator[](size_type i) const; +# else + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL col_type const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tmat2x2<T, P> & operator=(tmat2x2<T, P> const & v); + + template <typename U> + GLM_FUNC_DECL tmat2x2<T, P> & operator=(tmat2x2<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat2x2<T, P> & operator+=(U s); + template <typename U> + GLM_FUNC_DECL tmat2x2<T, P> & operator+=(tmat2x2<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat2x2<T, P> & operator-=(U s); + template <typename U> + GLM_FUNC_DECL tmat2x2<T, P> & operator-=(tmat2x2<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat2x2<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tmat2x2<T, P> & operator*=(tmat2x2<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat2x2<T, P> & operator/=(U s); + template <typename U> + GLM_FUNC_DECL tmat2x2<T, P> & operator/=(tmat2x2<U, P> const & m); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tmat2x2<T, P> & operator++ (); + GLM_FUNC_DECL tmat2x2<T, P> & operator-- (); + GLM_FUNC_DECL tmat2x2<T, P> operator++(int); + GLM_FUNC_DECL tmat2x2<T, P> operator--(int); + }; + + // Binary operators + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator+(tmat2x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator+(T const & s, tmat2x2<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator+(tmat2x2<T, P> const & m1, tmat2x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator-(tmat2x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator-(T const & s, tmat2x2<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator-(tmat2x2<T, P> const & m1, tmat2x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator*(tmat2x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator*(T const & s, tmat2x2<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat2x2<T, P>::col_type operator*(tmat2x2<T, P> const & m, typename tmat2x2<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat2x2<T, P>::row_type operator*(typename tmat2x2<T, P>::col_type const & v, tmat2x2<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator*(tmat2x2<T, P> const & m1, tmat2x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> operator*(tmat2x2<T, P> const & m1, tmat3x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> operator*(tmat2x2<T, P> const & m1, tmat4x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator/(tmat2x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator/(T const & s, tmat2x2<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat2x2<T, P>::col_type operator/(tmat2x2<T, P> const & m, typename tmat2x2<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat2x2<T, P>::row_type operator/(typename tmat2x2<T, P>::col_type const & v, tmat2x2<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator/(tmat2x2<T, P> const & m1, tmat2x2<T, P> const & m2); + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> const operator-(tmat2x2<T, P> const & m); +} //namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat2x2.inl" +#endif diff --git a/extensions/common/glm/detail/type_mat2x2.inl b/extensions/common/glm/detail/type_mat2x2.inl new file mode 100644 index 0000000000..4a19cb9a8f --- /dev/null +++ b/extensions/common/glm/detail/type_mat2x2.inl @@ -0,0 +1,548 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat2x2.inl +/// @date 2005-01-16 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> compute_inverse(tmat2x2<T, P> const & m) + { + T OneOverDeterminant = static_cast<T>(1) / ( + + m[0][0] * m[1][1] + - m[1][0] * m[0][1]); + + tmat2x2<T, P> Inverse( + + m[1][1] * OneOverDeterminant, + - m[0][1] * OneOverDeterminant, + - m[1][0] * OneOverDeterminant, + + m[0][0] * OneOverDeterminant); + + return Inverse; + } +}//namespace detail + + ////////////////////////////////////////////////////////////// + // Constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2() + { +# ifndef GLM_FORCE_NO_CTOR_INIT + this->value[0] = col_type(1, 0); + this->value[1] = col_type(0, 1); +# endif + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tmat2x2<T, P> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + } + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tmat2x2<T, Q> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(T const & s) + { + this->value[0] = col_type(s, 0); + this->value[1] = col_type(0, s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2 + ( + T const & x0, T const & y0, + T const & x1, T const & y1 + ) + { + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(col_type const & v0, col_type const & v1) + { + this->value[0] = v0; + this->value[1] = v1; + } + + ////////////////////////////////////// + // Conversion constructors + template <typename T, precision P> + template <typename X1, typename Y1, typename X2, typename Y2> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2 + ( + X1 const & x1, Y1 const & y1, + X2 const & x2, Y2 const & y2 + ) + { + this->value[0] = col_type(static_cast<T>(x1), value_type(y1)); + this->value[1] = col_type(static_cast<T>(x2), value_type(y2)); + } + + template <typename T, precision P> + template <typename V1, typename V2> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tvec2<V1, P> const & v1, tvec2<V2, P> const & v2) + { + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + } + + ////////////////////////////////////////////////////////////// + // mat2x2 matrix conversions + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tmat2x2<U, Q> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tmat3x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tmat4x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tmat2x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tmat3x2<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tmat2x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tmat4x2<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tmat3x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(tmat4x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat2x2<T, P>::size_type tmat2x2<T, P>::size() const + { + return 2; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::col_type & tmat2x2<T, P>::operator[](typename tmat2x2<T, P>::size_type i) + { + assert(i < this->size()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::col_type const & tmat2x2<T, P>::operator[](typename tmat2x2<T, P>::size_type i) const + { + assert(i < this->size()); + return this->value[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat2x2<T, P>::length_type tmat2x2<T, P>::length() const + { + return 2; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::col_type & tmat2x2<T, P>::operator[](typename tmat2x2<T, P>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::col_type const & tmat2x2<T, P>::operator[](typename tmat2x2<T, P>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////////////////////////////// + // Unary updatable operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator=(tmat2x2<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator=(tmat2x2<U, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator+=(tmat2x2<U, P> const & m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator-=(tmat2x2<U, P> const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator*=(tmat2x2<U, P> const & m) + { + return (*this = *this * m); + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator/=(tmat2x2<U, P> const & m) + { + return (*this = *this * detail::compute_inverse<T, P>(m)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> tmat2x2<T, P>::operator++(int) + { + tmat2x2<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> tmat2x2<T, P>::operator--(int) + { + tmat2x2<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////////////////////////////// + // Binary operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator+(tmat2x2<T, P> const & m, T const & s) + { + return tmat2x2<T, P>( + m[0] + s, + m[1] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator+(T const & s, tmat2x2<T, P> const & m) + { + return tmat2x2<T, P>( + m[0] + s, + m[1] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator+(tmat2x2<T, P> const & m1, tmat2x2<T, P> const & m2) + { + return tmat2x2<T, P>( + m1[0] + m2[0], + m1[1] + m2[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator-(tmat2x2<T, P> const & m, T const & s) + { + return tmat2x2<T, P>( + m[0] - s, + m[1] - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator-(T const & s, tmat2x2<T, P> const & m) + { + return tmat2x2<T, P>( + s - m[0], + s - m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator-(tmat2x2<T, P> const & m1, tmat2x2<T, P> const & m2) + { + return tmat2x2<T, P>( + m1[0] - m2[0], + m1[1] - m2[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator*(tmat2x2<T, P> const & m, T const & s) + { + return tmat2x2<T, P>( + m[0] * s, + m[1] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator*(T const & s, tmat2x2<T, P> const & m) + { + return tmat2x2<T, P>( + m[0] * s, + m[1] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::col_type operator* + ( + tmat2x2<T, P> const & m, + typename tmat2x2<T, P>::row_type const & v + ) + { + return tvec2<T, P>( + m[0][0] * v.x + m[1][0] * v.y, + m[0][1] * v.x + m[1][1] * v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::row_type operator* + ( + typename tmat2x2<T, P>::col_type const & v, + tmat2x2<T, P> const & m + ) + { + return tvec2<T, P>( + v.x * m[0][0] + v.y * m[0][1], + v.x * m[1][0] + v.y * m[1][1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator*(tmat2x2<T, P> const & m1, tmat2x2<T, P> const & m2) + { + return tmat2x2<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> operator*(tmat2x2<T, P> const & m1, tmat3x2<T, P> const & m2) + { + return tmat3x2<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> operator*(tmat2x2<T, P> const & m1, tmat4x2<T, P> const & m2) + { + return tmat4x2<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator/(tmat2x2<T, P> const & m, T const & s) + { + return tmat2x2<T, P>( + m[0] / s, + m[1] / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator/(T const & s, tmat2x2<T, P> const & m) + { + return tmat2x2<T, P>( + s / m[0], + s / m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::col_type operator/(tmat2x2<T, P> const & m, typename tmat2x2<T, P>::row_type const & v) + { + return detail::compute_inverse<T, P>(m) * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::row_type operator/(typename tmat2x2<T, P>::col_type const & v, tmat2x2<T, P> const & m) + { + return v * detail::compute_inverse<T, P>(m); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator/(tmat2x2<T, P> const & m1, tmat2x2<T, P> const & m2) + { + tmat2x2<T, P> m1_copy(m1); + return m1_copy /= m2; + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> const operator-(tmat2x2<T, P> const & m) + { + return tmat2x2<T, P>( + -m[0], + -m[1]); + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tmat2x2<T, P> const & m1, tmat2x2<T, P> const & m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tmat2x2<T, P> const & m1, tmat2x2<T, P> const & m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]); + } +} //namespace glm diff --git a/extensions/common/glm/detail/type_mat2x3.hpp b/extensions/common/glm/detail/type_mat2x3.hpp new file mode 100644 index 0000000000..8da3c164e2 --- /dev/null +++ b/extensions/common/glm/detail/type_mat2x3.hpp @@ -0,0 +1,201 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat2x3.hpp +/// @date 2006-10-01 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../fwd.hpp" +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include "type_mat.hpp" +#include <limits> +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tmat2x3 + { + typedef tvec3<T, P> col_type; + typedef tvec2<T, P> row_type; + typedef tmat2x3<T, P> type; + typedef tmat3x2<T, P> transpose_type; + typedef T value_type; + + private: + /// @cond DETAIL + col_type value[2]; + /// @endcond + + public: + // Constructors + GLM_FUNC_DECL tmat2x3(); + GLM_FUNC_DECL tmat2x3(tmat2x3<T, P> const & m); + template <precision Q> + GLM_FUNC_DECL tmat2x3(tmat2x3<T, Q> const & m); + + GLM_FUNC_DECL explicit tmat2x3(ctor); + GLM_FUNC_DECL explicit tmat2x3(T const & s); + GLM_FUNC_DECL tmat2x3( + T const & x0, T const & y0, T const & z0, + T const & x1, T const & y1, T const & z1); + GLM_FUNC_DECL tmat2x3( + col_type const & v0, + col_type const & v1); + + ////////////////////////////////////// + // Conversions + + template <typename X1, typename Y1, typename Z1, typename X2, typename Y2, typename Z2> + GLM_FUNC_DECL tmat2x3( + X1 const & x1, Y1 const & y1, Z1 const & z1, + X2 const & x2, Y2 const & y2, Z2 const & z2); + + template <typename U, typename V> + GLM_FUNC_DECL tmat2x3( + tvec3<U, P> const & v1, + tvec3<V, P> const & v2); + + ////////////////////////////////////// + // Matrix conversion + +# ifdef GLM_FORCE_EXPLICIT_CTOR + template <typename U, precision Q> + GLM_FUNC_DECL explicit tmat2x3(tmat2x3<U, Q> const & m); +# else + template <typename U, precision Q> + GLM_FUNC_DECL tmat2x3(tmat2x3<U, Q> const & m); +# endif + + GLM_FUNC_DECL explicit tmat2x3(tmat2x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x3(tmat3x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x3(tmat4x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x3(tmat2x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x3(tmat3x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x3(tmat3x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x3(tmat4x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x3(tmat4x3<T, P> const & x); + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_t size() const; + + GLM_FUNC_DECL col_type & operator[](size_type i); + GLM_FUNC_DECL col_type const & operator[](size_type i) const; +# else + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL col_type const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tmat2x3<T, P> & operator=(tmat2x3<T, P> const & m); + + template <typename U> + GLM_FUNC_DECL tmat2x3<T, P> & operator=(tmat2x3<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat2x3<T, P> & operator+=(U s); + template <typename U> + GLM_FUNC_DECL tmat2x3<T, P> & operator+=(tmat2x3<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat2x3<T, P> & operator-=(U s); + template <typename U> + GLM_FUNC_DECL tmat2x3<T, P> & operator-=(tmat2x3<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat2x3<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tmat2x3<T, P> & operator/=(U s); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tmat2x3<T, P> & operator++ (); + GLM_FUNC_DECL tmat2x3<T, P> & operator-- (); + GLM_FUNC_DECL tmat2x3<T, P> operator++(int); + GLM_FUNC_DECL tmat2x3<T, P> operator--(int); + }; + + // Binary operators + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator+(tmat2x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator+(tmat2x3<T, P> const & m1, tmat2x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator-(tmat2x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator-(tmat2x3<T, P> const & m1, tmat2x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator*(tmat2x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator*(T const & s, tmat2x3<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat2x3<T, P>::col_type operator*(tmat2x3<T, P> const & m, typename tmat2x3<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat2x3<T, P>::row_type operator*(typename tmat2x3<T, P>::col_type const & v, tmat2x3<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator*(tmat2x3<T, P> const & m1, tmat2x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator*(tmat2x3<T, P> const & m1, tmat3x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> operator*(tmat2x3<T, P> const & m1, tmat4x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator/(tmat2x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator/(T const & s, tmat2x3<T, P> const & m); + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> const operator-(tmat2x3<T, P> const & m); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat2x3.inl" +#endif diff --git a/extensions/common/glm/detail/type_mat2x3.inl b/extensions/common/glm/detail/type_mat2x3.inl new file mode 100644 index 0000000000..5db880e7b6 --- /dev/null +++ b/extensions/common/glm/detail/type_mat2x3.inl @@ -0,0 +1,506 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat2x3.inl +/// @date 2006-08-05 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + ////////////////////////////////////////////////////////////// + // Constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3() + { +# ifndef GLM_FORCE_NO_CTOR_INIT + this->value[0] = col_type(1, 0, 0); + this->value[1] = col_type(0, 1, 0); +# endif + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tmat2x3<T, P> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + } + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tmat2x3<T, Q> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(T const & s) + { + this->value[0] = col_type(s, 0, 0); + this->value[1] = col_type(0, s, 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3 + ( + T const & x0, T const & y0, T const & z0, + T const & x1, T const & y1, T const & z1 + ) + { + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(col_type const & v0, col_type const & v1) + { + this->value[0] = v0; + this->value[1] = v1; + } + + ////////////////////////////////////// + // Conversion constructors + template <typename T, precision P> + template < + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3 + ( + X1 const & x1, Y1 const & y1, Z1 const & z1, + X2 const & x2, Y2 const & y2, Z2 const & z2 + ) + { + this->value[0] = col_type(static_cast<T>(x1), value_type(y1), value_type(z1)); + this->value[1] = col_type(static_cast<T>(x2), value_type(y2), value_type(z2)); + } + + template <typename T, precision P> + template <typename V1, typename V2> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tvec3<V1, P> const & v1, tvec3<V2, P> const & v2) + { + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + } + + ////////////////////////////////////// + // Matrix conversions + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tmat2x3<U, Q> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tmat2x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tmat3x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tmat4x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tmat2x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tmat3x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tmat3x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tmat4x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>::tmat2x3(tmat4x3<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + } + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat2x3<T, P>::size_type tmat2x3<T, P>::size() const + { + return 2; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x3<T, P>::col_type & tmat2x3<T, P>::operator[](typename tmat2x3<T, P>::size_type i) + { + assert(i < this->size()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x3<T, P>::col_type const & tmat2x3<T, P>::operator[](typename tmat2x3<T, P>::size_type i) const + { + assert(i < this->size()); + return this->value[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat2x3<T, P>::length_type tmat2x3<T, P>::length() const + { + return 2; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x3<T, P>::col_type & tmat2x3<T, P>::operator[](typename tmat2x3<T, P>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x3<T, P>::col_type const & tmat2x3<T, P>::operator[](typename tmat2x3<T, P>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////////////////////////////// + // Unary updatable operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P>& tmat2x3<T, P>::operator=(tmat2x3<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x3<T, P>& tmat2x3<T, P>::operator=(tmat2x3<U, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x3<T, P> & tmat2x3<T, P>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x3<T, P>& tmat2x3<T, P>::operator+=(tmat2x3<U, P> const & m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x3<T, P>& tmat2x3<T, P>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x3<T, P>& tmat2x3<T, P>::operator-=(tmat2x3<U, P> const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x3<T, P>& tmat2x3<T, P>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x3<T, P> & tmat2x3<T, P>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> & tmat2x3<T, P>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> & tmat2x3<T, P>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> tmat2x3<T, P>::operator++(int) + { + tmat2x3<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> tmat2x3<T, P>::operator--(int) + { + tmat2x3<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////////////////////////////// + // Binary operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> operator+(tmat2x3<T, P> const & m, T const & s) + { + return tmat2x3<T, P>( + m[0] + s, + m[1] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> operator+(tmat2x3<T, P> const & m1, tmat2x3<T, P> const & m2) + { + return tmat2x3<T, P>( + m1[0] + m2[0], + m1[1] + m2[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> operator-(tmat2x3<T, P> const & m, T const & s) + { + return tmat2x3<T, P>( + m[0] - s, + m[1] - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> operator-(tmat2x3<T, P> const & m1, tmat2x3<T, P> const & m2) + { + return tmat2x3<T, P>( + m1[0] - m2[0], + m1[1] - m2[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> operator*(tmat2x3<T, P> const & m, T const & s) + { + return tmat2x3<T, P>( + m[0] * s, + m[1] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> operator*(T const & s, tmat2x3<T, P> const & m) + { + return tmat2x3<T, P>( + m[0] * s, + m[1] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x3<T, P>::col_type operator* + ( + tmat2x3<T, P> const & m, + typename tmat2x3<T, P>::row_type const & v) + { + return typename tmat2x3<T, P>::col_type( + m[0][0] * v.x + m[1][0] * v.y, + m[0][1] * v.x + m[1][1] * v.y, + m[0][2] * v.x + m[1][2] * v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x3<T, P>::row_type operator* + ( + typename tmat2x3<T, P>::col_type const & v, + tmat2x3<T, P> const & m) + { + return typename tmat2x3<T, P>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> operator*(tmat2x3<T, P> const & m1, tmat2x2<T, P> const & m2) + { + return tmat2x3<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator*(tmat2x3<T, P> const & m1, tmat3x2<T, P> const & m2) + { + T SrcA00 = m1[0][0]; + T SrcA01 = m1[0][1]; + T SrcA02 = m1[0][2]; + T SrcA10 = m1[1][0]; + T SrcA11 = m1[1][1]; + T SrcA12 = m1[1][2]; + + T SrcB00 = m2[0][0]; + T SrcB01 = m2[0][1]; + T SrcB10 = m2[1][0]; + T SrcB11 = m2[1][1]; + T SrcB20 = m2[2][0]; + T SrcB21 = m2[2][1]; + + tmat3x3<T, P> Result(uninitialize); + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> operator*(tmat2x3<T, P> const & m1, tmat4x2<T, P> const & m2) + { + return tmat4x3<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1], + m1[0][2] * m2[3][0] + m1[1][2] * m2[3][1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> operator/(tmat2x3<T, P> const & m, T const & s) + { + return tmat2x3<T, P>( + m[0] / s, + m[1] / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> operator/(T const & s, tmat2x3<T, P> const & m) + { + return tmat2x3<T, P>( + s / m[0], + s / m[1]); + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> const operator-(tmat2x3<T, P> const & m) + { + return tmat2x3<T, P>( + -m[0], + -m[1]); + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tmat2x3<T, P> const & m1, tmat2x3<T, P> const & m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tmat2x3<T, P> const & m1, tmat2x3<T, P> const & m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]); + } +} //namespace glm diff --git a/extensions/common/glm/detail/type_mat2x4.hpp b/extensions/common/glm/detail/type_mat2x4.hpp new file mode 100644 index 0000000000..406931072a --- /dev/null +++ b/extensions/common/glm/detail/type_mat2x4.hpp @@ -0,0 +1,202 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat2x4.hpp +/// @date 2006-08-05 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../fwd.hpp" +#include "type_vec2.hpp" +#include "type_vec4.hpp" +#include "type_mat.hpp" +#include <limits> +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tmat2x4 + { + typedef tvec4<T, P> col_type; + typedef tvec2<T, P> row_type; + typedef tmat2x4<T, P> type; + typedef tmat4x2<T, P> transpose_type; + typedef T value_type; + + private: + /// @cond DETAIL + col_type value[2]; + /// @endcond + + public: + // Constructors + GLM_FUNC_DECL tmat2x4(); + GLM_FUNC_DECL tmat2x4(tmat2x4<T, P> const & m); + template <precision Q> + GLM_FUNC_DECL tmat2x4(tmat2x4<T, Q> const & m); + + GLM_FUNC_DECL explicit tmat2x4(ctor); + GLM_FUNC_DECL explicit tmat2x4(T const & s); + GLM_FUNC_DECL tmat2x4( + T const & x0, T const & y0, T const & z0, T const & w0, + T const & x1, T const & y1, T const & z1, T const & w1); + GLM_FUNC_DECL tmat2x4( + col_type const & v0, + col_type const & v1); + + ////////////////////////////////////// + // Conversions + template < + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2> + GLM_FUNC_DECL tmat2x4( + X1 const & x1, Y1 const & y1, Z1 const & z1, W1 const & w1, + X2 const & x2, Y2 const & y2, Z2 const & z2, W2 const & w2); + + template <typename U, typename V> + GLM_FUNC_DECL tmat2x4( + tvec4<U, P> const & v1, + tvec4<V, P> const & v2); + + ////////////////////////////////////// + // Matrix conversions + +# ifdef GLM_FORCE_EXPLICIT_CTOR + template <typename U, precision Q> + GLM_FUNC_DECL explicit tmat2x4(tmat2x4<U, Q> const & m); +# else + template <typename U, precision Q> + GLM_FUNC_DECL tmat2x4(tmat2x4<U, Q> const & m); +# endif + + GLM_FUNC_DECL explicit tmat2x4(tmat2x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x4(tmat3x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x4(tmat4x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x4(tmat2x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x4(tmat3x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x4(tmat3x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x4(tmat4x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat2x4(tmat4x3<T, P> const & x); + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_t size() const; + + GLM_FUNC_DECL col_type & operator[](size_type i); + GLM_FUNC_DECL col_type const & operator[](size_type i) const; +# else + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL col_type const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tmat2x4<T, P> & operator=(tmat2x4<T, P> const & m); + + template <typename U> + GLM_FUNC_DECL tmat2x4<T, P> & operator=(tmat2x4<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat2x4<T, P> & operator+=(U s); + template <typename U> + GLM_FUNC_DECL tmat2x4<T, P> & operator+=(tmat2x4<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat2x4<T, P> & operator-=(U s); + template <typename U> + GLM_FUNC_DECL tmat2x4<T, P> & operator-=(tmat2x4<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat2x4<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tmat2x4<T, P> & operator/=(U s); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tmat2x4<T, P> & operator++ (); + GLM_FUNC_DECL tmat2x4<T, P> & operator-- (); + GLM_FUNC_DECL tmat2x4<T, P> operator++(int); + GLM_FUNC_DECL tmat2x4<T, P> operator--(int); + }; + + // Binary operators + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> operator+(tmat2x4<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> operator+(tmat2x4<T, P> const & m1, tmat2x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> operator-(tmat2x4<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> operator-(tmat2x4<T, P> const & m1, tmat2x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> operator*(tmat2x4<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> operator*(T const & s, tmat2x4<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat2x4<T, P>::col_type operator*(tmat2x4<T, P> const & m, typename tmat2x4<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat2x4<T, P>::row_type operator*(typename tmat2x4<T, P>::col_type const & v, tmat2x4<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator*(tmat2x4<T, P> const & m1, tmat4x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> operator*(tmat2x4<T, P> const & m1, tmat2x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> operator*(tmat2x4<T, P> const & m1, tmat3x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> operator/(tmat2x4<T, P> const & m, T s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> operator/(T s, tmat2x4<T, P> const & m); + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> const operator-(tmat2x4<T, P> const & m); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat2x4.inl" +#endif diff --git a/extensions/common/glm/detail/type_mat2x4.inl b/extensions/common/glm/detail/type_mat2x4.inl new file mode 100644 index 0000000000..3f95e9cf9b --- /dev/null +++ b/extensions/common/glm/detail/type_mat2x4.inl @@ -0,0 +1,515 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat2x4.inl +/// @date 2006-08-05 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + ////////////////////////////////////////////////////////////// + // Constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4() + { +# ifndef GLM_FORCE_NO_CTOR_INIT + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); +# endif + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tmat2x4<T, P> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + } + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tmat2x4<T, Q> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(T const & s) + { + value_type const Zero(0); + this->value[0] = col_type(s, Zero, Zero, Zero); + this->value[1] = col_type(Zero, s, Zero, Zero); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4 + ( + T const & x0, T const & y0, T const & z0, T const & w0, + T const & x1, T const & y1, T const & z1, T const & w1 + ) + { + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(col_type const & v0, col_type const & v1) + { + this->value[0] = v0; + this->value[1] = v1; + } + + ////////////////////////////////////// + // Conversion constructors + template <typename T, precision P> + template < + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4 + ( + X1 const & x1, Y1 const & y1, Z1 const & z1, W1 const & w1, + X2 const & x2, Y2 const & y2, Z2 const & z2, W2 const & w2 + ) + { + this->value[0] = col_type(static_cast<T>(x1), value_type(y1), value_type(z1), value_type(w1)); + this->value[1] = col_type(static_cast<T>(x2), value_type(y2), value_type(z2), value_type(w2)); + } + + template <typename T, precision P> + template <typename V1, typename V2> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tvec4<V1, P> const & v1, tvec4<V2, P> const & v2) + { + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + } + + ////////////////////////////////////// + // Matrix conversions + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tmat2x4<U, Q> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tmat2x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tmat3x3<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tmat4x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tmat2x3<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tmat3x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tmat3x4<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tmat4x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>::tmat2x4(tmat4x3<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + } + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat2x4<T, P>::size_type tmat2x4<T, P>::size() const + { + return 2; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x4<T, P>::col_type & tmat2x4<T, P>::operator[](typename tmat2x4<T, P>::size_type i) + { + assert(i < this->size()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x4<T, P>::col_type const & tmat2x4<T, P>::operator[](typename tmat2x4<T, P>::size_type i) const + { + assert(i < this->size()); + return this->value[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat2x4<T, P>::length_type tmat2x4<T, P>::length() const + { + return 2; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x4<T, P>::col_type & tmat2x4<T, P>::operator[](typename tmat2x4<T, P>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x4<T, P>::col_type const & tmat2x4<T, P>::operator[](typename tmat2x4<T, P>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////////////////////////////// + // Unary updatable operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>& tmat2x4<T, P>::operator=(tmat2x4<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x4<T, P>& tmat2x4<T, P>::operator=(tmat2x4<U, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x4<T, P>& tmat2x4<T, P>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x4<T, P>& tmat2x4<T, P>::operator+=(tmat2x4<U, P> const & m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x4<T, P>& tmat2x4<T, P>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x4<T, P>& tmat2x4<T, P>::operator-=(tmat2x4<U, P> const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x4<T, P>& tmat2x4<T, P>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat2x4<T, P> & tmat2x4<T, P>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>& tmat2x4<T, P>::operator++() + { + ++this->value[0]; + ++this->value[1]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P>& tmat2x4<T, P>::operator--() + { + --this->value[0]; + --this->value[1]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> tmat2x4<T, P>::operator++(int) + { + tmat2x4<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> tmat2x4<T, P>::operator--(int) + { + tmat2x4<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////////////////////////////// + // Binary operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> operator+(tmat2x4<T, P> const & m, T const & s) + { + return tmat2x4<T, P>( + m[0] + s, + m[1] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> operator+(tmat2x4<T, P> const & m1, tmat2x4<T, P> const & m2) + { + return tmat2x4<T, P>( + m1[0] + m2[0], + m1[1] + m2[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> operator-(tmat2x4<T, P> const & m, T const & s) + { + return tmat2x4<T, P>( + m[0] - s, + m[1] - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> operator-(tmat2x4<T, P> const & m1, tmat2x4<T, P> const & m2) + { + return tmat2x4<T, P>( + m1[0] - m2[0], + m1[1] - m2[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> operator*(tmat2x4<T, P> const & m, T const & s) + { + return tmat2x4<T, P>( + m[0] * s, + m[1] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> operator*(T const & s, tmat2x4<T, P> const & m) + { + return tmat2x4<T, P>( + m[0] * s, + m[1] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x4<T, P>::col_type operator*(tmat2x4<T, P> const & m, typename tmat2x4<T, P>::row_type const & v) + { + return typename tmat2x4<T, P>::col_type( + m[0][0] * v.x + m[1][0] * v.y, + m[0][1] * v.x + m[1][1] * v.y, + m[0][2] * v.x + m[1][2] * v.y, + m[0][3] * v.x + m[1][3] * v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat2x4<T, P>::row_type operator*(typename tmat2x4<T, P>::col_type const & v, tmat2x4<T, P> const & m) + { + return typename tmat2x4<T, P>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2] + v.w * m[0][3], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2] + v.w * m[1][3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*(tmat2x4<T, P> const & m1, tmat4x2<T, P> const & m2) + { + T SrcA00 = m1[0][0]; + T SrcA01 = m1[0][1]; + T SrcA02 = m1[0][2]; + T SrcA03 = m1[0][3]; + T SrcA10 = m1[1][0]; + T SrcA11 = m1[1][1]; + T SrcA12 = m1[1][2]; + T SrcA13 = m1[1][3]; + + T SrcB00 = m2[0][0]; + T SrcB01 = m2[0][1]; + T SrcB10 = m2[1][0]; + T SrcB11 = m2[1][1]; + T SrcB20 = m2[2][0]; + T SrcB21 = m2[2][1]; + T SrcB30 = m2[3][0]; + T SrcB31 = m2[3][1]; + + tmat4x4<T, P> Result(uninitialize); + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01; + Result[0][3] = SrcA03 * SrcB00 + SrcA13 * SrcB01; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11; + Result[1][3] = SrcA03 * SrcB10 + SrcA13 * SrcB11; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21; + Result[2][3] = SrcA03 * SrcB20 + SrcA13 * SrcB21; + Result[3][0] = SrcA00 * SrcB30 + SrcA10 * SrcB31; + Result[3][1] = SrcA01 * SrcB30 + SrcA11 * SrcB31; + Result[3][2] = SrcA02 * SrcB30 + SrcA12 * SrcB31; + Result[3][3] = SrcA03 * SrcB30 + SrcA13 * SrcB31; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> operator*(tmat2x4<T, P> const & m1, tmat2x2<T, P> const & m2) + { + return tmat2x4<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> operator*(tmat2x4<T, P> const & m1, tmat3x2<T, P> const & m2) + { + return tmat3x4<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1], + m1[0][3] * m2[2][0] + m1[1][3] * m2[2][1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> operator/(tmat2x4<T, P> const & m, T s) + { + return tmat2x4<T, P>( + m[0] / s, + m[1] / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> operator/(T s, tmat2x4<T, P> const & m) + { + return tmat2x4<T, P>( + s / m[0], + s / m[1]); + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> const operator-(tmat2x4<T, P> const & m) + { + return tmat2x4<T, P>( + -m[0], + -m[1]); + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tmat2x4<T, P> const & m1, tmat2x4<T, P> const & m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tmat2x4<T, P> const & m1, tmat2x4<T, P> const & m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]); + } +} //namespace glm diff --git a/extensions/common/glm/detail/type_mat3x2.hpp b/extensions/common/glm/detail/type_mat3x2.hpp new file mode 100644 index 0000000000..9de218f3a2 --- /dev/null +++ b/extensions/common/glm/detail/type_mat3x2.hpp @@ -0,0 +1,207 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat3x2.hpp +/// @date 2006-08-05 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../fwd.hpp" +#include "type_vec2.hpp" +#include "type_vec3.hpp" +#include "type_mat.hpp" +#include <limits> +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tmat3x2 + { + typedef tvec2<T, P> col_type; + typedef tvec3<T, P> row_type; + typedef tmat3x2<T, P> type; + typedef tmat2x3<T, P> transpose_type; + typedef T value_type; + + private: + /// @cond DETAIL + col_type value[3]; + /// @endcond + + public: + // Constructors + GLM_FUNC_DECL tmat3x2(); + GLM_FUNC_DECL tmat3x2(tmat3x2<T, P> const & m); + template <precision Q> + GLM_FUNC_DECL tmat3x2(tmat3x2<T, Q> const & m); + + GLM_FUNC_DECL explicit tmat3x2(ctor); + GLM_FUNC_DECL explicit tmat3x2(T const & s); + GLM_FUNC_DECL tmat3x2( + T const & x0, T const & y0, + T const & x1, T const & y1, + T const & x2, T const & y2); + GLM_FUNC_DECL tmat3x2( + col_type const & v0, + col_type const & v1, + col_type const & v2); + + ////////////////////////////////////// + // Conversions + + template< + typename X1, typename Y1, + typename X2, typename Y2, + typename X3, typename Y3> + GLM_FUNC_DECL tmat3x2( + X1 const & x1, Y1 const & y1, + X2 const & x2, Y2 const & y2, + X3 const & x3, Y3 const & y3); + + template <typename V1, typename V2, typename V3> + GLM_FUNC_DECL tmat3x2( + tvec2<V1, P> const & v1, + tvec2<V2, P> const & v2, + tvec2<V3, P> const & v3); + + ////////////////////////////////////// + // Matrix conversions + +# ifdef GLM_FORCE_EXPLICIT_CTOR + template <typename U, precision Q> + GLM_FUNC_DECL explicit tmat3x2(tmat3x2<U, Q> const & m); +# else + template <typename U, precision Q> + GLM_FUNC_DECL tmat3x2(tmat3x2<U, Q> const & m); +# endif + + GLM_FUNC_DECL explicit tmat3x2(tmat2x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x2(tmat3x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x2(tmat4x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x2(tmat2x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x2(tmat2x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x2(tmat3x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x2(tmat4x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x2(tmat4x3<T, P> const & x); + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_t size() const; + + GLM_FUNC_DECL col_type & operator[](size_type i); + GLM_FUNC_DECL col_type const & operator[](size_type i) const; +# else + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL col_type const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tmat3x2<T, P> & operator=(tmat3x2<T, P> const & m); + + template <typename U> + GLM_FUNC_DECL tmat3x2<T, P> & operator=(tmat3x2<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat3x2<T, P> & operator+=(U s); + template <typename U> + GLM_FUNC_DECL tmat3x2<T, P> & operator+=(tmat3x2<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat3x2<T, P> & operator-=(U s); + template <typename U> + GLM_FUNC_DECL tmat3x2<T, P> & operator-=(tmat3x2<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat3x2<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tmat3x2<T, P> & operator/=(U s); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tmat3x2<T, P> & operator++ (); + GLM_FUNC_DECL tmat3x2<T, P> & operator-- (); + GLM_FUNC_DECL tmat3x2<T, P> operator++(int); + GLM_FUNC_DECL tmat3x2<T, P> operator--(int); + }; + + // Binary operators + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> operator+(tmat3x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> operator+(tmat3x2<T, P> const & m1, tmat3x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> operator-(tmat3x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> operator-(tmat3x2<T, P> const & m1, tmat3x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> operator*(tmat3x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> operator*(T const & s, tmat3x2<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat3x2<T, P>::col_type operator*(tmat3x2<T, P> const & m, typename tmat3x2<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat3x2<T, P>::row_type operator*(typename tmat3x2<T, P>::col_type const & v, tmat3x2<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> operator*(tmat3x2<T, P> const & m1, tmat2x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> operator*(tmat3x2<T, P> const & m1, tmat3x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> operator*(tmat3x2<T, P> const & m1, tmat4x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> operator/(tmat3x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> operator/(T const & s, tmat3x2<T, P> const & m); + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> const operator-(tmat3x2<T, P> const & m); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat3x2.inl" +#endif diff --git a/extensions/common/glm/detail/type_mat3x2.inl b/extensions/common/glm/detail/type_mat3x2.inl new file mode 100644 index 0000000000..a503542aba --- /dev/null +++ b/extensions/common/glm/detail/type_mat3x2.inl @@ -0,0 +1,540 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat3x2.inl +/// @date 2006-08-05 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + ////////////////////////////////////////////////////////////// + // Constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2() + { +# ifndef GLM_FORCE_NO_CTOR_INIT + this->value[0] = col_type(1, 0); + this->value[1] = col_type(0, 1); + this->value[2] = col_type(0, 0); +# endif + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(tmat3x2<T, P> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + } + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(tmat3x2<T, Q> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(T const & s) + { + this->value[0] = col_type(s, 0); + this->value[1] = col_type(0, s); + this->value[2] = col_type(0, 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2 + ( + T const & x0, T const & y0, + T const & x1, T const & y1, + T const & x2, T const & y2 + ) + { + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + this->value[2] = col_type(x2, y2); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2 + ( + col_type const & v0, + col_type const & v1, + col_type const & v2 + ) + { + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + } + + ////////////////////////////////////// + // Conversion constructors + template <typename T, precision P> + template < + typename X1, typename Y1, + typename X2, typename Y2, + typename X3, typename Y3> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2 + ( + X1 const & x1, Y1 const & y1, + X2 const & x2, Y2 const & y2, + X3 const & x3, Y3 const & y3 + ) + { + this->value[0] = col_type(static_cast<T>(x1), value_type(y1)); + this->value[1] = col_type(static_cast<T>(x2), value_type(y2)); + this->value[2] = col_type(static_cast<T>(x3), value_type(y3)); + } + + template <typename T, precision P> + template <typename V1, typename V2, typename V3> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2 + ( + tvec2<V1, P> const & v1, + tvec2<V2, P> const & v2, + tvec2<V3, P> const & v3 + ) + { + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + } + + ////////////////////////////////////////////////////////////// + // mat3x2 matrix conversions + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(tmat3x2<U, Q> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(tmat2x2<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = col_type(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(tmat3x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(tmat4x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(tmat2x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(T(0)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(tmat2x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(T(0)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(tmat3x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(tmat4x2<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>::tmat3x2(tmat4x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + } + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat3x2<T, P>::size_type tmat3x2<T, P>::size() const + { + return 3; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x2<T, P>::col_type & tmat3x2<T, P>::operator[](typename tmat3x2<T, P>::size_type i) + { + assert(i < this->size()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x2<T, P>::col_type const & tmat3x2<T, P>::operator[](typename tmat3x2<T, P>::size_type i) const + { + assert(i < this->size()); + return this->value[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat3x2<T, P>::length_type tmat3x2<T, P>::length() const + { + return 3; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x2<T, P>::col_type & tmat3x2<T, P>::operator[](typename tmat3x2<T, P>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x2<T, P>::col_type const & tmat3x2<T, P>::operator[](typename tmat3x2<T, P>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////////////////////////////// + // Unary updatable operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>& tmat3x2<T, P>::operator=(tmat3x2<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x2<T, P>& tmat3x2<T, P>::operator=(tmat3x2<U, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x2<T, P>& tmat3x2<T, P>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x2<T, P>& tmat3x2<T, P>::operator+=(tmat3x2<U, P> const & m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x2<T, P>& tmat3x2<T, P>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x2<T, P>& tmat3x2<T, P>::operator-=(tmat3x2<U, P> const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x2<T, P>& tmat3x2<T, P>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x2<T, P> & tmat3x2<T, P>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>& tmat3x2<T, P>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P>& tmat3x2<T, P>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> tmat3x2<T, P>::operator++(int) + { + tmat3x2<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> tmat3x2<T, P>::operator--(int) + { + tmat3x2<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////////////////////////////// + // Binary operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> operator+(tmat3x2<T, P> const & m, T const & s) + { + return tmat3x2<T, P>( + m[0] + s, + m[1] + s, + m[2] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> operator+(tmat3x2<T, P> const & m1, tmat3x2<T, P> const & m2) + { + return tmat3x2<T, P>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> operator-(tmat3x2<T, P> const & m, T const & s) + { + return tmat3x2<T, P>( + m[0] - s, + m[1] - s, + m[2] - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> operator-(tmat3x2<T, P> const & m1, tmat3x2<T, P> const & m2) + { + return tmat3x2<T, P>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> operator*(tmat3x2<T, P> const & m, T const & s) + { + return tmat3x2<T, P>( + m[0] * s, + m[1] * s, + m[2] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> operator*(T const & s, tmat3x2<T, P> const & m) + { + return tmat3x2<T, P>( + m[0] * s, + m[1] * s, + m[2] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x2<T, P>::col_type operator*(tmat3x2<T, P> const & m, typename tmat3x2<T, P>::row_type const & v) + { + return typename tmat3x2<T, P>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x2<T, P>::row_type operator*(typename tmat3x2<T, P>::col_type const & v, tmat3x2<T, P> const & m) + { + return typename tmat3x2<T, P>::row_type( + v.x * m[0][0] + v.y * m[0][1], + v.x * m[1][0] + v.y * m[1][1], + v.x * m[2][0] + v.y * m[2][1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator*(tmat3x2<T, P> const & m1, tmat2x3<T, P> const & m2) + { + const T SrcA00 = m1[0][0]; + const T SrcA01 = m1[0][1]; + const T SrcA10 = m1[1][0]; + const T SrcA11 = m1[1][1]; + const T SrcA20 = m1[2][0]; + const T SrcA21 = m1[2][1]; + + const T SrcB00 = m2[0][0]; + const T SrcB01 = m2[0][1]; + const T SrcB02 = m2[0][2]; + const T SrcB10 = m2[1][0]; + const T SrcB11 = m2[1][1]; + const T SrcB12 = m2[1][2]; + + tmat2x2<T, P> Result(uninitialize); + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> operator*(tmat3x2<T, P> const & m1, tmat3x3<T, P> const & m2) + { + return tmat3x2<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> operator*(tmat3x2<T, P> const & m1, tmat4x3<T, P> const & m2) + { + return tmat4x2<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> operator/(tmat3x2<T, P> const & m, T const & s) + { + return tmat3x2<T, P>( + m[0] / s, + m[1] / s, + m[2] / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> operator/(T const & s, tmat3x2<T, P> const & m) + { + return tmat3x2<T, P>( + s / m[0], + s / m[1], + s / m[2]); + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> const operator-(tmat3x2<T, P> const & m) + { + return tmat3x2<T, P>( + -m[0], + -m[1], + -m[2]); + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tmat3x2<T, P> const & m1, tmat3x2<T, P> const & m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tmat3x2<T, P> const & m1, tmat3x2<T, P> const & m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]); + } +} //namespace glm diff --git a/extensions/common/glm/detail/type_mat3x3.hpp b/extensions/common/glm/detail/type_mat3x3.hpp new file mode 100644 index 0000000000..ce937e56b3 --- /dev/null +++ b/extensions/common/glm/detail/type_mat3x3.hpp @@ -0,0 +1,230 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat3x3.hpp +/// @date 2005-01-27 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../fwd.hpp" +#include "type_vec3.hpp" +#include "type_mat.hpp" +#include <limits> +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tmat3x3 + { + typedef tvec3<T, P> col_type; + typedef tvec3<T, P> row_type; + typedef tmat3x3<T, P> type; + typedef tmat3x3<T, P> transpose_type; + typedef T value_type; + + template <typename U, precision Q> + friend tvec3<U, Q> operator/(tmat3x3<U, Q> const & m, tvec3<U, Q> const & v); + template <typename U, precision Q> + friend tvec3<U, Q> operator/(tvec3<U, Q> const & v, tmat3x3<U, Q> const & m); + + private: + /// @cond DETAIL + col_type value[3]; + /// @endcond + + public: + // Constructors + GLM_FUNC_DECL tmat3x3(); + GLM_FUNC_DECL tmat3x3(tmat3x3<T, P> const & m); + template <precision Q> + GLM_FUNC_DECL tmat3x3(tmat3x3<T, Q> const & m); + + GLM_FUNC_DECL explicit tmat3x3(ctor); + GLM_FUNC_DECL explicit tmat3x3(T const & s); + GLM_FUNC_DECL tmat3x3( + T const & x0, T const & y0, T const & z0, + T const & x1, T const & y1, T const & z1, + T const & x2, T const & y2, T const & z2); + GLM_FUNC_DECL tmat3x3( + col_type const & v0, + col_type const & v1, + col_type const & v2); + + ////////////////////////////////////// + // Conversions + + template< + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3> + GLM_FUNC_DECL tmat3x3( + X1 const & x1, Y1 const & y1, Z1 const & z1, + X2 const & x2, Y2 const & y2, Z2 const & z2, + X3 const & x3, Y3 const & y3, Z3 const & z3); + + template <typename V1, typename V2, typename V3> + GLM_FUNC_DECL tmat3x3( + tvec3<V1, P> const & v1, + tvec3<V2, P> const & v2, + tvec3<V3, P> const & v3); + + ////////////////////////////////////// + // Matrix conversions + +# ifdef GLM_FORCE_EXPLICIT_CTOR + template <typename U, precision Q> + GLM_FUNC_DECL explicit tmat3x3(tmat3x3<U, Q> const & m); +# else + template <typename U, precision Q> + GLM_FUNC_DECL tmat3x3(tmat3x3<U, Q> const & m); +# endif + + GLM_FUNC_DECL explicit tmat3x3(tmat2x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x3(tmat4x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x3(tmat2x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x3(tmat3x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x3(tmat2x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x3(tmat4x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x3(tmat3x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x3(tmat4x3<T, P> const & x); + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_t size() const; + + GLM_FUNC_DECL col_type & operator[](size_type i); + GLM_FUNC_DECL col_type const & operator[](size_type i) const; +# else + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL col_type const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tmat3x3<T, P> & operator=(tmat3x3<T, P> const & m); + + template <typename U> + GLM_FUNC_DECL tmat3x3<T, P> & operator=(tmat3x3<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat3x3<T, P> & operator+=(U s); + template <typename U> + GLM_FUNC_DECL tmat3x3<T, P> & operator+=(tmat3x3<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat3x3<T, P> & operator-=(U s); + template <typename U> + GLM_FUNC_DECL tmat3x3<T, P> & operator-=(tmat3x3<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat3x3<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tmat3x3<T, P> & operator*=(tmat3x3<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat3x3<T, P> & operator/=(U s); + template <typename U> + GLM_FUNC_DECL tmat3x3<T, P> & operator/=(tmat3x3<U, P> const & m); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tmat3x3<T, P> & operator++(); + GLM_FUNC_DECL tmat3x3<T, P> & operator--(); + GLM_FUNC_DECL tmat3x3<T, P> operator++(int); + GLM_FUNC_DECL tmat3x3<T, P> operator--(int); + }; + + // Binary operators + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator+(tmat3x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator+(T const & s, tmat3x3<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator+(tmat3x3<T, P> const & m1, tmat3x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator-(tmat3x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator-(T const & s, tmat3x3<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator-(tmat3x3<T, P> const & m1, tmat3x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator*(tmat3x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator*(T const & s, tmat3x3<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat3x3<T, P>::col_type operator*(tmat3x3<T, P> const & m, typename tmat3x3<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat3x3<T, P>::row_type operator*(typename tmat3x3<T, P>::col_type const & v, tmat3x3<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator*(tmat3x3<T, P> const & m1, tmat3x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator*(tmat3x3<T, P> const & m1, tmat2x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> operator*(tmat3x3<T, P> const & m1, tmat4x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator/(tmat3x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator/(T const & s, tmat3x3<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat3x3<T, P>::col_type operator/(tmat3x3<T, P> const & m, typename tmat3x3<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat3x3<T, P>::row_type operator/(typename tmat3x3<T, P>::col_type const & v, tmat3x3<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator/(tmat3x3<T, P> const & m1, tmat3x3<T, P> const & m2); + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> const operator-(tmat3x3<T, P> const & m); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat3x3.inl" +#endif diff --git a/extensions/common/glm/detail/type_mat3x3.inl b/extensions/common/glm/detail/type_mat3x3.inl new file mode 100644 index 0000000000..5e432523a9 --- /dev/null +++ b/extensions/common/glm/detail/type_mat3x3.inl @@ -0,0 +1,631 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat3x3.inl +/// @date 2005-01-27 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> compute_inverse(tmat3x3<T, P> const & m) + { + T OneOverDeterminant = static_cast<T>(1) / ( + + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2]) + - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2]) + + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2])); + + tmat3x3<T, P> Inverse(uninitialize); + Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDeterminant; + Inverse[1][0] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDeterminant; + Inverse[2][0] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDeterminant; + Inverse[0][1] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDeterminant; + Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDeterminant; + Inverse[2][1] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDeterminant; + Inverse[0][2] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDeterminant; + Inverse[1][2] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDeterminant; + Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDeterminant; + + return Inverse; + } +}//namespace detail + + ////////////////////////////////////////////////////////////// + // Constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3() + { +# ifndef GLM_FORCE_NO_CTOR_INIT + this->value[0] = col_type(1, 0, 0); + this->value[1] = col_type(0, 1, 0); + this->value[2] = col_type(0, 0, 1); +# endif + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(tmat3x3<T, P> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + } + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(tmat3x3<T, Q> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(T const & s) + { + this->value[0] = col_type(s, 0, 0); + this->value[1] = col_type(0, s, 0); + this->value[2] = col_type(0, 0, s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3 + ( + T const & x0, T const & y0, T const & z0, + T const & x1, T const & y1, T const & z1, + T const & x2, T const & y2, T const & z2 + ) + { + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); + this->value[2] = col_type(x2, y2, z2); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3 + ( + col_type const & v0, + col_type const & v1, + col_type const & v2 + ) + { + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + } + + ////////////////////////////////////// + // Conversion constructors + template <typename T, precision P> + template < + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3 + ( + X1 const & x1, Y1 const & y1, Z1 const & z1, + X2 const & x2, Y2 const & y2, Z2 const & z2, + X3 const & x3, Y3 const & y3, Z3 const & z3 + ) + { + this->value[0] = col_type(static_cast<T>(x1), value_type(y1), value_type(z1)); + this->value[1] = col_type(static_cast<T>(x2), value_type(y2), value_type(z2)); + this->value[2] = col_type(static_cast<T>(x3), value_type(y3), value_type(z3)); + } + + template <typename T, precision P> + template <typename V1, typename V2, typename V3> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3 + ( + tvec3<V1, P> const & v1, + tvec3<V2, P> const & v2, + tvec3<V3, P> const & v3 + ) + { + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + } + + ////////////////////////////////////////////////////////////// + // Conversions + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(tmat3x3<U, Q> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(tmat2x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(0, 0, 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(tmat4x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(tmat2x3<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = col_type(0, 0, 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(tmat3x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(tmat2x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(tmat4x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(tmat3x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P>::tmat3x3(tmat4x3<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + } + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat3x3<T, P>::size_type tmat3x3<T, P>::size() const + { + return 3; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x3<T, P>::col_type & tmat3x3<T, P>::operator[](typename tmat3x3<T, P>::size_type i) + { + assert(i < this->size()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x3<T, P>::col_type const & tmat3x3<T, P>::operator[](typename tmat3x3<T, P>::size_type i) const + { + assert(i < this->size()); + return this->value[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat3x3<T, P>::length_type tmat3x3<T, P>::length() const + { + return 3; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x3<T, P>::col_type & tmat3x3<T, P>::operator[](typename tmat3x3<T, P>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x3<T, P>::col_type const & tmat3x3<T, P>::operator[](typename tmat3x3<T, P>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////////////////////////////// + // Operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator=(tmat3x3<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator=(tmat3x3<U, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator+=(tmat3x3<U, P> const & m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator-=(tmat3x3<U, P> const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator*=(tmat3x3<U, P> const & m) + { + return (*this = *this * m); + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator/=(tmat3x3<U, P> const & m) + { + return (*this = *this * detail::compute_inverse<T, P>(m)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> & tmat3x3<T, P>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> tmat3x3<T, P>::operator++(int) + { + tmat3x3<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> tmat3x3<T, P>::operator--(int) + { + tmat3x3<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////////////////////////////// + // Binary operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator+(tmat3x3<T, P> const & m, T const & s) + { + return tmat3x3<T, P>( + m[0] + s, + m[1] + s, + m[2] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator+(T const & s, tmat3x3<T, P> const & m) + { + return tmat3x3<T, P>( + m[0] + s, + m[1] + s, + m[2] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator+(tmat3x3<T, P> const & m1, tmat3x3<T, P> const & m2) + { + return tmat3x3<T, P>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator-(tmat3x3<T, P> const & m, T const & s) + { + return tmat3x3<T, P>( + m[0] - s, + m[1] - s, + m[2] - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator-(T const & s, tmat3x3<T, P> const & m) + { + return tmat3x3<T, P>( + s - m[0], + s - m[1], + s - m[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator-(tmat3x3<T, P> const & m1, tmat3x3<T, P> const & m2) + { + return tmat3x3<T, P>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator*(tmat3x3<T, P> const & m, T const & s) + { + return tmat3x3<T, P>( + m[0] * s, + m[1] * s, + m[2] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator*(T const & s, tmat3x3<T, P> const & m) + { + return tmat3x3<T, P>( + m[0] * s, + m[1] * s, + m[2] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x3<T, P>::col_type operator*(tmat3x3<T, P> const & m, typename tmat3x3<T, P>::row_type const & v) + { + return typename tmat3x3<T, P>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z, + m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x3<T, P>::row_type operator*(typename tmat3x3<T, P>::col_type const & v, tmat3x3<T, P> const & m) + { + return typename tmat3x3<T, P>::row_type( + m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z, + m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z, + m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator*(tmat3x3<T, P> const & m1, tmat3x3<T, P> const & m2) + { + T const SrcA00 = m1[0][0]; + T const SrcA01 = m1[0][1]; + T const SrcA02 = m1[0][2]; + T const SrcA10 = m1[1][0]; + T const SrcA11 = m1[1][1]; + T const SrcA12 = m1[1][2]; + T const SrcA20 = m1[2][0]; + T const SrcA21 = m1[2][1]; + T const SrcA22 = m1[2][2]; + + T const SrcB00 = m2[0][0]; + T const SrcB01 = m2[0][1]; + T const SrcB02 = m2[0][2]; + T const SrcB10 = m2[1][0]; + T const SrcB11 = m2[1][1]; + T const SrcB12 = m2[1][2]; + T const SrcB20 = m2[2][0]; + T const SrcB21 = m2[2][1]; + T const SrcB22 = m2[2][2]; + + tmat3x3<T, P> Result(uninitialize); + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01 + SrcA22 * SrcB02; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11 + SrcA22 * SrcB12; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21 + SrcA20 * SrcB22; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21 + SrcA21 * SrcB22; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21 + SrcA22 * SrcB22; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> operator*(tmat3x3<T, P> const & m1, tmat2x3<T, P> const & m2) + { + return tmat2x3<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> operator*(tmat3x3<T, P> const & m1, tmat4x3<T, P> const & m2) + { + return tmat4x3<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2], + m1[0][2] * m2[3][0] + m1[1][2] * m2[3][1] + m1[2][2] * m2[3][2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator/(tmat3x3<T, P> const & m, T const & s) + { + return tmat3x3<T, P>( + m[0] / s, + m[1] / s, + m[2] / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator/(T const & s, tmat3x3<T, P> const & m) + { + return tmat3x3<T, P>( + s / m[0], + s / m[1], + s / m[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x3<T, P>::col_type operator/(tmat3x3<T, P> const & m, typename tmat3x3<T, P>::row_type const & v) + { + return detail::compute_inverse<T, P>(m) * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x3<T, P>::row_type operator/(typename tmat3x3<T, P>::col_type const & v, tmat3x3<T, P> const & m) + { + return v * detail::compute_inverse<T, P>(m); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator/(tmat3x3<T, P> const & m1, tmat3x3<T, P> const & m2) + { + tmat3x3<T, P> m1_copy(m1); + return m1_copy /= m2; + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> const operator-(tmat3x3<T, P> const & m) + { + return tmat3x3<T, P>( + -m[0], + -m[1], + -m[2]); + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tmat3x3<T, P> const & m1, tmat3x3<T, P> const & m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tmat3x3<T, P> const & m1, tmat3x3<T, P> const & m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]); + } +} //namespace glm diff --git a/extensions/common/glm/detail/type_mat3x4.hpp b/extensions/common/glm/detail/type_mat3x4.hpp new file mode 100644 index 0000000000..e826101eee --- /dev/null +++ b/extensions/common/glm/detail/type_mat3x4.hpp @@ -0,0 +1,206 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat3x4.hpp +/// @date 2006-08-05 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../fwd.hpp" +#include "type_vec3.hpp" +#include "type_vec4.hpp" +#include "type_mat.hpp" +#include <limits> +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tmat3x4 + { + typedef tvec4<T, P> col_type; + typedef tvec3<T, P> row_type; + typedef tmat3x4<T, P> type; + typedef tmat4x3<T, P> transpose_type; + typedef T value_type; + + private: + /// @cond DETAIL + col_type value[3]; + /// @endcond + + public: + // Constructors + GLM_FUNC_DECL tmat3x4(); + GLM_FUNC_DECL tmat3x4(tmat3x4<T, P> const & m); + template <precision Q> + GLM_FUNC_DECL tmat3x4(tmat3x4<T, Q> const & m); + + GLM_FUNC_DECL explicit tmat3x4(ctor); + GLM_FUNC_DECL explicit tmat3x4(T const & s); + GLM_FUNC_DECL tmat3x4( + T const & x0, T const & y0, T const & z0, T const & w0, + T const & x1, T const & y1, T const & z1, T const & w1, + T const & x2, T const & y2, T const & z2, T const & w2); + GLM_FUNC_DECL tmat3x4( + col_type const & v0, + col_type const & v1, + col_type const & v2); + + ////////////////////////////////////// + // Conversions + template< + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2, + typename X3, typename Y3, typename Z3, typename W3> + GLM_FUNC_DECL tmat3x4( + X1 const & x1, Y1 const & y1, Z1 const & z1, W1 const & w1, + X2 const & x2, Y2 const & y2, Z2 const & z2, W2 const & w2, + X3 const & x3, Y3 const & y3, Z3 const & z3, W3 const & w3); + + template <typename V1, typename V2, typename V3> + GLM_FUNC_DECL tmat3x4( + tvec4<V1, P> const & v1, + tvec4<V2, P> const & v2, + tvec4<V3, P> const & v3); + + ////////////////////////////////////// + // Matrix conversion + +# ifdef GLM_FORCE_EXPLICIT_CTOR + template <typename U, precision Q> + GLM_FUNC_DECL explicit tmat3x4(tmat3x4<U, Q> const & m); +# else + template <typename U, precision Q> + GLM_FUNC_DECL tmat3x4(tmat3x4<U, Q> const & m); +# endif + + GLM_FUNC_DECL explicit tmat3x4(tmat2x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x4(tmat3x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x4(tmat4x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x4(tmat2x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x4(tmat3x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x4(tmat2x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x4(tmat4x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat3x4(tmat4x3<T, P> const & x); + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_t size() const; + + GLM_FUNC_DECL col_type & operator[](size_type i); + GLM_FUNC_DECL col_type const & operator[](size_type i) const; +# else + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL col_type const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tmat3x4<T, P> & operator=(tmat3x4<T, P> const & m); + + template <typename U> + GLM_FUNC_DECL tmat3x4<T, P> & operator=(tmat3x4<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat3x4<T, P> & operator+=(U s); + template <typename U> + GLM_FUNC_DECL tmat3x4<T, P> & operator+=(tmat3x4<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat3x4<T, P> & operator-=(U s); + template <typename U> + GLM_FUNC_DECL tmat3x4<T, P> & operator-=(tmat3x4<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat3x4<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tmat3x4<T, P> & operator/=(U s); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tmat3x4<T, P> & operator++(); + GLM_FUNC_DECL tmat3x4<T, P> & operator--(); + GLM_FUNC_DECL tmat3x4<T, P> operator++(int); + GLM_FUNC_DECL tmat3x4<T, P> operator--(int); + }; + + // Binary operators + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> operator+(tmat3x4<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> operator+(tmat3x4<T, P> const & m1, tmat3x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> operator-(tmat3x4<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> operator-(tmat3x4<T, P> const & m1, tmat3x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> operator*(tmat3x4<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> operator*(T const & s, tmat3x4<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat3x4<T, P>::col_type operator*(tmat3x4<T, P> const & m, typename tmat3x4<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat3x4<T, P>::row_type operator*(typename tmat3x4<T, P>::col_type const & v, tmat3x4<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator*(tmat3x4<T, P> const & m1, tmat4x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> operator*(tmat3x4<T, P> const & m1, tmat2x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> operator*(tmat3x4<T, P> const & m1, tmat3x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> operator/(tmat3x4<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> operator/(T const & s, tmat3x4<T, P> const & m); + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> const operator-(tmat3x4<T, P> const & m); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat3x4.inl" +#endif diff --git a/extensions/common/glm/detail/type_mat3x4.inl b/extensions/common/glm/detail/type_mat3x4.inl new file mode 100644 index 0000000000..761bc0233a --- /dev/null +++ b/extensions/common/glm/detail/type_mat3x4.inl @@ -0,0 +1,579 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat3x4.inl +/// @date 2006-08-05 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + ////////////////////////////////////////////////////////////// + // Constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4() + { +# ifndef GLM_FORCE_NO_CTOR_INIT + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(0, 0, 1, 0); +# endif + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(tmat3x4<T, P> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + } + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(tmat3x4<T, Q> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(T const & s) + { + value_type const Zero(0); + this->value[0] = col_type(s, Zero, Zero, Zero); + this->value[1] = col_type(Zero, s, Zero, Zero); + this->value[2] = col_type(Zero, Zero, s, Zero); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4 + ( + T const & x0, T const & y0, T const & z0, T const & w0, + T const & x1, T const & y1, T const & z1, T const & w1, + T const & x2, T const & y2, T const & z2, T const & w2 + ) + { + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); + this->value[2] = col_type(x2, y2, z2, w2); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4 + ( + col_type const & v0, + col_type const & v1, + col_type const & v2 + ) + { + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + } + + ////////////////////////////////////// + // Conversion constructors + template <typename T, precision P> + template < + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2, + typename X3, typename Y3, typename Z3, typename W3> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4 + ( + X1 const & x1, Y1 const & y1, Z1 const & z1, W1 const & w1, + X2 const & x2, Y2 const & y2, Z2 const & z2, W2 const & w2, + X3 const & x3, Y3 const & y3, Z3 const & z3, W3 const & w3 + ) + { + this->value[0] = col_type(static_cast<T>(x1), value_type(y1), value_type(z1), value_type(w1)); + this->value[1] = col_type(static_cast<T>(x2), value_type(y2), value_type(z2), value_type(w2)); + this->value[2] = col_type(static_cast<T>(x3), value_type(y3), value_type(z3), value_type(w3)); + } + + template <typename T, precision P> + template <typename V1, typename V2, typename V3> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4 + ( + tvec4<V1, P> const & v1, + tvec4<V2, P> const & v2, + tvec4<V3, P> const & v3 + ) + { + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + } + + // Conversion + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(tmat3x4<U, Q> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(tmat2x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(tmat3x3<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(tmat4x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(tmat2x3<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(0, 0, 1, 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(tmat3x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(m[2], 0, 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(tmat2x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1, 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(tmat4x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(m[2], 1, 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>::tmat3x4(tmat4x3<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); + } + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat3x4<T, P>::size_type tmat3x4<T, P>::size() const + { + return 3; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x4<T, P>::col_type & tmat3x4<T, P>::operator[](typename tmat3x4<T, P>::size_type i) + { + assert(i < this->size()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x4<T, P>::col_type const & tmat3x4<T, P>::operator[](typename tmat3x4<T, P>::size_type i) const + { + assert(i < this->size()); + return this->value[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat3x4<T, P>::length_type tmat3x4<T, P>::length() const + { + return 3; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x4<T, P>::col_type & tmat3x4<T, P>::operator[](typename tmat3x4<T, P>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x4<T, P>::col_type const & tmat3x4<T, P>::operator[](typename tmat3x4<T, P>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////////////////////////////// + // Unary updatable operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>& tmat3x4<T, P>::operator=(tmat3x4<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x4<T, P>& tmat3x4<T, P>::operator=(tmat3x4<U, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x4<T, P>& tmat3x4<T, P>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x4<T, P>& tmat3x4<T, P>::operator+=(tmat3x4<U, P> const & m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x4<T, P>& tmat3x4<T, P>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x4<T, P>& tmat3x4<T, P>::operator-=(tmat3x4<U, P> const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x4<T, P>& tmat3x4<T, P>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat3x4<T, P> & tmat3x4<T, P>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>& tmat3x4<T, P>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P>& tmat3x4<T, P>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> tmat3x4<T, P>::operator++(int) + { + tmat3x4<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> tmat3x4<T, P>::operator--(int) + { + tmat3x4<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////////////////////////////// + // Binary operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> operator+(tmat3x4<T, P> const & m, T const & s) + { + return tmat3x4<T, P>( + m[0] + s, + m[1] + s, + m[2] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> operator+(tmat3x4<T, P> const & m1, tmat3x4<T, P> const & m2) + { + return tmat3x4<T, P>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> operator-(tmat3x4<T, P> const & m, T const & s) + { + return tmat3x4<T, P>( + m[0] - s, + m[1] - s, + m[2] - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> operator-(tmat3x4<T, P> const & m1, tmat3x4<T, P> const & m2) + { + return tmat3x4<T, P>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> operator*(tmat3x4<T, P> const & m, T const & s) + { + return tmat3x4<T, P>( + m[0] * s, + m[1] * s, + m[2] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> operator*(T const & s, tmat3x4<T, P> const & m) + { + return tmat3x4<T, P>( + m[0] * s, + m[1] * s, + m[2] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x4<T, P>::col_type operator* + ( + tmat3x4<T, P> const & m, + typename tmat3x4<T, P>::row_type const & v + ) + { + return typename tmat3x4<T, P>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z, + m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z, + m[0][3] * v.x + m[1][3] * v.y + m[2][3] * v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat3x4<T, P>::row_type operator* + ( + typename tmat3x4<T, P>::col_type const & v, + tmat3x4<T, P> const & m + ) + { + return typename tmat3x4<T, P>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2] + v.w * m[0][3], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2] + v.w * m[1][3], + v.x * m[2][0] + v.y * m[2][1] + v.z * m[2][2] + v.w * m[2][3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*(tmat3x4<T, P> const & m1, tmat4x3<T, P> const & m2) + { + const T SrcA00 = m1[0][0]; + const T SrcA01 = m1[0][1]; + const T SrcA02 = m1[0][2]; + const T SrcA03 = m1[0][3]; + const T SrcA10 = m1[1][0]; + const T SrcA11 = m1[1][1]; + const T SrcA12 = m1[1][2]; + const T SrcA13 = m1[1][3]; + const T SrcA20 = m1[2][0]; + const T SrcA21 = m1[2][1]; + const T SrcA22 = m1[2][2]; + const T SrcA23 = m1[2][3]; + + const T SrcB00 = m2[0][0]; + const T SrcB01 = m2[0][1]; + const T SrcB02 = m2[0][2]; + const T SrcB10 = m2[1][0]; + const T SrcB11 = m2[1][1]; + const T SrcB12 = m2[1][2]; + const T SrcB20 = m2[2][0]; + const T SrcB21 = m2[2][1]; + const T SrcB22 = m2[2][2]; + const T SrcB30 = m2[3][0]; + const T SrcB31 = m2[3][1]; + const T SrcB32 = m2[3][2]; + + tmat4x4<T, P> Result(uninitialize); + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01 + SrcA22 * SrcB02; + Result[0][3] = SrcA03 * SrcB00 + SrcA13 * SrcB01 + SrcA23 * SrcB02; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11 + SrcA22 * SrcB12; + Result[1][3] = SrcA03 * SrcB10 + SrcA13 * SrcB11 + SrcA23 * SrcB12; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21 + SrcA20 * SrcB22; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21 + SrcA21 * SrcB22; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21 + SrcA22 * SrcB22; + Result[2][3] = SrcA03 * SrcB20 + SrcA13 * SrcB21 + SrcA23 * SrcB22; + Result[3][0] = SrcA00 * SrcB30 + SrcA10 * SrcB31 + SrcA20 * SrcB32; + Result[3][1] = SrcA01 * SrcB30 + SrcA11 * SrcB31 + SrcA21 * SrcB32; + Result[3][2] = SrcA02 * SrcB30 + SrcA12 * SrcB31 + SrcA22 * SrcB32; + Result[3][3] = SrcA03 * SrcB30 + SrcA13 * SrcB31 + SrcA23 * SrcB32; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> operator*(tmat3x4<T, P> const & m1, tmat2x3<T, P> const & m2) + { + return tmat2x4<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> operator*(tmat3x4<T, P> const & m1, tmat3x3<T, P> const & m2) + { + return tmat3x4<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2], + m1[0][3] * m2[2][0] + m1[1][3] * m2[2][1] + m1[2][3] * m2[2][2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> operator/(tmat3x4<T, P> const & m, T const & s) + { + return tmat3x4<T, P>( + m[0] / s, + m[1] / s, + m[2] / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> operator/(T const & s, tmat3x4<T, P> const & m) + { + return tmat3x4<T, P>( + s / m[0], + s / m[1], + s / m[2]); + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> const operator-(tmat3x4<T, P> const & m) + { + return tmat3x4<T, P>( + -m[0], + -m[1], + -m[2]); + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tmat3x4<T, P> const & m1, tmat3x4<T, P> const & m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tmat3x4<T, P> const & m1, tmat3x4<T, P> const & m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]); + } +} //namespace glm diff --git a/extensions/common/glm/detail/type_mat4x2.hpp b/extensions/common/glm/detail/type_mat4x2.hpp new file mode 100644 index 0000000000..77206bb7ea --- /dev/null +++ b/extensions/common/glm/detail/type_mat4x2.hpp @@ -0,0 +1,212 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat4x2.hpp +/// @date 2006-10-01 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../fwd.hpp" +#include "type_vec2.hpp" +#include "type_vec4.hpp" +#include "type_mat.hpp" +#include <limits> +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tmat4x2 + { + typedef tvec2<T, P> col_type; + typedef tvec4<T, P> row_type; + typedef tmat4x2<T, P> type; + typedef tmat2x4<T, P> transpose_type; + typedef T value_type; + + private: + /// @cond DETAIL + col_type value[4]; + /// @endcond + + public: + // Constructors + GLM_FUNC_DECL tmat4x2(); + GLM_FUNC_DECL tmat4x2(tmat4x2<T, P> const & m); + template <precision Q> + GLM_FUNC_DECL tmat4x2(tmat4x2<T, Q> const & m); + + GLM_FUNC_DECL explicit tmat4x2(ctor); + GLM_FUNC_DECL explicit tmat4x2(T const & x); + GLM_FUNC_DECL tmat4x2( + T const & x0, T const & y0, + T const & x1, T const & y1, + T const & x2, T const & y2, + T const & x3, T const & y3); + GLM_FUNC_DECL tmat4x2( + col_type const & v0, + col_type const & v1, + col_type const & v2, + col_type const & v3); + + ////////////////////////////////////// + // Conversions + + template < + typename X1, typename Y1, + typename X2, typename Y2, + typename X3, typename Y3, + typename X4, typename Y4> + GLM_FUNC_DECL tmat4x2( + X1 const & x1, Y1 const & y1, + X2 const & x2, Y2 const & y2, + X3 const & x3, Y3 const & y3, + X4 const & x4, Y4 const & y4); + + template <typename V1, typename V2, typename V3, typename V4> + GLM_FUNC_DECL tmat4x2( + tvec2<V1, P> const & v1, + tvec2<V2, P> const & v2, + tvec2<V3, P> const & v3, + tvec2<V4, P> const & v4); + + ////////////////////////////////////// + // Matrix conversions + +# ifdef GLM_FORCE_EXPLICIT_CTOR + template <typename U, precision Q> + GLM_FUNC_DECL explicit tmat4x2(tmat4x2<U, Q> const & m); +# else + template <typename U, precision Q> + GLM_FUNC_DECL tmat4x2(tmat4x2<U, Q> const & m); +# endif + + GLM_FUNC_DECL explicit tmat4x2(tmat2x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x2(tmat3x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x2(tmat4x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x2(tmat2x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x2(tmat3x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x2(tmat2x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x2(tmat4x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x2(tmat3x4<T, P> const & x); + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_t size() const; + + GLM_FUNC_DECL col_type & operator[](size_type i); + GLM_FUNC_DECL col_type const & operator[](size_type i) const; +# else + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL col_type const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tmat4x2<T, P> & operator=(tmat4x2<T, P> const & m); + + template <typename U> + GLM_FUNC_DECL tmat4x2<T, P> & operator=(tmat4x2<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat4x2<T, P> & operator+=(U s); + template <typename U> + GLM_FUNC_DECL tmat4x2<T, P> & operator+=(tmat4x2<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat4x2<T, P> & operator-=(U s); + template <typename U> + GLM_FUNC_DECL tmat4x2<T, P> & operator-=(tmat4x2<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat4x2<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tmat4x2<T, P> & operator/=(U s); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tmat4x2<T, P> & operator++ (); + GLM_FUNC_DECL tmat4x2<T, P> & operator-- (); + GLM_FUNC_DECL tmat4x2<T, P> operator++(int); + GLM_FUNC_DECL tmat4x2<T, P> operator--(int); + }; + + // Binary operators + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> operator+(tmat4x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> operator+(tmat4x2<T, P> const & m1, tmat4x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> operator-(tmat4x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> operator-(tmat4x2<T, P> const & m1, tmat4x2<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> operator*(tmat4x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> operator*(T const & s, tmat4x2<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat4x2<T, P>::col_type operator*(tmat4x2<T, P> const & m, typename tmat4x2<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat4x2<T, P>::row_type operator*(typename tmat4x2<T, P>::col_type const & v, tmat4x2<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> operator*(tmat4x2<T, P> const & m1, tmat3x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> operator*(tmat4x2<T, P> const & m1, tmat4x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator*(tmat4x3<T, P> const & m1, tmat2x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> operator/(tmat4x2<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> operator/(T const & s, tmat4x2<T, P> const & m); + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> const operator-(tmat4x2<T, P> const & m); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat4x2.inl" +#endif diff --git a/extensions/common/glm/detail/type_mat4x2.inl b/extensions/common/glm/detail/type_mat4x2.inl new file mode 100644 index 0000000000..5b14015b93 --- /dev/null +++ b/extensions/common/glm/detail/type_mat4x2.inl @@ -0,0 +1,587 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat4x2.inl +/// @date 2006-10-01 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + ////////////////////////////////////////////////////////////// + // Constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2() + { +# ifndef GLM_FORCE_NO_CTOR_INIT + this->value[0] = col_type(1, 0); + this->value[1] = col_type(0, 1); + this->value[2] = col_type(0, 0); + this->value[3] = col_type(0, 0); +# endif + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(tmat4x2<T, P> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + this->value[3] = m.value[3]; + } + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(tmat4x2<T, Q> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + this->value[3] = m.value[3]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(T const & s) + { + value_type const Zero(0); + this->value[0] = col_type(s, Zero); + this->value[1] = col_type(Zero, s); + this->value[2] = col_type(Zero, Zero); + this->value[3] = col_type(Zero, Zero); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2 + ( + T const & x0, T const & y0, + T const & x1, T const & y1, + T const & x2, T const & y2, + T const & x3, T const & y3 + ) + { + this->value[0] = col_type(x0, y0); + this->value[1] = col_type(x1, y1); + this->value[2] = col_type(x2, y2); + this->value[3] = col_type(x3, y3); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2 + ( + col_type const & v0, + col_type const & v1, + col_type const & v2, + col_type const & v3 + ) + { + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + this->value[3] = v3; + } + + ////////////////////////////////////// + // Conversion constructors + + template <typename T, precision P> + template < + typename X1, typename Y1, + typename X2, typename Y2, + typename X3, typename Y3, + typename X4, typename Y4> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2 + ( + X1 const & x1, Y1 const & y1, + X2 const & x2, Y2 const & y2, + X3 const & x3, Y3 const & y3, + X4 const & x4, Y4 const & y4 + ) + { + this->value[0] = col_type(static_cast<T>(x1), value_type(y1)); + this->value[1] = col_type(static_cast<T>(x2), value_type(y2)); + this->value[2] = col_type(static_cast<T>(x3), value_type(y3)); + this->value[3] = col_type(static_cast<T>(x4), value_type(y4)); + } + + template <typename T, precision P> + template <typename V1, typename V2, typename V3, typename V4> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2 + ( + tvec2<V1, P> const & v1, + tvec2<V2, P> const & v2, + tvec2<V3, P> const & v3, + tvec2<V4, P> const & v4 + ) + { + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + this->value[3] = col_type(v4); + } + + ////////////////////////////////////// + // Conversion + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(tmat4x2<U, Q> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(tmat2x2<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); + this->value[3] = col_type(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(tmat3x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(tmat4x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(tmat2x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); + this->value[3] = col_type(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(tmat3x2<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(tmat2x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0); + this->value[3] = col_type(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(tmat4x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>::tmat4x2(tmat3x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); + } + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat4x2<T, P>::size_type tmat4x2<T, P>::size() const + { + return 4; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x2<T, P>::col_type & tmat4x2<T, P>::operator[](typename tmat4x2<T, P>::size_type i) + { + assert(i < this->size()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x2<T, P>::col_type const & tmat4x2<T, P>::operator[](typename tmat4x2<T, P>::size_type i) const + { + assert(i < this->size()); + return this->value[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat4x2<T, P>::length_type tmat4x2<T, P>::length() const + { + return 4; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x2<T, P>::col_type & tmat4x2<T, P>::operator[](typename tmat4x2<T, P>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x2<T, P>::col_type const & tmat4x2<T, P>::operator[](typename tmat4x2<T, P>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////////////////////////////// + // Unary updatable operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P>& tmat4x2<T, P>::operator=(tmat4x2<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x2<T, P>& tmat4x2<T, P>::operator=(tmat4x2<U, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x2<T, P> & tmat4x2<T, P>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + this->value[3] += s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x2<T, P> & tmat4x2<T, P>::operator+=(tmat4x2<U, P> const & m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + this->value[3] += m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x2<T, P> & tmat4x2<T, P>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + this->value[3] -= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x2<T, P> & tmat4x2<T, P>::operator-=(tmat4x2<U, P> const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + this->value[3] -= m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x2<T, P> & tmat4x2<T, P>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + this->value[3] *= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x2<T, P> & tmat4x2<T, P>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + this->value[3] /= s; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> & tmat4x2<T, P>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + ++this->value[3]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> & tmat4x2<T, P>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + --this->value[3]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> tmat4x2<T, P>::operator++(int) + { + tmat4x2<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> tmat4x2<T, P>::operator--(int) + { + tmat4x2<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////////////////////////////// + // Binary operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> operator+(tmat4x2<T, P> const & m, T const & s) + { + return tmat4x2<T, P>( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> operator+(tmat4x2<T, P> const & m1, tmat4x2<T, P> const & m2) + { + return tmat4x2<T, P>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2], + m1[3] + m2[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> operator-(tmat4x2<T, P> const & m, T const & s) + { + return tmat4x2<T, P>( + m[0] - s, + m[1] - s, + m[2] - s, + m[3] - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> operator-(tmat4x2<T, P> const & m1, tmat4x2<T, P> const & m2) + { + return tmat4x2<T, P>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2], + m1[3] - m2[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> operator*(tmat4x2<T, P> const & m, T const & s) + { + return tmat4x2<T, P>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> operator*(T const & s, tmat4x2<T, P> const & m) + { + return tmat4x2<T, P>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x2<T, P>::col_type operator*(tmat4x2<T, P> const & m, typename tmat4x2<T, P>::row_type const & v) + { + return typename tmat4x2<T, P>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z + m[3][0] * v.w, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z + m[3][1] * v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x2<T, P>::row_type operator*(typename tmat4x2<T, P>::col_type const & v, tmat4x2<T, P> const & m) + { + return typename tmat4x2<T, P>::row_type( + v.x * m[0][0] + v.y * m[0][1], + v.x * m[1][0] + v.y * m[1][1], + v.x * m[2][0] + v.y * m[2][1], + v.x * m[3][0] + v.y * m[3][1]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> operator*(tmat4x2<T, P> const & m1, tmat2x4<T, P> const & m2) + { + T const SrcA00 = m1[0][0]; + T const SrcA01 = m1[0][1]; + T const SrcA10 = m1[1][0]; + T const SrcA11 = m1[1][1]; + T const SrcA20 = m1[2][0]; + T const SrcA21 = m1[2][1]; + T const SrcA30 = m1[3][0]; + T const SrcA31 = m1[3][1]; + + T const SrcB00 = m2[0][0]; + T const SrcB01 = m2[0][1]; + T const SrcB02 = m2[0][2]; + T const SrcB03 = m2[0][3]; + T const SrcB10 = m2[1][0]; + T const SrcB11 = m2[1][1]; + T const SrcB12 = m2[1][2]; + T const SrcB13 = m2[1][3]; + + tmat2x2<T, P> Result(uninitialize); + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02 + SrcA30 * SrcB03; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02 + SrcA31 * SrcB03; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12 + SrcA30 * SrcB13; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12 + SrcA31 * SrcB13; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> operator*(tmat4x2<T, P> const & m1, tmat3x4<T, P> const & m2) + { + return tmat3x2<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> operator*(tmat4x2<T, P> const & m1, tmat4x4<T, P> const & m2) + { + return tmat4x2<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2] + m1[3][0] * m2[3][3], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2] + m1[3][1] * m2[3][3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> operator/(tmat4x2<T, P> const & m, T const & s) + { + return tmat4x2<T, P>( + m[0] / s, + m[1] / s, + m[2] / s, + m[3] / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> operator/(T const & s, tmat4x2<T, P> const & m) + { + return tmat4x2<T, P>( + s / m[0], + s / m[1], + s / m[2], + s / m[3]); + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> const operator-(tmat4x2<T, P> const & m) + { + return tmat4x2<T, P>( + -m[0], + -m[1], + -m[2], + -m[3]); + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tmat4x2<T, P> const & m1, tmat4x2<T, P> const & m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tmat4x2<T, P> const & m1, tmat4x2<T, P> const & m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]); + } +} //namespace glm diff --git a/extensions/common/glm/detail/type_mat4x3.hpp b/extensions/common/glm/detail/type_mat4x3.hpp new file mode 100644 index 0000000000..6789b24fbb --- /dev/null +++ b/extensions/common/glm/detail/type_mat4x3.hpp @@ -0,0 +1,211 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat4x3.hpp +/// @date 2006-08-04 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../fwd.hpp" +#include "type_vec3.hpp" +#include "type_vec4.hpp" +#include "type_mat.hpp" +#include <limits> +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tmat4x3 + { + typedef tvec3<T, P> col_type; + typedef tvec4<T, P> row_type; + typedef tmat4x3<T, P> type; + typedef tmat3x4<T, P> transpose_type; + typedef T value_type; + + private: + // Data + col_type value[4]; + + public: + // Constructors + GLM_FUNC_DECL tmat4x3(); + GLM_FUNC_DECL tmat4x3(tmat4x3<T, P> const & m); + template <precision Q> + GLM_FUNC_DECL tmat4x3(tmat4x3<T, Q> const & m); + + GLM_FUNC_DECL explicit tmat4x3(ctor); + GLM_FUNC_DECL explicit tmat4x3(T const & x); + GLM_FUNC_DECL tmat4x3( + T const & x0, T const & y0, T const & z0, + T const & x1, T const & y1, T const & z1, + T const & x2, T const & y2, T const & z2, + T const & x3, T const & y3, T const & z3); + GLM_FUNC_DECL tmat4x3( + col_type const & v0, + col_type const & v1, + col_type const & v2, + col_type const & v3); + + ////////////////////////////////////// + // Conversions + + template < + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3, + typename X4, typename Y4, typename Z4> + GLM_FUNC_DECL tmat4x3( + X1 const & x1, Y1 const & y1, Z1 const & z1, + X2 const & x2, Y2 const & y2, Z2 const & z2, + X3 const & x3, Y3 const & y3, Z3 const & z3, + X4 const & x4, Y4 const & y4, Z4 const & z4); + + template <typename V1, typename V2, typename V3, typename V4> + GLM_FUNC_DECL tmat4x3( + tvec3<V1, P> const & v1, + tvec3<V2, P> const & v2, + tvec3<V3, P> const & v3, + tvec3<V4, P> const & v4); + + ////////////////////////////////////// + // Matrix conversions + +# ifdef GLM_FORCE_EXPLICIT_CTOR + template <typename U, precision Q> + GLM_FUNC_DECL explicit tmat4x3(tmat4x3<U, Q> const & m); +# else + template <typename U, precision Q> + GLM_FUNC_DECL tmat4x3(tmat4x3<U, Q> const & m); +# endif + + GLM_FUNC_DECL explicit tmat4x3(tmat2x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x3(tmat3x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x3(tmat4x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x3(tmat2x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x3(tmat3x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x3(tmat2x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x3(tmat4x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x3(tmat3x4<T, P> const & x); + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_t size() const; + + GLM_FUNC_DECL col_type & operator[](size_type i); + GLM_FUNC_DECL col_type const & operator[](size_type i) const; +# else + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL col_type const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tmat4x3<T, P> & operator=(tmat4x3<T, P> const & m); + + template <typename U> + GLM_FUNC_DECL tmat4x3<T, P> & operator=(tmat4x3<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat4x3<T, P> & operator+=(U s); + template <typename U> + GLM_FUNC_DECL tmat4x3<T, P> & operator+=(tmat4x3<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat4x3<T, P> & operator-=(U s); + template <typename U> + GLM_FUNC_DECL tmat4x3<T, P> & operator-=(tmat4x3<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat4x3<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tmat4x3<T, P> & operator/=(U s); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tmat4x3<T, P> & operator++(); + GLM_FUNC_DECL tmat4x3<T, P> & operator--(); + GLM_FUNC_DECL tmat4x3<T, P> operator++(int); + GLM_FUNC_DECL tmat4x3<T, P> operator--(int); + }; + + // Binary operators + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> operator+(tmat4x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> operator+(tmat4x3<T, P> const & m1, tmat4x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> operator-(tmat4x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> operator-(tmat4x3<T, P> const & m1, tmat4x3<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> operator*(tmat4x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> operator*(T const & s, tmat4x3<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat4x3<T, P>::col_type operator*(tmat4x3<T, P> const & m, typename tmat4x3<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat4x3<T, P>::row_type operator*(typename tmat4x3<T, P>::col_type const & v, tmat4x3<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> operator*(tmat4x3<T, P> const & m1, tmat2x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> operator*(tmat4x3<T, P> const & m1, tmat3x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> operator*(tmat4x3<T, P> const & m1, tmat4x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> operator/(tmat4x3<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> operator/(T const & s, tmat4x3<T, P> const & m); + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> const operator-(tmat4x3<T, P> const & m); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat4x3.inl" +#endif //GLM_EXTERNAL_TEMPLATE diff --git a/extensions/common/glm/detail/type_mat4x3.inl b/extensions/common/glm/detail/type_mat4x3.inl new file mode 100644 index 0000000000..ce61fdd81e --- /dev/null +++ b/extensions/common/glm/detail/type_mat4x3.inl @@ -0,0 +1,631 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat4x3.inl +/// @date 2006-04-17 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + ////////////////////////////////////////////////////////////// + // Constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3() + { +# ifndef GLM_FORCE_NO_CTOR_INIT + this->value[0] = col_type(1, 0, 0); + this->value[1] = col_type(0, 1, 0); + this->value[2] = col_type(0, 0, 1); + this->value[3] = col_type(0, 0, 0); +# endif + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(tmat4x3<T, P> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + this->value[3] = m.value[3]; + } + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(tmat4x3<T, Q> const & m) + { + this->value[0] = m.value[0]; + this->value[1] = m.value[1]; + this->value[2] = m.value[2]; + this->value[3] = m.value[3]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(T const & s) + { + this->value[0] = col_type(s, 0, 0); + this->value[1] = col_type(0, s, 0); + this->value[2] = col_type(0, 0, s); + this->value[3] = col_type(0, 0, 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3 + ( + T const & x0, T const & y0, T const & z0, + T const & x1, T const & y1, T const & z1, + T const & x2, T const & y2, T const & z2, + T const & x3, T const & y3, T const & z3 + ) + { + this->value[0] = col_type(x0, y0, z0); + this->value[1] = col_type(x1, y1, z1); + this->value[2] = col_type(x2, y2, z2); + this->value[3] = col_type(x3, y3, z3); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3 + ( + col_type const & v0, + col_type const & v1, + col_type const & v2, + col_type const & v3 + ) + { + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + this->value[3] = v3; + } + + ////////////////////////////////////// + // Conversion constructors + + template <typename T, precision P> + template < + typename X1, typename Y1, typename Z1, + typename X2, typename Y2, typename Z2, + typename X3, typename Y3, typename Z3, + typename X4, typename Y4, typename Z4> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3 + ( + X1 const & x1, Y1 const & y1, Z1 const & z1, + X2 const & x2, Y2 const & y2, Z2 const & z2, + X3 const & x3, Y3 const & y3, Z3 const & z3, + X4 const & x4, Y4 const & y4, Z4 const & z4 + ) + { + this->value[0] = col_type(static_cast<T>(x1), value_type(y1), value_type(z1)); + this->value[1] = col_type(static_cast<T>(x2), value_type(y2), value_type(z2)); + this->value[2] = col_type(static_cast<T>(x3), value_type(y3), value_type(z3)); + this->value[3] = col_type(static_cast<T>(x4), value_type(y4), value_type(z4)); + } + + template <typename T, precision P> + template <typename V1, typename V2, typename V3, typename V4> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3 + ( + tvec3<V1, P> const & v1, + tvec3<V2, P> const & v2, + tvec3<V3, P> const & v3, + tvec3<V4, P> const & v4 + ) + { + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + this->value[3] = col_type(v4); + } + + ////////////////////////////////////////////////////////////// + // Matrix conversions + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(tmat4x3<U, Q> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(tmat2x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); + this->value[3] = col_type(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(tmat3x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(tmat4x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(tmat2x3<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1); + this->value[3] = col_type(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(tmat3x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); + this->value[3] = col_type(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(tmat2x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(0, 0, 1); + this->value[3] = col_type(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(tmat4x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 1); + this->value[3] = col_type(m[3], 0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>::tmat4x3(tmat3x4<T, P> const & m) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(0); + } + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat4x3<T, P>::size_type tmat4x3<T, P>::size() const + { + return 4; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x3<T, P>::col_type & tmat4x3<T, P>::operator[](typename tmat4x3<T, P>::size_type i) + { + assert(i < this->size()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x3<T, P>::col_type const & tmat4x3<T, P>::operator[](typename tmat4x3<T, P>::size_type i) const + { + assert(i < this->size()); + return this->value[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat4x3<T, P>::length_type tmat4x3<T, P>::length() const + { + return 4; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x3<T, P>::col_type & tmat4x3<T, P>::operator[](typename tmat4x3<T, P>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x3<T, P>::col_type const & tmat4x3<T, P>::operator[](typename tmat4x3<T, P>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////////////////////////////// + // Unary updatable operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P>& tmat4x3<T, P>::operator=(tmat4x3<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x3<T, P>& tmat4x3<T, P>::operator=(tmat4x3<U, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x3<T, P> & tmat4x3<T, P>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + this->value[3] += s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x3<T, P> & tmat4x3<T, P>::operator+=(tmat4x3<U, P> const & m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + this->value[3] += m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x3<T, P> & tmat4x3<T, P>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + this->value[3] -= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x3<T, P> & tmat4x3<T, P>::operator-=(tmat4x3<U, P> const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + this->value[3] -= m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x3<T, P> & tmat4x3<T, P>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + this->value[3] *= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x3<T, P> & tmat4x3<T, P>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + this->value[3] /= s; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> & tmat4x3<T, P>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + ++this->value[3]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> & tmat4x3<T, P>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + --this->value[3]; + return *this; + } + + ////////////////////////////////////////////////////////////// + // Binary operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> operator+(tmat4x3<T, P> const & m, T const & s) + { + return tmat4x3<T, P>( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> operator+(tmat4x3<T, P> const & m1, tmat4x3<T, P> const & m2) + { + return tmat4x3<T, P>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2], + m1[3] + m2[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> operator-(tmat4x3<T, P> const & m, T const & s) + { + return tmat4x3<T, P>( + m[0] - s, + m[1] - s, + m[2] - s, + m[3] - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> operator-(tmat4x3<T, P> const & m1, tmat4x3<T, P> const & m2) + { + return tmat4x3<T, P>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2], + m1[3] - m2[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> operator*(tmat4x3<T, P> const & m, T const & s) + { + return tmat4x3<T, P>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> operator*(T const & s, tmat4x3<T, P> const & m) + { + return tmat4x3<T, P>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x3<T, P>::col_type operator* + ( + tmat4x3<T, P> const & m, + typename tmat4x3<T, P>::row_type const & v) + { + return typename tmat4x3<T, P>::col_type( + m[0][0] * v.x + m[1][0] * v.y + m[2][0] * v.z + m[3][0] * v.w, + m[0][1] * v.x + m[1][1] * v.y + m[2][1] * v.z + m[3][1] * v.w, + m[0][2] * v.x + m[1][2] * v.y + m[2][2] * v.z + m[3][2] * v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x3<T, P>::row_type operator* + ( + typename tmat4x3<T, P>::col_type const & v, + tmat4x3<T, P> const & m) + { + return typename tmat4x3<T, P>::row_type( + v.x * m[0][0] + v.y * m[0][1] + v.z * m[0][2], + v.x * m[1][0] + v.y * m[1][1] + v.z * m[1][2], + v.x * m[2][0] + v.y * m[2][1] + v.z * m[2][2], + v.x * m[3][0] + v.y * m[3][1] + v.z * m[3][2]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> operator*(tmat4x3<T, P> const & m1, tmat2x4<T, P> const & m2) + { + return tmat2x3<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> operator*(tmat4x3<T, P> const & m1, tmat3x4<T, P> const & m2) + { + T const SrcA00 = m1[0][0]; + T const SrcA01 = m1[0][1]; + T const SrcA02 = m1[0][2]; + T const SrcA10 = m1[1][0]; + T const SrcA11 = m1[1][1]; + T const SrcA12 = m1[1][2]; + T const SrcA20 = m1[2][0]; + T const SrcA21 = m1[2][1]; + T const SrcA22 = m1[2][2]; + T const SrcA30 = m1[3][0]; + T const SrcA31 = m1[3][1]; + T const SrcA32 = m1[3][2]; + + T const SrcB00 = m2[0][0]; + T const SrcB01 = m2[0][1]; + T const SrcB02 = m2[0][2]; + T const SrcB03 = m2[0][3]; + T const SrcB10 = m2[1][0]; + T const SrcB11 = m2[1][1]; + T const SrcB12 = m2[1][2]; + T const SrcB13 = m2[1][3]; + T const SrcB20 = m2[2][0]; + T const SrcB21 = m2[2][1]; + T const SrcB22 = m2[2][2]; + T const SrcB23 = m2[2][3]; + + tmat3x3<T, P> Result(uninitialize); + Result[0][0] = SrcA00 * SrcB00 + SrcA10 * SrcB01 + SrcA20 * SrcB02 + SrcA30 * SrcB03; + Result[0][1] = SrcA01 * SrcB00 + SrcA11 * SrcB01 + SrcA21 * SrcB02 + SrcA31 * SrcB03; + Result[0][2] = SrcA02 * SrcB00 + SrcA12 * SrcB01 + SrcA22 * SrcB02 + SrcA32 * SrcB03; + Result[1][0] = SrcA00 * SrcB10 + SrcA10 * SrcB11 + SrcA20 * SrcB12 + SrcA30 * SrcB13; + Result[1][1] = SrcA01 * SrcB10 + SrcA11 * SrcB11 + SrcA21 * SrcB12 + SrcA31 * SrcB13; + Result[1][2] = SrcA02 * SrcB10 + SrcA12 * SrcB11 + SrcA22 * SrcB12 + SrcA32 * SrcB13; + Result[2][0] = SrcA00 * SrcB20 + SrcA10 * SrcB21 + SrcA20 * SrcB22 + SrcA30 * SrcB23; + Result[2][1] = SrcA01 * SrcB20 + SrcA11 * SrcB21 + SrcA21 * SrcB22 + SrcA31 * SrcB23; + Result[2][2] = SrcA02 * SrcB20 + SrcA12 * SrcB21 + SrcA22 * SrcB22 + SrcA32 * SrcB23; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> operator*(tmat4x3<T, P> const & m1, tmat4x4<T, P> const & m2) + { + return tmat4x3<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2] + m1[3][2] * m2[2][3], + m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1] + m1[2][0] * m2[3][2] + m1[3][0] * m2[3][3], + m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1] + m1[2][1] * m2[3][2] + m1[3][1] * m2[3][3], + m1[0][2] * m2[3][0] + m1[1][2] * m2[3][1] + m1[2][2] * m2[3][2] + m1[3][2] * m2[3][3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> operator/(tmat4x3<T, P> const & m, T const & s) + { + return tmat4x3<T, P>( + m[0] / s, + m[1] / s, + m[2] / s, + m[3] / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> operator/(T const & s, tmat4x3<T, P> const & m) + { + return tmat4x3<T, P>( + s / m[0], + s / m[1], + s / m[2], + s / m[3]); + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> const operator-(tmat4x3<T, P> const & m) + { + return tmat4x3<T, P>( + -m[0], + -m[1], + -m[2], + -m[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> const operator++(tmat4x3<T, P> const & m, int) + { + return tmat4x3<T, P>( + m[0] + T(1), + m[1] + T(1), + m[2] + T(1), + m[3] + T(1)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> const operator--(tmat4x3<T, P> const & m, int) + { + return tmat4x3<T, P>( + m[0] - T(1), + m[1] - T(1), + m[2] - T(1), + m[3] - T(1)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> tmat4x3<T, P>::operator++(int) + { + tmat4x3<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> tmat4x3<T, P>::operator--(int) + { + tmat4x3<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tmat4x3<T, P> const & m1, tmat4x3<T, P> const & m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tmat4x3<T, P> const & m1, tmat4x3<T, P> const & m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]); + } +} //namespace glm diff --git a/extensions/common/glm/detail/type_mat4x4.hpp b/extensions/common/glm/detail/type_mat4x4.hpp new file mode 100644 index 0000000000..cc058efacb --- /dev/null +++ b/extensions/common/glm/detail/type_mat4x4.hpp @@ -0,0 +1,235 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat4x4.hpp +/// @date 2005-01-27 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../fwd.hpp" +#include "type_vec4.hpp" +#include "type_mat.hpp" +#include <limits> +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tmat4x4 + { + typedef tvec4<T, P> col_type; + typedef tvec4<T, P> row_type; + typedef tmat4x4<T, P> type; + typedef tmat4x4<T, P> transpose_type; + typedef T value_type; + + template <typename U, precision Q> + friend tvec4<U, Q> operator/(tmat4x4<U, Q> const & m, tvec4<U, Q> const & v); + template <typename U, precision Q> + friend tvec4<U, Q> operator/(tvec4<U, Q> const & v, tmat4x4<U, Q> const & m); + + private: + /// @cond DETAIL + col_type value[4]; + /// @endcond + + public: + // Constructors + GLM_FUNC_DECL tmat4x4(); + GLM_FUNC_DECL tmat4x4(tmat4x4<T, P> const & m); + template <precision Q> + GLM_FUNC_DECL tmat4x4(tmat4x4<T, Q> const & m); + + GLM_FUNC_DECL explicit tmat4x4(ctor); + GLM_FUNC_DECL explicit tmat4x4(T const & x); + GLM_FUNC_DECL tmat4x4( + T const & x0, T const & y0, T const & z0, T const & w0, + T const & x1, T const & y1, T const & z1, T const & w1, + T const & x2, T const & y2, T const & z2, T const & w2, + T const & x3, T const & y3, T const & z3, T const & w3); + GLM_FUNC_DECL tmat4x4( + col_type const & v0, + col_type const & v1, + col_type const & v2, + col_type const & v3); + + ////////////////////////////////////// + // Conversions + + template < + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2, + typename X3, typename Y3, typename Z3, typename W3, + typename X4, typename Y4, typename Z4, typename W4> + GLM_FUNC_DECL tmat4x4( + X1 const & x1, Y1 const & y1, Z1 const & z1, W1 const & w1, + X2 const & x2, Y2 const & y2, Z2 const & z2, W2 const & w2, + X3 const & x3, Y3 const & y3, Z3 const & z3, W3 const & w3, + X4 const & x4, Y4 const & y4, Z4 const & z4, W4 const & w4); + + template <typename V1, typename V2, typename V3, typename V4> + GLM_FUNC_DECL tmat4x4( + tvec4<V1, P> const & v1, + tvec4<V2, P> const & v2, + tvec4<V3, P> const & v3, + tvec4<V4, P> const & v4); + + ////////////////////////////////////// + // Matrix conversions + +# ifdef GLM_FORCE_EXPLICIT_CTOR + template <typename U, precision Q> + GLM_FUNC_DECL explicit tmat4x4(tmat4x4<U, Q> const & m); +# else + template <typename U, precision Q> + GLM_FUNC_DECL tmat4x4(tmat4x4<U, Q> const & m); +# endif + + GLM_FUNC_DECL explicit tmat4x4(tmat2x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x4(tmat3x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x4(tmat2x3<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x4(tmat3x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x4(tmat2x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x4(tmat4x2<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x4(tmat3x4<T, P> const & x); + GLM_FUNC_DECL explicit tmat4x4(tmat4x3<T, P> const & x); + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_t size() const; + + GLM_FUNC_DECL col_type & operator[](size_type i); + GLM_FUNC_DECL col_type const & operator[](size_type i) const; +# else + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL col_type & operator[](length_type i); + GLM_FUNC_DECL col_type const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tmat4x4<T, P> & operator=(tmat4x4<T, P> const & m); + + template <typename U> + GLM_FUNC_DECL tmat4x4<T, P> & operator=(tmat4x4<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat4x4<T, P> & operator+=(U s); + template <typename U> + GLM_FUNC_DECL tmat4x4<T, P> & operator+=(tmat4x4<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat4x4<T, P> & operator-=(U s); + template <typename U> + GLM_FUNC_DECL tmat4x4<T, P> & operator-=(tmat4x4<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat4x4<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tmat4x4<T, P> & operator*=(tmat4x4<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tmat4x4<T, P> & operator/=(U s); + template <typename U> + GLM_FUNC_DECL tmat4x4<T, P> & operator/=(tmat4x4<U, P> const & m); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tmat4x4<T, P> & operator++(); + GLM_FUNC_DECL tmat4x4<T, P> & operator--(); + GLM_FUNC_DECL tmat4x4<T, P> operator++(int); + GLM_FUNC_DECL tmat4x4<T, P> operator--(int); + }; + + // Binary operators + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator+(tmat4x4<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator+(T const & s, tmat4x4<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator+(tmat4x4<T, P> const & m1, tmat4x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator-(tmat4x4<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator-(T const & s, tmat4x4<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator-(tmat4x4<T, P> const & m1, tmat4x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator*(tmat4x4<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator*(T const & s, tmat4x4<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat4x4<T, P>::col_type operator*(tmat4x4<T, P> const & m, typename tmat4x4<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat4x4<T, P>::row_type operator*(typename tmat4x4<T, P>::col_type const & v, tmat4x4<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> operator*(tmat4x4<T, P> const & m1, tmat2x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> operator*(tmat4x4<T, P> const & m1, tmat3x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator*(tmat4x4<T, P> const & m1, tmat4x4<T, P> const & m2); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator/(tmat4x4<T, P> const & m, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator/(T const & s, tmat4x4<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat4x4<T, P>::col_type operator/(tmat4x4<T, P> const & m, typename tmat4x4<T, P>::row_type const & v); + + template <typename T, precision P> + GLM_FUNC_DECL typename tmat4x4<T, P>::row_type operator/(typename tmat4x4<T, P>::col_type & v, tmat4x4<T, P> const & m); + + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> operator/(tmat4x4<T, P> const & m1, tmat4x4<T, P> const & m2); + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> const operator-(tmat4x4<T, P> const & m); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_mat4x4.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/extensions/common/glm/detail/type_mat4x4.inl b/extensions/common/glm/detail/type_mat4x4.inl new file mode 100644 index 0000000000..ec9a17c00e --- /dev/null +++ b/extensions/common/glm/detail/type_mat4x4.inl @@ -0,0 +1,790 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_mat4x4.inl +/// @date 2005-01-27 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> compute_inverse(tmat4x4<T, P> const & m) + { + T Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + T Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + T Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + + T Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + T Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + T Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + + T Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + T Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + T Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + + T Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + T Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + T Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + + T Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + T Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + T Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + + T Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + T Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + T Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + tvec4<T, P> Fac0(Coef00, Coef00, Coef02, Coef03); + tvec4<T, P> Fac1(Coef04, Coef04, Coef06, Coef07); + tvec4<T, P> Fac2(Coef08, Coef08, Coef10, Coef11); + tvec4<T, P> Fac3(Coef12, Coef12, Coef14, Coef15); + tvec4<T, P> Fac4(Coef16, Coef16, Coef18, Coef19); + tvec4<T, P> Fac5(Coef20, Coef20, Coef22, Coef23); + + tvec4<T, P> Vec0(m[1][0], m[0][0], m[0][0], m[0][0]); + tvec4<T, P> Vec1(m[1][1], m[0][1], m[0][1], m[0][1]); + tvec4<T, P> Vec2(m[1][2], m[0][2], m[0][2], m[0][2]); + tvec4<T, P> Vec3(m[1][3], m[0][3], m[0][3], m[0][3]); + + tvec4<T, P> Inv0(Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2); + tvec4<T, P> Inv1(Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4); + tvec4<T, P> Inv2(Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5); + tvec4<T, P> Inv3(Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5); + + tvec4<T, P> SignA(+1, -1, +1, -1); + tvec4<T, P> SignB(-1, +1, -1, +1); + tmat4x4<T, P> Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB); + + tvec4<T, P> Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]); + + tvec4<T, P> Dot0(m[0] * Row0); + T Dot1 = (Dot0.x + Dot0.y) + (Dot0.z + Dot0.w); + + T OneOverDeterminant = static_cast<T>(1) / Dot1; + + return Inverse * OneOverDeterminant; + } +}//namespace detail + + ////////////////////////////////////////////////////////////// + // Constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4() + { +# ifndef GLM_FORCE_NO_CTOR_INIT + this->value[0] = col_type(1, 0, 0, 0); + this->value[1] = col_type(0, 1, 0, 0); + this->value[2] = col_type(0, 0, 1, 0); + this->value[3] = col_type(0, 0, 0, 1); +# endif + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(tmat4x4<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + } + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(tmat4x4<T, Q> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(T const & s) + { + this->value[0] = col_type(s, 0, 0, 0); + this->value[1] = col_type(0, s, 0, 0); + this->value[2] = col_type(0, 0, s, 0); + this->value[3] = col_type(0, 0, 0, s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4 + ( + T const & x0, T const & y0, T const & z0, T const & w0, + T const & x1, T const & y1, T const & z1, T const & w1, + T const & x2, T const & y2, T const & z2, T const & w2, + T const & x3, T const & y3, T const & z3, T const & w3 + ) + { + this->value[0] = col_type(x0, y0, z0, w0); + this->value[1] = col_type(x1, y1, z1, w1); + this->value[2] = col_type(x2, y2, z2, w2); + this->value[3] = col_type(x3, y3, z3, w3); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4 + ( + col_type const & v0, + col_type const & v1, + col_type const & v2, + col_type const & v3 + ) + { + this->value[0] = v0; + this->value[1] = v1; + this->value[2] = v2; + this->value[3] = v3; + } + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4 + ( + tmat4x4<U, Q> const & m + ) + { + this->value[0] = col_type(m[0]); + this->value[1] = col_type(m[1]); + this->value[2] = col_type(m[2]); + this->value[3] = col_type(m[3]); + } + + ////////////////////////////////////// + // Conversion constructors + template <typename T, precision P> + template < + typename X1, typename Y1, typename Z1, typename W1, + typename X2, typename Y2, typename Z2, typename W2, + typename X3, typename Y3, typename Z3, typename W3, + typename X4, typename Y4, typename Z4, typename W4> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4 + ( + X1 const & x1, Y1 const & y1, Z1 const & z1, W1 const & w1, + X2 const & x2, Y2 const & y2, Z2 const & z2, W2 const & w2, + X3 const & x3, Y3 const & y3, Z3 const & z3, W3 const & w3, + X4 const & x4, Y4 const & y4, Z4 const & z4, W4 const & w4 + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<X1>::is_iec559 || std::numeric_limits<X1>::is_integer, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Y1>::is_iec559 || std::numeric_limits<Y1>::is_integer, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Z1>::is_iec559 || std::numeric_limits<Z1>::is_integer, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<W1>::is_iec559 || std::numeric_limits<W1>::is_integer, "*mat4x4 constructor only takes float and integer types, 4th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits<X2>::is_iec559 || std::numeric_limits<X2>::is_integer, "*mat4x4 constructor only takes float and integer types, 5th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Y2>::is_iec559 || std::numeric_limits<Y2>::is_integer, "*mat4x4 constructor only takes float and integer types, 6th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Z2>::is_iec559 || std::numeric_limits<Z2>::is_integer, "*mat4x4 constructor only takes float and integer types, 7th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<W2>::is_iec559 || std::numeric_limits<W2>::is_integer, "*mat4x4 constructor only takes float and integer types, 8th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits<X3>::is_iec559 || std::numeric_limits<X3>::is_integer, "*mat4x4 constructor only takes float and integer types, 9th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Y3>::is_iec559 || std::numeric_limits<Y3>::is_integer, "*mat4x4 constructor only takes float and integer types, 10th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Z3>::is_iec559 || std::numeric_limits<Z3>::is_integer, "*mat4x4 constructor only takes float and integer types, 11th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<W3>::is_iec559 || std::numeric_limits<W3>::is_integer, "*mat4x4 constructor only takes float and integer types, 12th parameter type invalid."); + + GLM_STATIC_ASSERT(std::numeric_limits<X4>::is_iec559 || std::numeric_limits<X4>::is_integer, "*mat4x4 constructor only takes float and integer types, 13th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Y4>::is_iec559 || std::numeric_limits<Y4>::is_integer, "*mat4x4 constructor only takes float and integer types, 14th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<Z4>::is_iec559 || std::numeric_limits<Z4>::is_integer, "*mat4x4 constructor only takes float and integer types, 15th parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<W4>::is_iec559 || std::numeric_limits<W4>::is_integer, "*mat4x4 constructor only takes float and integer types, 16th parameter type invalid."); + + this->value[0] = col_type(static_cast<T>(x1), value_type(y1), value_type(z1), value_type(w1)); + this->value[1] = col_type(static_cast<T>(x2), value_type(y2), value_type(z2), value_type(w2)); + this->value[2] = col_type(static_cast<T>(x3), value_type(y3), value_type(z3), value_type(w3)); + this->value[3] = col_type(static_cast<T>(x4), value_type(y4), value_type(z4), value_type(w4)); + } + + template <typename T, precision P> + template <typename V1, typename V2, typename V3, typename V4> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4 + ( + tvec4<V1, P> const & v1, + tvec4<V2, P> const & v2, + tvec4<V3, P> const & v3, + tvec4<V4, P> const & v4 + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<V1>::is_iec559 || std::numeric_limits<V1>::is_integer, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<V2>::is_iec559 || std::numeric_limits<V2>::is_integer, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<V3>::is_iec559 || std::numeric_limits<V3>::is_integer, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid."); + GLM_STATIC_ASSERT(std::numeric_limits<V4>::is_iec559 || std::numeric_limits<V4>::is_integer, "*mat4x4 constructor only takes float and integer types, 4th parameter type invalid."); + + this->value[0] = col_type(v1); + this->value[1] = col_type(v2); + this->value[2] = col_type(v3); + this->value[3] = col_type(v4); + } + + ////////////////////////////////////// + // Matrix convertion constructors + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(tmat2x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(0); + this->value[3] = col_type(0, 0, 0, 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(tmat3x3<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); + this->value[3] = col_type(0, 0, 0, 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(tmat2x3<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(0); + this->value[3] = col_type(0, 0, 0, 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(tmat3x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(m[2], 0, 0); + this->value[3] = col_type(0, 0, 0, 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(tmat2x4<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = col_type(0); + this->value[3] = col_type(0, 0, 0, 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(tmat4x2<T, P> const & m) + { + this->value[0] = col_type(m[0], 0, 0); + this->value[1] = col_type(m[1], 0, 0); + this->value[2] = col_type(0); + this->value[3] = col_type(0, 0, 0, 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(tmat3x4<T, P> const & m) + { + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = col_type(0, 0, 0, 1); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4(tmat4x3<T, P> const & m) + { + this->value[0] = col_type(m[0], 0); + this->value[1] = col_type(m[1], 0); + this->value[2] = col_type(m[2], 0); + this->value[3] = col_type(m[3], 1); + } + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat4x4<T, P>::size_type tmat4x4<T, P>::size() const + { + return 4; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type & tmat4x4<T, P>::operator[](typename tmat4x4<T, P>::size_type i) + { + assert(i < this->size()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type const & tmat4x4<T, P>::operator[](typename tmat4x4<T, P>::size_type i) const + { + assert(i < this->size()); + return this->value[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tmat4x4<T, P>::length_type tmat4x4<T, P>::length() const + { + return 4; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type & tmat4x4<T, P>::operator[](typename tmat4x4<T, P>::length_type i) + { + assert(i < this->length()); + return this->value[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type const & tmat4x4<T, P>::operator[](typename tmat4x4<T, P>::length_type i) const + { + assert(i < this->length()); + return this->value[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////////////////////////////// + // Operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator=(tmat4x4<T, P> const & m) + { + //memcpy could be faster + //memcpy(&this->value, &m.value, 16 * sizeof(valType)); + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator=(tmat4x4<U, P> const & m) + { + //memcpy could be faster + //memcpy(&this->value, &m.value, 16 * sizeof(valType)); + this->value[0] = m[0]; + this->value[1] = m[1]; + this->value[2] = m[2]; + this->value[3] = m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator+=(U s) + { + this->value[0] += s; + this->value[1] += s; + this->value[2] += s; + this->value[3] += s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator+=(tmat4x4<U, P> const & m) + { + this->value[0] += m[0]; + this->value[1] += m[1]; + this->value[2] += m[2]; + this->value[3] += m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator-=(U s) + { + this->value[0] -= s; + this->value[1] -= s; + this->value[2] -= s; + this->value[3] -= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator-=(tmat4x4<U, P> const & m) + { + this->value[0] -= m[0]; + this->value[1] -= m[1]; + this->value[2] -= m[2]; + this->value[3] -= m[3]; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator*=(U s) + { + this->value[0] *= s; + this->value[1] *= s; + this->value[2] *= s; + this->value[3] *= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator*=(tmat4x4<U, P> const & m) + { + return (*this = *this * m); + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator/=(U s) + { + this->value[0] /= s; + this->value[1] /= s; + this->value[2] /= s; + this->value[3] /= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator/=(tmat4x4<U, P> const & m) + { + return (*this = *this * detail::compute_inverse<T, P>(m)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator++() + { + ++this->value[0]; + ++this->value[1]; + ++this->value[2]; + ++this->value[3]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator--() + { + --this->value[0]; + --this->value[1]; + --this->value[2]; + --this->value[3]; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> tmat4x4<T, P>::operator++(int) + { + tmat4x4<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> tmat4x4<T, P>::operator--(int) + { + tmat4x4<T, P> Result(*this); + --*this; + return Result; + } + + // Binary operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator+(tmat4x4<T, P> const & m, T const & s) + { + return tmat4x4<T, P>( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator+(T const & s, tmat4x4<T, P> const & m) + { + return tmat4x4<T, P>( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator+(tmat4x4<T, P> const & m1, tmat4x4<T, P> const & m2) + { + return tmat4x4<T, P>( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2], + m1[3] + m2[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator-(tmat4x4<T, P> const & m, T const & s) + { + return tmat4x4<T, P>( + m[0] - s, + m[1] - s, + m[2] - s, + m[3] - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator-(T const & s, tmat4x4<T, P> const & m) + { + return tmat4x4<T, P>( + s - m[0], + s - m[1], + s - m[2], + s - m[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator-(tmat4x4<T, P> const & m1, tmat4x4<T, P> const & m2) + { + return tmat4x4<T, P>( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2], + m1[3] - m2[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*(tmat4x4<T, P> const & m, T const & s) + { + return tmat4x4<T, P>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*(T const & s, tmat4x4<T, P> const & m) + { + return tmat4x4<T, P>( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type operator* + ( + tmat4x4<T, P> const & m, + typename tmat4x4<T, P>::row_type const & v + ) + { +/* + __m128 v0 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 v1 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 v2 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 v3 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 3, 3, 3)); + + __m128 m0 = _mm_mul_ps(m[0].data, v0); + __m128 m1 = _mm_mul_ps(m[1].data, v1); + __m128 a0 = _mm_add_ps(m0, m1); + + __m128 m2 = _mm_mul_ps(m[2].data, v2); + __m128 m3 = _mm_mul_ps(m[3].data, v3); + __m128 a1 = _mm_add_ps(m2, m3); + + __m128 a2 = _mm_add_ps(a0, a1); + + return typename tmat4x4<T, P>::col_type(a2); +*/ + + typename tmat4x4<T, P>::col_type const Mov0(v[0]); + typename tmat4x4<T, P>::col_type const Mov1(v[1]); + typename tmat4x4<T, P>::col_type const Mul0 = m[0] * Mov0; + typename tmat4x4<T, P>::col_type const Mul1 = m[1] * Mov1; + typename tmat4x4<T, P>::col_type const Add0 = Mul0 + Mul1; + typename tmat4x4<T, P>::col_type const Mov2(v[2]); + typename tmat4x4<T, P>::col_type const Mov3(v[3]); + typename tmat4x4<T, P>::col_type const Mul2 = m[2] * Mov2; + typename tmat4x4<T, P>::col_type const Mul3 = m[3] * Mov3; + typename tmat4x4<T, P>::col_type const Add1 = Mul2 + Mul3; + typename tmat4x4<T, P>::col_type const Add2 = Add0 + Add1; + return Add2; + +/* + return typename tmat4x4<T, P>::col_type( + m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3], + m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3], + m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3], + m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3]); +*/ + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::row_type operator* + ( + typename tmat4x4<T, P>::col_type const & v, + tmat4x4<T, P> const & m + ) + { + return typename tmat4x4<T, P>::row_type( + m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3], + m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3], + m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3], + m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> operator*(tmat4x4<T, P> const & m1, tmat2x4<T, P> const & m2) + { + return tmat2x4<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2] + m1[3][3] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2] + m1[3][3] * m2[1][3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> operator*(tmat4x4<T, P> const & m1, tmat3x4<T, P> const & m2) + { + return tmat3x4<T, P>( + m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3], + m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3], + m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3], + m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2] + m1[3][3] * m2[0][3], + m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3], + m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3], + m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3], + m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2] + m1[3][3] * m2[1][3], + m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3], + m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3], + m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2] + m1[3][2] * m2[2][3], + m1[0][3] * m2[2][0] + m1[1][3] * m2[2][1] + m1[2][3] * m2[2][2] + m1[3][3] * m2[2][3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*(tmat4x4<T, P> const & m1, tmat4x4<T, P> const & m2) + { + typename tmat4x4<T, P>::col_type const SrcA0 = m1[0]; + typename tmat4x4<T, P>::col_type const SrcA1 = m1[1]; + typename tmat4x4<T, P>::col_type const SrcA2 = m1[2]; + typename tmat4x4<T, P>::col_type const SrcA3 = m1[3]; + + typename tmat4x4<T, P>::col_type const SrcB0 = m2[0]; + typename tmat4x4<T, P>::col_type const SrcB1 = m2[1]; + typename tmat4x4<T, P>::col_type const SrcB2 = m2[2]; + typename tmat4x4<T, P>::col_type const SrcB3 = m2[3]; + + tmat4x4<T, P> Result(uninitialize); + Result[0] = SrcA0 * SrcB0[0] + SrcA1 * SrcB0[1] + SrcA2 * SrcB0[2] + SrcA3 * SrcB0[3]; + Result[1] = SrcA0 * SrcB1[0] + SrcA1 * SrcB1[1] + SrcA2 * SrcB1[2] + SrcA3 * SrcB1[3]; + Result[2] = SrcA0 * SrcB2[0] + SrcA1 * SrcB2[1] + SrcA2 * SrcB2[2] + SrcA3 * SrcB2[3]; + Result[3] = SrcA0 * SrcB3[0] + SrcA1 * SrcB3[1] + SrcA2 * SrcB3[2] + SrcA3 * SrcB3[3]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator/(tmat4x4<T, P> const & m, T const & s) + { + return tmat4x4<T, P>( + m[0] / s, + m[1] / s, + m[2] / s, + m[3] / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator/(T const & s, tmat4x4<T, P> const & m) + { + return tmat4x4<T, P>( + s / m[0], + s / m[1], + s / m[2], + s / m[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type operator/(tmat4x4<T, P> const & m, typename tmat4x4<T, P>::row_type const & v) + { + return detail::compute_inverse<T, P>(m) * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::row_type operator/(typename tmat4x4<T, P>::col_type const & v, tmat4x4<T, P> const & m) + { + return v * detail::compute_inverse<T, P>(m); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> operator/(tmat4x4<T, P> const & m1, tmat4x4<T, P> const & m2) + { + tmat4x4<T, P> m1_copy(m1); + return m1_copy /= m2; + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> const operator-(tmat4x4<T, P> const & m) + { + return tmat4x4<T, P>( + -m[0], + -m[1], + -m[2], + -m[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> const operator++(tmat4x4<T, P> const & m, int) + { + return tmat4x4<T, P>( + m[0] + static_cast<T>(1), + m[1] + static_cast<T>(1), + m[2] + static_cast<T>(1), + m[3] + static_cast<T>(1)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> const operator--(tmat4x4<T, P> const & m, int) + { + return tmat4x4<T, P>( + m[0] - static_cast<T>(1), + m[1] - static_cast<T>(1), + m[2] - static_cast<T>(1), + m[3] - static_cast<T>(1)); + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tmat4x4<T, P> const & m1, tmat4x4<T, P> const & m2) + { + return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tmat4x4<T, P> const & m1, tmat4x4<T, P> const & m2) + { + return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]); + } +}//namespace glm diff --git a/extensions/common/glm/detail/type_vec.hpp b/extensions/common/glm/detail/type_vec.hpp new file mode 100644 index 0000000000..0936a17f78 --- /dev/null +++ b/extensions/common/glm/detail/type_vec.hpp @@ -0,0 +1,518 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_vec.hpp +/// @date 2010-01-26 / 2014-10-05 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "precision.hpp" +#include "type_int.hpp" + +namespace glm +{ + template <typename T, precision P> struct tvec1; + template <typename T, precision P> struct tvec2; + template <typename T, precision P> struct tvec3; + template <typename T, precision P> struct tvec4; + + typedef tvec1<float, highp> highp_vec1_t; + typedef tvec1<float, mediump> mediump_vec1_t; + typedef tvec1<float, lowp> lowp_vec1_t; + typedef tvec1<double, highp> highp_dvec1_t; + typedef tvec1<double, mediump> mediump_dvec1_t; + typedef tvec1<double, lowp> lowp_dvec1_t; + typedef tvec1<int, highp> highp_ivec1_t; + typedef tvec1<int, mediump> mediump_ivec1_t; + typedef tvec1<int, lowp> lowp_ivec1_t; + typedef tvec1<uint, highp> highp_uvec1_t; + typedef tvec1<uint, mediump> mediump_uvec1_t; + typedef tvec1<uint, lowp> lowp_uvec1_t; + typedef tvec1<bool, highp> highp_bvec1_t; + typedef tvec1<bool, mediump> mediump_bvec1_t; + typedef tvec1<bool, lowp> lowp_bvec1_t; + + /// @addtogroup core_precision + /// @{ + + /// 2 components vector of high single-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<float, highp> highp_vec2; + + /// 2 components vector of medium single-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<float, mediump> mediump_vec2; + + /// 2 components vector of low single-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<float, lowp> lowp_vec2; + + /// 2 components vector of high double-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<double, highp> highp_dvec2; + + /// 2 components vector of medium double-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<double, mediump> mediump_dvec2; + + /// 2 components vector of low double-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<double, lowp> lowp_dvec2; + + /// 2 components vector of high precision signed integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<int, highp> highp_ivec2; + + /// 2 components vector of medium precision signed integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<int, mediump> mediump_ivec2; + + /// 2 components vector of low precision signed integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<int, lowp> lowp_ivec2; + + /// 2 components vector of high precision unsigned integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<uint, highp> highp_uvec2; + + /// 2 components vector of medium precision unsigned integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<uint, mediump> mediump_uvec2; + + /// 2 components vector of low precision unsigned integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<uint, lowp> lowp_uvec2; + + /// 2 components vector of high precision bool numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<bool, highp> highp_bvec2; + + /// 2 components vector of medium precision bool numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<bool, mediump> mediump_bvec2; + + /// 2 components vector of low precision bool numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec2<bool, lowp> lowp_bvec2; + + /// @} + + + /// @addtogroup core_precision + /// @{ + + /// 3 components vector of high single-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<float, highp> highp_vec3; + + /// 3 components vector of medium single-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<float, mediump> mediump_vec3; + + /// 3 components vector of low single-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<float, lowp> lowp_vec3; + + /// 3 components vector of high double-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<double, highp> highp_dvec3; + + /// 3 components vector of medium double-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<double, mediump> mediump_dvec3; + + /// 3 components vector of low double-precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<double, lowp> lowp_dvec3; + + /// 3 components vector of high precision signed integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<int, highp> highp_ivec3; + + /// 3 components vector of medium precision signed integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<int, mediump> mediump_ivec3; + + /// 3 components vector of low precision signed integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<int, lowp> lowp_ivec3; + + /// 3 components vector of high precision unsigned integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<uint, highp> highp_uvec3; + + /// 3 components vector of medium precision unsigned integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<uint, mediump> mediump_uvec3; + + /// 3 components vector of low precision unsigned integer numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<uint, lowp> lowp_uvec3; + + /// 3 components vector of high precision bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<bool, highp> highp_bvec3; + + /// 3 components vector of medium precision bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<bool, mediump> mediump_bvec3; + + /// 3 components vector of low precision bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec3<bool, lowp> lowp_bvec3; + + /// @} + + /// @addtogroup core_precision + /// @{ + + /// 4 components vector of high single-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<float, highp> highp_vec4; + + /// 4 components vector of medium single-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<float, mediump> mediump_vec4; + + /// 4 components vector of low single-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<float, lowp> lowp_vec4; + + /// 4 components vector of high double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<double, highp> highp_dvec4; + + /// 4 components vector of medium double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<double, mediump> mediump_dvec4; + + /// 4 components vector of low double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<double, lowp> lowp_dvec4; + + /// 4 components vector of high precision signed integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<int, highp> highp_ivec4; + + /// 4 components vector of medium precision signed integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<int, mediump> mediump_ivec4; + + /// 4 components vector of low precision signed integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<int, lowp> lowp_ivec4; + + /// 4 components vector of high precision unsigned integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<uint, highp> highp_uvec4; + + /// 4 components vector of medium precision unsigned integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<uint, mediump> mediump_uvec4; + + /// 4 components vector of low precision unsigned integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<uint, lowp> lowp_uvec4; + + /// 4 components vector of high precision bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<bool, highp> highp_bvec4; + + /// 4 components vector of medium precision bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<bool, mediump> mediump_bvec4; + + /// 4 components vector of low precision bool numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tvec4<bool, lowp> lowp_bvec4; + + /// @} + + /// @addtogroup core_types + /// @{ + + ////////////////////////// + // Default float definition + +#if(defined(GLM_PRECISION_LOWP_FLOAT)) + typedef lowp_vec2 vec2; + typedef lowp_vec3 vec3; + typedef lowp_vec4 vec4; +#elif(defined(GLM_PRECISION_MEDIUMP_FLOAT)) + typedef mediump_vec2 vec2; + typedef mediump_vec3 vec3; + typedef mediump_vec4 vec4; +#else //defined(GLM_PRECISION_HIGHP_FLOAT) + /// 2 components vector of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_vec2 vec2; + + //! 3 components vector of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_vec3 vec3; + + //! 4 components vector of floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_vec4 vec4; +#endif//GLM_PRECISION + + ////////////////////////// + // Default double definition + +#if(defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef lowp_dvec2 dvec2; + typedef lowp_dvec3 dvec3; + typedef lowp_dvec4 dvec4; +#elif(defined(GLM_PRECISION_MEDIUMP_DOUBLE)) + typedef mediump_dvec2 dvec2; + typedef mediump_dvec3 dvec3; + typedef mediump_dvec4 dvec4; +#else //defined(GLM_PRECISION_HIGHP_DOUBLE) + /// 2 components vector of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_dvec2 dvec2; + + //! 3 components vector of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_dvec3 dvec3; + + //! 4 components vector of double-precision floating-point numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_dvec4 dvec4; +#endif//GLM_PRECISION + + ////////////////////////// + // Signed integer definition + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_ivec2 ivec2; + typedef lowp_ivec3 ivec3; + typedef lowp_ivec4 ivec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef mediump_ivec2 ivec2; + typedef mediump_ivec3 ivec3; + typedef mediump_ivec4 ivec4; +#else //defined(GLM_PRECISION_HIGHP_INT) + //! 2 components vector of signed integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_ivec2 ivec2; + + //! 3 components vector of signed integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_ivec3 ivec3; + + //! 4 components vector of signed integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_ivec4 ivec4; +#endif//GLM_PRECISION + + ////////////////////////// + // Unsigned integer definition + +#if(defined(GLM_PRECISION_LOWP_UINT)) + typedef lowp_uvec2 uvec2; + typedef lowp_uvec3 uvec3; + typedef lowp_uvec4 uvec4; +#elif(defined(GLM_PRECISION_MEDIUMP_UINT)) + typedef mediump_uvec2 uvec2; + typedef mediump_uvec3 uvec3; + typedef mediump_uvec4 uvec4; +#else //defined(GLM_PRECISION_HIGHP_UINT) + /// 2 components vector of unsigned integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_uvec2 uvec2; + + /// 3 components vector of unsigned integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_uvec3 uvec3; + + /// 4 components vector of unsigned integer numbers. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_uvec4 uvec4; +#endif//GLM_PRECISION + + ////////////////////////// + // Boolean definition + +#if(defined(GLM_PRECISION_LOWP_BOOL)) + typedef lowp_bvec2 bvec2; + typedef lowp_bvec3 bvec3; + typedef lowp_bvec4 bvec4; +#elif(defined(GLM_PRECISION_MEDIUMP_BOOL)) + typedef mediump_bvec2 bvec2; + typedef mediump_bvec3 bvec3; + typedef mediump_bvec4 bvec4; +#else //defined(GLM_PRECISION_HIGHP_BOOL) + //! 2 components vector of boolean. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_bvec2 bvec2; + + //! 3 components vector of boolean. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_bvec3 bvec3; + + //! 4 components vector of boolean. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.5 Vectors</a> + typedef highp_bvec4 bvec4; +#endif//GLM_PRECISION + + /// @} +}//namespace glm diff --git a/extensions/common/glm/detail/type_vec.inl b/extensions/common/glm/detail/type_vec.inl new file mode 100644 index 0000000000..bc034721d9 --- /dev/null +++ b/extensions/common/glm/detail/type_vec.inl @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_vec.inl +/// @date 2011-06-15 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// diff --git a/extensions/common/glm/detail/type_vec1.hpp b/extensions/common/glm/detail/type_vec1.hpp new file mode 100644 index 0000000000..09589860fe --- /dev/null +++ b/extensions/common/glm/detail/type_vec1.hpp @@ -0,0 +1,322 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_vec1.hpp +/// @date 2008-08-25 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../fwd.hpp" +#include "type_vec.hpp" +#ifdef GLM_SWIZZLE +# if GLM_HAS_ANONYMOUS_UNION +# include "_swizzle.hpp" +# else +# include "_swizzle_func.hpp" +# endif +#endif //GLM_SWIZZLE +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tvec1 + { + ////////////////////////////////////// + // Implementation detail + + typedef tvec1<T, P> type; + typedef tvec1<bool, P> bool_type; + typedef T value_type; + + ////////////////////////////////////// + // Data + +# if GLM_HAS_ANONYMOUS_UNION + union + { + T x; + T r; + T s; +/* +# ifdef GLM_SWIZZLE + _GLM_SWIZZLE1_2_MEMBERS(T, P, tvec2, x) + _GLM_SWIZZLE1_2_MEMBERS(T, P, tvec2, r) + _GLM_SWIZZLE1_2_MEMBERS(T, P, tvec2, s) + _GLM_SWIZZLE1_3_MEMBERS(T, P, tvec3, x) + _GLM_SWIZZLE1_3_MEMBERS(T, P, tvec3, r) + _GLM_SWIZZLE1_3_MEMBERS(T, P, tvec3, s) + _GLM_SWIZZLE1_4_MEMBERS(T, P, tvec4, x) + _GLM_SWIZZLE1_4_MEMBERS(T, P, tvec4, r) + _GLM_SWIZZLE1_4_MEMBERS(T, P, tvec4, s) +# endif//GLM_SWIZZLE*/ + }; +# else + union {T x, r, s;}; +/* +# ifdef GLM_SWIZZLE + GLM_SWIZZLE_GEN_VEC_FROM_VEC1(T, P, tvec2, tvec2, tvec3, tvec4) +# endif//GLM_SWIZZLE*/ +# endif + + ////////////////////////////////////// + // Accesses + +# ifdef GLM_FORCE_SIZE_FUNC + /// Return the count of components of the vector + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_type size() const; + + GLM_FUNC_DECL T & operator[](size_type i); + GLM_FUNC_DECL T const & operator[](size_type i) const; +# else + /// Return the count of components of the vector + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL T & operator[](length_type i); + GLM_FUNC_DECL T const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Implicit basic constructors + + GLM_FUNC_DECL tvec1(); + GLM_FUNC_DECL tvec1(tvec1<T, P> const & v); + template <precision Q> + GLM_FUNC_DECL tvec1(tvec1<T, Q> const & v); + + ////////////////////////////////////// + // Explicit basic constructors + + GLM_FUNC_DECL explicit tvec1(ctor); + GLM_FUNC_DECL explicit tvec1(T const & s); + + ////////////////////////////////////// + // Conversion vector constructors + + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL explicit tvec1(tvec2<U, Q> const & v); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL explicit tvec1(tvec3<U, Q> const & v); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL explicit tvec1(tvec4<U, Q> const & v); + +# ifdef GLM_FORCE_EXPLICIT_CTOR + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL explicit tvec1(tvec1<U, Q> const & v); +# else + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL tvec1(tvec1<U, Q> const & v); +# endif + + ////////////////////////////////////// + // Swizzle constructors + +# if(GLM_HAS_ANONYMOUS_UNION && defined(GLM_SWIZZLE)) + template <int E0> + GLM_FUNC_DECL tvec1(detail::_swizzle<1, T, P, tvec1<T, P>, E0, -1,-2,-3> const & that) + { + *this = that(); + } +# endif//(GLM_HAS_ANONYMOUS_UNION && defined(GLM_SWIZZLE)) + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tvec1<T, P> & operator=(tvec1<T, P> const & v); + + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator+=(U const & s); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator+=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator-=(U const & s); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator-=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator*=(U const & s); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator*=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator/=(U const & s); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator/=(tvec1<U, P> const & v); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tvec1<T, P> & operator++(); + GLM_FUNC_DECL tvec1<T, P> & operator--(); + GLM_FUNC_DECL tvec1<T, P> operator++(int); + GLM_FUNC_DECL tvec1<T, P> operator--(int); + + ////////////////////////////////////// + // Unary bit operators + + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator%=(U const & s); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator%=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator&=(U const & s); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator&=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator|=(U const & s); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator|=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator^=(U const & s); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator^=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator<<=(U const & s); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator<<=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator>>=(U const & s); + template <typename U> + GLM_FUNC_DECL tvec1<T, P> & operator>>=(tvec1<U, P> const & v); + }; + + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator+(tvec1<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator+(T const & s, tvec1<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator+(tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator-(tvec1<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator-(T const & s, tvec1<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator- (tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator*(tvec1<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator*(T const & s, tvec1<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator*(tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator/(tvec1<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator/(T const & s, tvec1<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator/(tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator-(tvec1<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL bool operator==(tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL bool operator!=(tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator%(tvec1<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator%(T const & s, tvec1<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator%(tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator&(tvec1<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator&(T const & s, tvec1<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator&(tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator|(tvec1<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator|(T const & s, tvec1<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator|(tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator^(tvec1<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator^(T const & s, tvec1<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator^(tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator<<(tvec1<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator<<(T const & s, tvec1<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator<<(tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator>>(tvec1<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator>>(T const & s, tvec1<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator>>(tvec1<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec1<T, P> operator~(tvec1<T, P> const & v); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec1.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/extensions/common/glm/detail/type_vec1.inl b/extensions/common/glm/detail/type_vec1.inl new file mode 100644 index 0000000000..15a44e7155 --- /dev/null +++ b/extensions/common/glm/detail/type_vec1.inl @@ -0,0 +1,616 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_vec1.inl +/// @date 2008-08-25 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + ////////////////////////////////////// + // Implicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P>::tvec1() +# ifndef GLM_FORCE_NO_CTOR_INIT + : x(0) +# endif + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P>::tvec1(tvec1<T, P> const & v) + : x(v.x) + {} + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tvec1<T, P>::tvec1(tvec1<T, Q> const & v) + : x(v.x) + {} + + ////////////////////////////////////// + // Explicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P>::tvec1(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P>::tvec1(T const & s) + : x(s) + {} + + ////////////////////////////////////// + // Conversion vector constructors + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tvec1<T, P>::tvec1(tvec1<U, Q> const & v) + : x(static_cast<T>(v.x)) + {} + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tvec1<T, P>::tvec1(tvec2<U, Q> const & v) + : x(static_cast<T>(v.x)) + {} + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tvec1<T, P>::tvec1(tvec3<U, Q> const & v) + : x(static_cast<T>(v.x)) + {} + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tvec1<T, P>::tvec1(tvec4<U, Q> const & v) + : x(static_cast<T>(v.x)) + {} + + ////////////////////////////////////// + // Component accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tvec1<T, P>::size_type tvec1<T, P>::size() const + { + return 1; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T & tvec1<T, P>::operator[](typename tvec1<T, P>::size_type i) + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T const & tvec1<T, P>::operator[](typename tvec1<T, P>::size_type i) const + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tvec1<T, P>::length_type tvec1<T, P>::length() const + { + return 1; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T & tvec1<T, P>::operator[](typename tvec1<T, P>::length_type i) + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T const & tvec1<T, P>::operator[](typename tvec1<T, P>::length_type i) const + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator=(tvec1<T, P> const & v) + { + this->x = v.x; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator=(tvec1<U, P> const & v) + { + this->x = static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator+=(U const & s) + { + this->x += static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator+=(tvec1<U, P> const & v) + { + this->x += static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator-=(U const & s) + { + this->x -= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator-=(tvec1<U, P> const & v) + { + this->x -= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator*=(U const & s) + { + this->x *= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator*=(tvec1<U, P> const & v) + { + this->x *= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator/=(U const & s) + { + this->x /= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator/=(tvec1<U, P> const & v) + { + this->x /= static_cast<T>(v.x); + return *this; + } + + ////////////////////////////////////// + // Increment and decrement operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator++() + { + ++this->x; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator--() + { + --this->x; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> tvec1<T, P>::operator++(int) + { + tvec1<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> tvec1<T, P>::operator--(int) + { + tvec1<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return (v1.x == v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return (v1.x != v2.x); + } + + ////////////////////////////////////// + // Unary bit operators + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator%=(U const & s) + { + this->x %= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator%=(tvec1<U, P> const & v) + { + this->x %= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator&=(U const & s) + { + this->x &= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator&=(tvec1<U, P> const & v) + { + this->x &= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator|=(U const & s) + { + this->x |= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator|=(tvec1<U, P> const & v) + { + this->x |= U(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator^=(U const & s) + { + this->x ^= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator^=(tvec1<U, P> const & v) + { + this->x ^= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator<<=(U const & s) + { + this->x <<= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator<<=(tvec1<U, P> const & v) + { + this->x <<= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator>>=(U const & s) + { + this->x >>= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec1<T, P> & tvec1<T, P>::operator>>=(tvec1<U, P> const & v) + { + this->x >>= static_cast<T>(v.x); + return *this; + } + + ////////////////////////////////////// + // Binary arithmetic operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator+(tvec1<T, P> const & v, T const & s) + { + return tvec1<T, P>( + v.x + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator+(T const & s, tvec1<T, P> const & v) + { + return tvec1<T, P>( + s + v.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator+(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec1<T, P>( + v1.x + v2.x); + } + + //operator- + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator-(tvec1<T, P> const & v, T const & s) + { + return tvec1<T, P>( + v.x - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator-(T const & s, tvec1<T, P> const & v) + { + return tvec1<T, P>( + s - v.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator-(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec1<T, P>( + v1.x - v2.x); + } + + //operator* + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator*(tvec1<T, P> const & v, T const & s) + { + return tvec1<T, P>( + v.x * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator*(T const & s, tvec1<T, P> const & v) + { + return tvec1<T, P>( + s * v.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator*(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec1<T, P>( + v1.x * v2.x); + } + + //operator/ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator/(tvec1<T, P> const & v, T const & s) + { + return tvec1<T, P>( + v.x / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator/(T const & s, tvec1<T, P> const & v) + { + return tvec1<T, P>( + s / v.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator/(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec1<T, P>( + v1.x / v2.x); + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator-(tvec1<T, P> const & v) + { + return tvec1<T, P>( + -v.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator++(tvec1<T, P> const & v, int) + { + return tvec1<T, P>( + v.x + T(1)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator--(tvec1<T, P> const & v, int) + { + return tvec1<T, P>( + v.x - T(1)); + } + + ////////////////////////////////////// + // Binary bit operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator%(tvec1<T, P> const & v, T const & s) + { + return tvec1<T, P>( + v.x % s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator%(T const & s, tvec1<T, P> const & v) + { + return tvec1<T, P>( + s % v.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator%(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec1<T, P>( + v1.x % v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator&(tvec1<T, P> const & v, T const & s) + { + return tvec1<T, P>( + v.x & s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator&(T const & s, tvec1<T, P> const & v) + { + return tvec1<T, P>( + s & v.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator&(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec1<T, P>( + v1.x & v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator|(tvec1<T, P> const & v, T const & s) + { + return tvec1<T, P>( + v.x | s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator|(T const & s, tvec1<T, P> const & v) + { + return tvec1<T, P>( + s | v.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator|(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec1<T, P>( + v1.x | v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator^(tvec1<T, P> const & v, T const & s) + { + return tvec1<T, P>( + v.x ^ s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator^(T const & s, tvec1<T, P> const & v) + { + return tvec1<T, P>( + s ^ v.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator^(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec1<T, P>( + v1.x ^ v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator<<(tvec1<T, P> const & v, T const & s) + { + return tvec1<T, P>( + v.x << s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator<<(T const & s, tvec1<T, P> const & v) + { + return tvec1<T, P>( + s << v.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator<<(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec1<T, P>( + v1.x << v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator>>(tvec1<T, P> const & v, T const & s) + { + return tvec1<T, P>( + v.x >> s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator>>(T const & s, tvec1<T, P> const & v) + { + return tvec1<T, P>( + s >> v.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator>>(tvec1<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec1<T, P>( + v1.x >> v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec1<T, P> operator~(tvec1<T, P> const & v) + { + return tvec1<T, P>( + ~v.x); + } +}//namespace glm diff --git a/extensions/common/glm/detail/type_vec2.hpp b/extensions/common/glm/detail/type_vec2.hpp new file mode 100644 index 0000000000..b979491a3b --- /dev/null +++ b/extensions/common/glm/detail/type_vec2.hpp @@ -0,0 +1,403 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_vec2.hpp +/// @date 2008-08-18 / 2013-08-27 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +//#include "../fwd.hpp" +#include "type_vec.hpp" +#ifdef GLM_SWIZZLE +# if GLM_HAS_ANONYMOUS_UNION +# include "_swizzle.hpp" +# else +# include "_swizzle_func.hpp" +# endif +#endif //GLM_SWIZZLE +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tvec2 + { + ////////////////////////////////////// + // Implementation detail + + typedef tvec2<T, P> type; + typedef tvec2<bool, P> bool_type; + typedef T value_type; + + ////////////////////////////////////// + // Data + +# if GLM_HAS_ANONYMOUS_UNION + union + { + struct{ T x, y; }; + struct{ T r, g; }; + struct{ T s, t; }; + +# ifdef GLM_SWIZZLE + _GLM_SWIZZLE2_2_MEMBERS(T, P, tvec2, x, y) + _GLM_SWIZZLE2_2_MEMBERS(T, P, tvec2, r, g) + _GLM_SWIZZLE2_2_MEMBERS(T, P, tvec2, s, t) + _GLM_SWIZZLE2_3_MEMBERS(T, P, tvec3, x, y) + _GLM_SWIZZLE2_3_MEMBERS(T, P, tvec3, r, g) + _GLM_SWIZZLE2_3_MEMBERS(T, P, tvec3, s, t) + _GLM_SWIZZLE2_4_MEMBERS(T, P, tvec4, x, y) + _GLM_SWIZZLE2_4_MEMBERS(T, P, tvec4, r, g) + _GLM_SWIZZLE2_4_MEMBERS(T, P, tvec4, s, t) +# endif//GLM_SWIZZLE + }; +# else + union {T x, r, s;}; + union {T y, g, t;}; + +# ifdef GLM_SWIZZLE + GLM_SWIZZLE_GEN_VEC_FROM_VEC2(T, P, tvec2, tvec2, tvec3, tvec4) +# endif//GLM_SWIZZLE +# endif + + ////////////////////////////////////// + // Component accesses + +# ifdef GLM_FORCE_SIZE_FUNC + /// Return the count of components of the vector + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_type size() const; + + GLM_FUNC_DECL T & operator[](size_type i); + GLM_FUNC_DECL T const & operator[](size_type i) const; +# else + /// Return the count of components of the vector + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL T & operator[](length_type i); + GLM_FUNC_DECL T const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Implicit basic constructors + + GLM_FUNC_DECL tvec2(); + GLM_FUNC_DECL tvec2(tvec2<T, P> const & v); + template <precision Q> + GLM_FUNC_DECL tvec2(tvec2<T, Q> const & v); + + ////////////////////////////////////// + // Explicit basic constructors + + GLM_FUNC_DECL explicit tvec2(ctor); + GLM_FUNC_DECL explicit tvec2(T const & s); + GLM_FUNC_DECL tvec2(T const & s1, T const & s2); + + ////////////////////////////////////// + // Conversion constructors + + /// Explicit converions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B> + GLM_FUNC_DECL tvec2(A const & x, B const & y); + template <typename A, typename B> + GLM_FUNC_DECL tvec2(tvec1<A, P> const & v1, tvec1<B, P> const & v2); + + ////////////////////////////////////// + // Conversion vector constructors + + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL explicit tvec2(tvec3<U, Q> const & v); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL explicit tvec2(tvec4<U, Q> const & v); + +# ifdef GLM_FORCE_EXPLICIT_CTOR + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL explicit tvec2(tvec2<U, Q> const & v); +# else + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL tvec2(tvec2<U, Q> const & v); +# endif + + ////////////////////////////////////// + // Swizzle constructors + +# if GLM_HAS_ANONYMOUS_UNION && defined(GLM_SWIZZLE) + template <int E0, int E1> + GLM_FUNC_DECL tvec2(detail::_swizzle<2, T, P, tvec2<T, P>, E0, E1,-1,-2> const & that) + { + *this = that(); + } +# endif// GLM_HAS_ANONYMOUS_UNION && defined(GLM_SWIZZLE) + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tvec2<T, P>& operator=(tvec2<T, P> const & v); + + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator=(tvec2<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator+=(U s); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator+=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator+=(tvec2<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator-=(U s); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator-=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator-=(tvec2<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator*=(U s); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator*=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator*=(tvec2<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator/=(U s); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator/=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P>& operator/=(tvec2<U, P> const & v); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tvec2<T, P> & operator++(); + GLM_FUNC_DECL tvec2<T, P> & operator--(); + GLM_FUNC_DECL tvec2<T, P> operator++(int); + GLM_FUNC_DECL tvec2<T, P> operator--(int); + + ////////////////////////////////////// + // Unary bit operators + + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator%=(U s); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator%=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator%=(tvec2<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator&=(U s); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator&=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator&=(tvec2<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator|=(U s); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator|=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator|=(tvec2<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator^=(U s); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator^=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator^=(tvec2<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator<<=(U s); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator<<=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator<<=(tvec2<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator>>=(U s); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator>>=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec2<T, P> & operator>>=(tvec2<U, P> const & v); + }; + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator+(tvec2<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator+(tvec2<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator+(T const & s, tvec2<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator+(tvec1<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator+(tvec2<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator-(tvec2<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator-(tvec2<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator-(T const & s, tvec2<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator-(tvec1<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator-(tvec2<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator*(tvec2<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator*(tvec2<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator*(T const & s, tvec2<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator*(tvec1<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator*(tvec2<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator/(tvec2<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator/(tvec2<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator/(T const & s, tvec2<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator/(tvec1<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator/(tvec2<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator-(tvec2<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator%(tvec2<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator%(tvec2<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator%(T const & s, tvec2<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator%(tvec1<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator%(tvec2<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator&(tvec2<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator&(tvec2<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator&(T const & s, tvec2<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator&(tvec1<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator&(tvec2<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator|(tvec2<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator|(tvec2<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator|(T const & s, tvec2<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator|(tvec1<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator|(tvec2<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator^(tvec2<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator^(tvec2<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator^(T const & s, tvec2<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator^(tvec1<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator^(tvec2<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator<<(tvec2<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator<<(tvec2<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator<<(T const & s, tvec2<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator<<(tvec1<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator<<(tvec2<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator>>(tvec2<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator>>(tvec2<T, P> const & v1, tvec1<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator>>(T const & s, tvec2<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator>>(tvec1<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator>>(tvec2<T, P> const & v1, tvec2<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> operator~(tvec2<T, P> const & v); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec2.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/extensions/common/glm/detail/type_vec2.inl b/extensions/common/glm/detail/type_vec2.inl new file mode 100644 index 0000000000..fa778def3a --- /dev/null +++ b/extensions/common/glm/detail/type_vec2.inl @@ -0,0 +1,909 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/core/type_tvec2.inl +/// @date 2008-08-18 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ +#ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR size_t tvec2<T, P>::size() const + { + return 2; + } +#else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR length_t tvec2<T, P>::length() const + { + return 2; + } +#endif + + ////////////////////////////////////// + // Accesses + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T & tvec2<T, P>::operator[](length_t i) + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T const & tvec2<T, P>::operator[](length_t i) const + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } + + ////////////////////////////////////// + // Implicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P>::tvec2() +# ifndef GLM_FORCE_NO_CTOR_INIT + : x(0), y(0) +# endif + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P>::tvec2(tvec2<T, P> const & v) + : x(v.x), y(v.y) + {} + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tvec2<T, P>::tvec2(tvec2<T, Q> const & v) + : x(v.x), y(v.y) + {} + + ////////////////////////////////////// + // Explicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P>::tvec2(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P>::tvec2(T const & s) + : x(s), y(s) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P>::tvec2(T const & s1, T const & s2) + : x(s1), y(s2) + {} + + ////////////////////////////////////// + // Conversion scalar constructors + + template <typename T, precision P> + template <typename A, typename B> + GLM_FUNC_QUALIFIER tvec2<T, P>::tvec2(A const & a, B const & b) + : x(static_cast<T>(a)) + , y(static_cast<T>(b)) + {} + + template <typename T, precision P> + template <typename A, typename B> + GLM_FUNC_QUALIFIER tvec2<T, P>::tvec2(tvec1<A, P> const & a, tvec1<B, P> const & b) + : x(static_cast<T>(a.x)) + , y(static_cast<T>(b.x)) + {} + + ////////////////////////////////////// + // Conversion vector constructors + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tvec2<T, P>::tvec2(tvec2<U, Q> const & v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.y)) + {} + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tvec2<T, P>::tvec2(tvec3<U, Q> const & v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.y)) + {} + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tvec2<T, P>::tvec2(tvec4<U, Q> const & v) + : x(static_cast<T>(v.x)) + , y(static_cast<T>(v.y)) + {} + + ////////////////////////////////////// + // Unary arithmetic operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator=(tvec2<T, P> const & v) + { + this->x = v.x; + this->y = v.y; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator=(tvec2<U, P> const & v) + { + this->x = static_cast<T>(v.x); + this->y = static_cast<T>(v.y); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator+=(U s) + { + this->x += static_cast<T>(s); + this->y += static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator+=(tvec1<U, P> const & v) + { + this->x += static_cast<T>(v.x); + this->y += static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator+=(tvec2<U, P> const & v) + { + this->x += static_cast<T>(v.x); + this->y += static_cast<T>(v.y); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator-=(U s) + { + this->x -= static_cast<T>(s); + this->y -= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator-=(tvec1<U, P> const & v) + { + this->x -= static_cast<T>(v.x); + this->y -= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator-=(tvec2<U, P> const & v) + { + this->x -= static_cast<T>(v.x); + this->y -= static_cast<T>(v.y); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator*=(U s) + { + this->x *= static_cast<T>(s); + this->y *= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator*=(tvec1<U, P> const & v) + { + this->x *= static_cast<T>(v.x); + this->y *= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator*=(tvec2<U, P> const & v) + { + this->x *= static_cast<T>(v.x); + this->y *= static_cast<T>(v.y); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator/=(U s) + { + this->x /= static_cast<T>(s); + this->y /= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator/=(tvec1<U, P> const & v) + { + this->x /= static_cast<T>(v.x); + this->y /= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator/=(tvec2<U, P> const & v) + { + this->x /= static_cast<T>(v.x); + this->y /= static_cast<T>(v.y); + return *this; + } + + ////////////////////////////////////// + // Increment and decrement operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator++() + { + ++this->x; + ++this->y; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator--() + { + --this->x; + --this->y; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> tvec2<T, P>::operator++(int) + { + tvec2<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> tvec2<T, P>::operator--(int) + { + tvec2<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return (v1.x == v2.x) && (v1.y == v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return (v1.x != v2.x) || (v1.y != v2.y); + } + + ////////////////////////////////////// + // Unary bit operators + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator%=(U s) + { + this->x %= static_cast<T>(s); + this->y %= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator%=(tvec1<U, P> const & v) + { + this->x %= static_cast<T>(v.x); + this->y %= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator%=(tvec2<U, P> const & v) + { + this->x %= static_cast<T>(v.x); + this->y %= static_cast<T>(v.y); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator&=(U s) + { + this->x &= static_cast<T>(s); + this->y &= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator&=(tvec1<U, P> const & v) + { + this->x &= static_cast<T>(v.x); + this->y &= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator&=(tvec2<U, P> const & v) + { + this->x &= static_cast<T>(v.x); + this->y &= static_cast<T>(v.y); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator|=(U s) + { + this->x |= static_cast<T>(s); + this->y |= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator|=(tvec1<U, P> const & v) + { + this->x |= static_cast<T>(v.x); + this->y |= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator|=(tvec2<U, P> const & v) + { + this->x |= static_cast<T>(v.x); + this->y |= static_cast<T>(v.y); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator^=(U s) + { + this->x ^= static_cast<T>(s); + this->y ^= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator^=(tvec1<U, P> const & v) + { + this->x ^= static_cast<T>(v.x); + this->y ^= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator^=(tvec2<U, P> const & v) + { + this->x ^= static_cast<T>(v.x); + this->y ^= static_cast<T>(v.y); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator<<=(U s) + { + this->x <<= static_cast<T>(s); + this->y <<= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator<<=(tvec1<U, P> const & v) + { + this->x <<= static_cast<T>(v.x); + this->y <<= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator<<=(tvec2<U, P> const & v) + { + this->x <<= static_cast<T>(v.x); + this->y <<= static_cast<T>(v.y); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator>>=(U s) + { + this->x >>= static_cast<T>(s); + this->y >>= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator>>=(tvec1<U, P> const & v) + { + this->x >>= static_cast<T>(v.x); + this->y >>= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec2<T, P> & tvec2<T, P>::operator>>=(tvec2<U, P> const & v) + { + this->x >>= static_cast<T>(v.x); + this->y >>= static_cast<T>(v.y); + return *this; + } + + ////////////////////////////////////// + // Binary arithmetic operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator+(tvec2<T, P> const & v, T const & s) + { + return tvec2<T, P>( + v.x + s, + v.y + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator+(tvec2<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec2<T, P>( + v1.x + v2.x, + v1.y + v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator+(T const & s, tvec2<T, P> const & v) + { + return tvec2<T, P>( + s + v.x, + s + v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator+(tvec1<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x + v2.x, + v1.x + v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator+(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x + v2.x, + v1.y + v2.y); + } + + //operator- + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator-(tvec2<T, P> const & v, T const & s) + { + return tvec2<T, P>( + v.x - s, + v.y - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator-(tvec2<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec2<T, P>( + v1.x - v2.x, + v1.y - v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator-(T const & s, tvec2<T, P> const & v) + { + return tvec2<T, P>( + s - v.x, + s - v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator-(tvec1<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x - v2.x, + v1.x - v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator-(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x - v2.x, + v1.y - v2.y); + } + + //operator* + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator*(tvec2<T, P> const & v1, T const & v2) + { + return tvec2<T, P>( + v1.x * v2, + v1.y * v2); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator*(tvec2<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec2<T, P>( + v1.x * v2.x, + v1.y * v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator*(T const & s, tvec2<T, P> const & v) + { + return tvec2<T, P>( + s * v.x, + s * v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator*(tvec1<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x * v2.x, + v1.x * v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator*(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x * v2.x, + v1.y * v2.y); + } + + //operator/ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator/(tvec2<T, P> const & v, T const & s) + { + return tvec2<T, P>( + v.x / s, + v.y / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator/(tvec2<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec2<T, P>( + v1.x / v2.x, + v1.y / v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator/(T const & s, tvec2<T, P> const & v) + { + return tvec2<T, P>( + s / v.x, + s / v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator/(tvec1<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x / v2.x, + v1.x / v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator/(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x / v2.x, + v1.y / v2.y); + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator-(tvec2<T, P> const & v) + { + return tvec2<T, P>( + -v.x, + -v.y); + } + + ////////////////////////////////////// + // Binary bit operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator%(tvec2<T, P> const & v, T const & s) + { + return tvec2<T, P>( + v.x % s, + v.y % s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator%(tvec2<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec2<T, P>( + v1.x % v2.x, + v1.y % v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator%(T const & s, tvec2<T, P> const & v) + { + return tvec2<T, P>( + s % v.x, + s % v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator%(tvec1<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x % v2.x, + v1.x % v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator%(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x % v2.x, + v1.y % v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator&(tvec2<T, P> const & v, T const & s) + { + return tvec2<T, P>( + v.x & s, + v.y & s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator&(tvec2<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec2<T, P>( + v1.x & v2.x, + v1.y & v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator&(T const & s, tvec2<T, P> const & v) + { + return tvec2<T, P>( + s & v.x, + s & v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator&(tvec1<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x & v2.x, + v1.x & v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator&(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x & v2.x, + v1.y & v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator|(tvec2<T, P> const & v, T const & s) + { + return tvec2<T, P>( + v.x | s, + v.y | s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator|(tvec2<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec2<T, P>( + v1.x | v2.x, + v1.y | v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator|(T const & s, tvec2<T, P> const & v) + { + return tvec2<T, P>( + s | v.x, + s | v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator|(tvec1<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x | v2.x, + v1.x | v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator|(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x | v2.x, + v1.y | v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator^(tvec2<T, P> const & v, T const & s) + { + return tvec2<T, P>( + v.x ^ s, + v.y ^ s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator^(tvec2<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec2<T, P>( + v1.x ^ v2.x, + v1.y ^ v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator^(T const & s, tvec2<T, P> const & v) + { + return tvec2<T, P>( + s ^ v.x, + s ^ v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator^(tvec1<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x ^ v2.x, + v1.x ^ v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator^(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x ^ v2.x, + v1.y ^ v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator<<(tvec2<T, P> const & v, T const & s) + { + return tvec2<T, P>( + v.x << s, + v.y << s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator<<(tvec2<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec2<T, P>( + v1.x << v2.x, + v1.y << v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator<<(T const & s, tvec2<T, P> const & v) + { + return tvec2<T, P>( + s << v.x, + s << v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator<<(tvec1<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x << v2.x, + v1.x << v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator<<(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x << v2.x, + v1.y << v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator>>(tvec2<T, P> const & v, T const & s) + { + return tvec2<T, P>( + v.x >> s, + v.y >> s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator>>(tvec2<T, P> const & v1, tvec1<T, P> const & v2) + { + return tvec2<T, P>( + v1.x >> v2.x, + v1.y >> v2.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator>>(T const & s, tvec2<T, P> const & v) + { + return tvec2<T, P>( + s >> v.x, + s >> v.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator>>(tvec1<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x >> v2.x, + v1.x >> v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator>>(tvec2<T, P> const & v1, tvec2<T, P> const & v2) + { + return tvec2<T, P>( + v1.x >> v2.x, + v1.y >> v2.y); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> operator~(tvec2<T, P> const & v) + { + return tvec2<T, P>( + ~v.x, + ~v.y); + } +}//namespace glm diff --git a/extensions/common/glm/detail/type_vec3.hpp b/extensions/common/glm/detail/type_vec3.hpp new file mode 100644 index 0000000000..01185ac905 --- /dev/null +++ b/extensions/common/glm/detail/type_vec3.hpp @@ -0,0 +1,425 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_vec3.hpp +/// @date 2008-08-22 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +//#include "../fwd.hpp" +#include "type_vec.hpp" +#ifdef GLM_SWIZZLE +# if GLM_HAS_ANONYMOUS_UNION +# include "_swizzle.hpp" +# else +# include "_swizzle_func.hpp" +# endif +#endif //GLM_SWIZZLE +#include <cstddef> + +namespace glm +{ + template <typename T, precision P = defaultp> + struct tvec3 + { + ////////////////////////////////////// + // Implementation detail + + typedef tvec3<T, P> type; + typedef tvec3<bool, P> bool_type; + typedef T value_type; + + ////////////////////////////////////// + // Data + +# if GLM_HAS_ANONYMOUS_UNION + union + { + struct{ T x, y, z; }; + struct{ T r, g, b; }; + struct{ T s, t, p; }; + +# ifdef GLM_SWIZZLE + _GLM_SWIZZLE3_2_MEMBERS(T, P, tvec2, x, y, z) + _GLM_SWIZZLE3_2_MEMBERS(T, P, tvec2, r, g, b) + _GLM_SWIZZLE3_2_MEMBERS(T, P, tvec2, s, t, p) + _GLM_SWIZZLE3_3_MEMBERS(T, P, tvec3, x, y, z) + _GLM_SWIZZLE3_3_MEMBERS(T, P, tvec3, r, g, b) + _GLM_SWIZZLE3_3_MEMBERS(T, P, tvec3, s, t, p) + _GLM_SWIZZLE3_4_MEMBERS(T, P, tvec4, x, y, z) + _GLM_SWIZZLE3_4_MEMBERS(T, P, tvec4, r, g, b) + _GLM_SWIZZLE3_4_MEMBERS(T, P, tvec4, s, t, p) +# endif//GLM_SWIZZLE + }; +# else + union { T x, r, s; }; + union { T y, g, t; }; + union { T z, b, p; }; + +# ifdef GLM_SWIZZLE + GLM_SWIZZLE_GEN_VEC_FROM_VEC3(T, P, tvec3, tvec2, tvec3, tvec4) +# endif//GLM_SWIZZLE +# endif//GLM_LANG + + ////////////////////////////////////// + // Component accesses + +# ifdef GLM_FORCE_SIZE_FUNC + /// Return the count of components of the vector + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_type size() const; + + GLM_FUNC_DECL T & operator[](size_type i); + GLM_FUNC_DECL T const & operator[](size_type i) const; +# else + /// Return the count of components of the vector + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL T & operator[](length_type i); + GLM_FUNC_DECL T const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Implicit basic constructors + + GLM_FUNC_DECL tvec3(); + GLM_FUNC_DECL tvec3(tvec3<T, P> const & v); + template <precision Q> + GLM_FUNC_DECL tvec3(tvec3<T, Q> const & v); + + ////////////////////////////////////// + // Explicit basic constructors + + GLM_FUNC_DECL explicit tvec3(ctor); + GLM_FUNC_DECL explicit tvec3(T const & s); + GLM_FUNC_DECL tvec3(T const & a, T const & b, T const & c); + + ////////////////////////////////////// + // Conversion scalar constructors + + /// Explicit converions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, typename C> + GLM_FUNC_DECL tvec3(A const & a, B const & b, C const & c); + template <typename A, typename B, typename C> + GLM_FUNC_DECL tvec3(tvec1<A, P> const & a, tvec1<B, P> const & b, tvec1<C, P> const & c); + + ////////////////////////////////////// + // Conversion vector constructors + + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, precision Q> + GLM_FUNC_DECL explicit tvec3(tvec2<A, Q> const & a, B const & b); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, precision Q> + GLM_FUNC_DECL explicit tvec3(tvec2<A, Q> const & a, tvec1<B, Q> const & b); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, precision Q> + GLM_FUNC_DECL explicit tvec3(A const & a, tvec2<B, Q> const & b); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, precision Q> + GLM_FUNC_DECL explicit tvec3(tvec1<A, Q> const & a, tvec2<B, Q> const & b); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL explicit tvec3(tvec4<U, Q> const & v); + +# ifdef GLM_FORCE_EXPLICIT_CTOR + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL explicit tvec3(tvec3<U, Q> const & v); +# else + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL tvec3(tvec3<U, Q> const & v); +# endif + + ////////////////////////////////////// + // Swizzle constructors + +# if GLM_HAS_ANONYMOUS_UNION && defined(GLM_SWIZZLE) + template <int E0, int E1, int E2> + GLM_FUNC_DECL tvec3(detail::_swizzle<3, T, P, tvec3<T, P>, E0, E1, E2, -1> const & that) + { + *this = that(); + } + + template <int E0, int E1> + GLM_FUNC_DECL tvec3(detail::_swizzle<2, T, P, tvec2<T, P>, E0, E1, -1, -2> const & v, T const & s) + { + *this = tvec3<T, P>(v(), s); + } + + template <int E0, int E1> + GLM_FUNC_DECL tvec3(T const & s, detail::_swizzle<2, T, P, tvec2<T, P>, E0, E1, -1, -2> const & v) + { + *this = tvec3<T, P>(s, v()); + } +# endif// GLM_HAS_ANONYMOUS_UNION && defined(GLM_SWIZZLE) + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tvec3<T, P> & operator=(tvec3<T, P> const & v); + + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator=(tvec3<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator+=(U s); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator+=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator+=(tvec3<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator-=(U s); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator-=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator-=(tvec3<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator*=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator*=(tvec3<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator/=(U s); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator/=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator/=(tvec3<U, P> const & v); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tvec3<T, P> & operator++(); + GLM_FUNC_DECL tvec3<T, P> & operator--(); + GLM_FUNC_DECL tvec3<T, P> operator++(int); + GLM_FUNC_DECL tvec3<T, P> operator--(int); + + ////////////////////////////////////// + // Unary bit operators + + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator%=(U s); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator%=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator%=(tvec3<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator&=(U s); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator&=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator&=(tvec3<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator|=(U s); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator|=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator|=(tvec3<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator^=(U s); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator^=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator^=(tvec3<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator<<=(U s); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator<<=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator<<=(tvec3<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator>>=(U s); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator>>=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec3<T, P> & operator>>=(tvec3<U, P> const & v); + }; + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator+(tvec3<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator+(tvec3<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator+(T const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator+(tvec1<T, P> const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator+(tvec3<T, P> const & v1, tvec3<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator-(tvec3<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator-(tvec3<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator-(T const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator-(tvec1<T, P> const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator-(tvec3<T, P> const & v1, tvec3<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator*(tvec3<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator*(tvec3<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator*(T const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator*(tvec1<T, P> const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator*(tvec3<T, P> const & v1, tvec3<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator/(tvec3<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator/(tvec3<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator/(T const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator/(tvec1<T, P> const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator/(tvec3<T, P> const & v1, tvec3<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator-(tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator%(tvec3<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator%(tvec3<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator%(T const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator%(tvec1<T, P> const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator%(tvec3<T, P> const & v1, tvec3<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator&(tvec3<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator&(tvec3<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator&(T const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator&(tvec1<T, P> const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator&(tvec3<T, P> const & v1, tvec3<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator|(tvec3<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator|(tvec3<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator|(T const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator|(tvec1<T, P> const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator|(tvec3<T, P> const & v1, tvec3<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator^(tvec3<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator^(tvec3<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator^(T const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator^(tvec1<T, P> const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator^(tvec3<T, P> const & v1, tvec3<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator<<(tvec3<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator<<(tvec3<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator<<(T const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator<<(tvec1<T, P> const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator<<(tvec3<T, P> const & v1, tvec3<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator>>(tvec3<T, P> const & v, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator>>(tvec3<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator>>(T const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator>>(tvec1<T, P> const & s, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator>>(tvec3<T, P> const & v1, tvec3<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator~(tvec3<T, P> const & v); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec3.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/extensions/common/glm/detail/type_vec3.inl b/extensions/common/glm/detail/type_vec3.inl new file mode 100644 index 0000000000..97f64547d2 --- /dev/null +++ b/extensions/common/glm/detail/type_vec3.inl @@ -0,0 +1,1042 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_tvec3.inl +/// @date 2008-08-22 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + ////////////////////////////////////// + // Implicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3() +# ifndef GLM_FORCE_NO_CTOR_INIT + : x(0), y(0), z(0) +# endif + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(tvec3<T, P> const & v) + : x(v.x), y(v.y), z(v.z) + {} + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(tvec3<T, Q> const & v) + : x(v.x), y(v.y), z(v.z) + {} + + ////////////////////////////////////// + // Explicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(T const & s) + : x(s), y(s), z(s) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(T const & a, T const & b, T const & c) + : x(a), y(b), z(c) + {} + + ////////////////////////////////////// + // Conversion scalar constructors + + template <typename T, precision P> + template <typename A, typename B, typename C> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(A const & a, B const & b, C const & c) : + x(static_cast<T>(a)), + y(static_cast<T>(b)), + z(static_cast<T>(c)) + {} + + template <typename T, precision P> + template <typename A, typename B, typename C> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(tvec1<A, P> const & a, tvec1<B, P> const & b, tvec1<C, P> const & c) : + x(static_cast<T>(a)), + y(static_cast<T>(b)), + z(static_cast<T>(c)) + {} + + ////////////////////////////////////// + // Conversion vector constructors + + template <typename T, precision P> + template <typename A, typename B, precision Q> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(tvec2<A, Q> const & a, B const & b) : + x(static_cast<T>(a.x)), + y(static_cast<T>(a.y)), + z(static_cast<T>(b)) + {} + + template <typename T, precision P> + template <typename A, typename B, precision Q> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(tvec2<A, Q> const & a, tvec1<B, Q> const & b) : + x(static_cast<T>(a.x)), + y(static_cast<T>(a.y)), + z(static_cast<T>(b.x)) + {} + + template <typename T, precision P> + template <typename A, typename B, precision Q> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(A const & a, tvec2<B, Q> const & b) : + x(static_cast<T>(a)), + y(static_cast<T>(b.x)), + z(static_cast<T>(b.y)) + {} + + template <typename T, precision P> + template <typename A, typename B, precision Q> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(tvec1<A, Q> const & a, tvec2<B, Q> const & b) : + x(static_cast<T>(a.x)), + y(static_cast<T>(b.x)), + z(static_cast<T>(b.y)) + {} + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(tvec3<U, Q> const & v) : + x(static_cast<T>(v.x)), + y(static_cast<T>(v.y)), + z(static_cast<T>(v.z)) + {} + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tvec3<T, P>::tvec3(tvec4<U, Q> const & v) : + x(static_cast<T>(v.x)), + y(static_cast<T>(v.y)), + z(static_cast<T>(v.z)) + {} + + ////////////////////////////////////// + // Component accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tvec3<T, P>::size_type tvec3<T, P>::size() const + { + return 3; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T & tvec3<T, P>::operator[](typename tvec3<T, P>::size_type i) + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T const & tvec3<T, P>::operator[](typename tvec3<T, P>::size_type i) const + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tvec3<T, P>::length_type tvec3<T, P>::length() const + { + return 3; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T & tvec3<T, P>::operator[](typename tvec3<T, P>::length_type i) + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T const & tvec3<T, P>::operator[](typename tvec3<T, P>::length_type i) const + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P>& tvec3<T, P>::operator=(tvec3<T, P> const & v) + { + this->x = v.x; + this->y = v.y; + this->z = v.z; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P>& tvec3<T, P>::operator=(tvec3<U, P> const & v) + { + this->x = static_cast<T>(v.x); + this->y = static_cast<T>(v.y); + this->z = static_cast<T>(v.z); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator+=(U s) + { + this->x += static_cast<T>(s); + this->y += static_cast<T>(s); + this->z += static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator+=(tvec1<U, P> const & v) + { + this->x += static_cast<T>(v.x); + this->y += static_cast<T>(v.x); + this->z += static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator+=(tvec3<U, P> const & v) + { + this->x += static_cast<T>(v.x); + this->y += static_cast<T>(v.y); + this->z += static_cast<T>(v.z); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator-=(U s) + { + this->x -= static_cast<T>(s); + this->y -= static_cast<T>(s); + this->z -= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator-=(tvec1<U, P> const & v) + { + this->x -= static_cast<T>(v.x); + this->y -= static_cast<T>(v.x); + this->z -= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator-=(tvec3<U, P> const & v) + { + this->x -= static_cast<T>(v.x); + this->y -= static_cast<T>(v.y); + this->z -= static_cast<T>(v.z); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator*=(U s) + { + this->x *= static_cast<T>(s); + this->y *= static_cast<T>(s); + this->z *= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator*=(tvec1<U, P> const & v) + { + this->x *= static_cast<T>(v.x); + this->y *= static_cast<T>(v.x); + this->z *= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator*=(tvec3<U, P> const & v) + { + this->x *= static_cast<T>(v.x); + this->y *= static_cast<T>(v.y); + this->z *= static_cast<T>(v.z); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator/=(U s) + { + this->x /= static_cast<T>(s); + this->y /= static_cast<T>(s); + this->z /= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator/=(tvec1<U, P> const & v) + { + this->x /= static_cast<T>(v.x); + this->y /= static_cast<T>(v.x); + this->z /= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator/=(tvec3<U, P> const & v) + { + this->x /= static_cast<T>(v.x); + this->y /= static_cast<T>(v.y); + this->z /= static_cast<T>(v.z); + return *this; + } + + ////////////////////////////////////// + // Increment and decrement operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator++() + { + ++this->x; + ++this->y; + ++this->z; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator--() + { + --this->x; + --this->y; + --this->z; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> tvec3<T, P>::operator++(int) + { + tvec3<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> tvec3<T, P>::operator--(int) + { + tvec3<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////// + // Unary bit operators + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator%=(U s) + { + this->x %= s; + this->y %= s; + this->z %= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator%=(tvec1<U, P> const & v) + { + this->x %= v.x; + this->y %= v.x; + this->z %= v.x; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator%=(tvec3<U, P> const & v) + { + this->x %= v.x; + this->y %= v.y; + this->z %= v.z; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator&=(U s) + { + this->x &= s; + this->y &= s; + this->z &= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator&=(tvec1<U, P> const & v) + { + this->x &= v.x; + this->y &= v.x; + this->z &= v.x; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator&=(tvec3<U, P> const & v) + { + this->x &= v.x; + this->y &= v.y; + this->z &= v.z; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator|=(U s) + { + this->x |= s; + this->y |= s; + this->z |= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator|=(tvec1<U, P> const & v) + { + this->x |= v.x; + this->y |= v.x; + this->z |= v.x; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator|=(tvec3<U, P> const & v) + { + this->x |= v.x; + this->y |= v.y; + this->z |= v.z; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator^=(U s) + { + this->x ^= s; + this->y ^= s; + this->z ^= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator^=(tvec1<U, P> const & v) + { + this->x ^= v.x; + this->y ^= v.x; + this->z ^= v.x; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator^=(tvec3<U, P> const & v) + { + this->x ^= v.x; + this->y ^= v.y; + this->z ^= v.z; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator<<=(U s) + { + this->x <<= s; + this->y <<= s; + this->z <<= s; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator<<=(tvec1<U, P> const & v) + { + this->x <<= static_cast<T>(v.x); + this->y <<= static_cast<T>(v.x); + this->z <<= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator<<=(tvec3<U, P> const & v) + { + this->x <<= static_cast<T>(v.x); + this->y <<= static_cast<T>(v.y); + this->z <<= static_cast<T>(v.z); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator>>=(U s) + { + this->x >>= static_cast<T>(s); + this->y >>= static_cast<T>(s); + this->z >>= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator>>=(tvec1<U, P> const & v) + { + this->x >>= static_cast<T>(v.x); + this->y >>= static_cast<T>(v.x); + this->z >>= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec3<T, P> & tvec3<T, P>::operator>>=(tvec3<U, P> const & v) + { + this->x >>= static_cast<T>(v.x); + this->y >>= static_cast<T>(v.y); + this->z >>= static_cast<T>(v.z); + return *this; + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return (v1.x != v2.x) || (v1.y != v2.y) || (v1.z != v2.z); + } + + ////////////////////////////////////// + // Binary arithmetic operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator+(tvec3<T, P> const & v, T const & s) + { + return tvec3<T, P>( + v.x + s, + v.y + s, + v.z + s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator+(tvec3<T, P> const & v, tvec1<T, P> const & s) + { + return tvec3<T, P>( + v.x + s.x, + v.y + s.x, + v.z + s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator+(T const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s + v.x, + s + v.y, + s + v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator+(tvec1<T, P> const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s.x + v.x, + s.x + v.y, + s.x + v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator+(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return tvec3<T, P>( + v1.x + v2.x, + v1.y + v2.y, + v1.z + v2.z); + } + + //operator- + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator-(tvec3<T, P> const & v, T const & s) + { + return tvec3<T, P>( + v.x - s, + v.y - s, + v.z - s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator-(tvec3<T, P> const & v, tvec1<T, P> const & s) + { + return tvec3<T, P>( + v.x - s.x, + v.y - s.x, + v.z - s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator-(T const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s - v.x, + s - v.y, + s - v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator-(tvec1<T, P> const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s.x - v.x, + s.x - v.y, + s.x - v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator-(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return tvec3<T, P>( + v1.x - v2.x, + v1.y - v2.y, + v1.z - v2.z); + } + + //operator* + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator*(tvec3<T, P> const & v, T const & s) + { + return tvec3<T, P>( + v.x * s, + v.y * s, + v.z * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator*(tvec3<T, P> const & v, tvec1<T, P> const & s) + { + return tvec3<T, P>( + v.x * s.x, + v.y * s.x, + v.z * s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator*(T const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s * v.x, + s * v.y, + s * v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator*(tvec1<T, P> const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s.x * v.x, + s.x * v.y, + s.x * v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator*(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return tvec3<T, P>( + v1.x * v2.x, + v1.y * v2.y, + v1.z * v2.z); + } + + //operator/ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator/(tvec3<T, P> const & v, T const & s) + { + return tvec3<T, P>( + v.x / s, + v.y / s, + v.z / s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator/(tvec3<T, P> const & v, tvec1<T, P> const & s) + { + return tvec3<T, P>( + v.x / s.x, + v.y / s.x, + v.z / s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator/(T const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s / v.x, + s / v.y, + s / v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator/(tvec1<T, P> const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s.x / v.x, + s.x / v.y, + s.x / v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator/(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return tvec3<T, P>( + v1.x / v2.x, + v1.y / v2.y, + v1.z / v2.z); + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator-(tvec3<T, P> const & v) + { + return tvec3<T, P>( + -v.x, + -v.y, + -v.z); + } + + ////////////////////////////////////// + // Binary bit operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator%(tvec3<T, P> const & v, T const & s) + { + return tvec3<T, P>( + v.x % s, + v.y % s, + v.z % s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator%(tvec3<T, P> const & v, tvec1<T, P> const & s) + { + return tvec3<T, P>( + v.x % s.x, + v.y % s.x, + v.z % s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator%(T const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s % v.x, + s % v.y, + s % v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator%(tvec1<T, P> const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s.x % v.x, + s.x % v.y, + s.x % v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator%(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return tvec3<T, P>( + v1.x % v2.x, + v1.y % v2.y, + v1.z % v2.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator&(tvec3<T, P> const & v, T const & s) + { + return tvec3<T, P>( + v.x & s, + v.y & s, + v.z & s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator&(tvec3<T, P> const & v, tvec1<T, P> const & s) + { + return tvec3<T, P>( + v.x & s.x, + v.y & s.x, + v.z & s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator&(T const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s & v.x, + s & v.y, + s & v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator&(tvec1<T, P> const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s.x & v.x, + s.x & v.y, + s.x & v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator&(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return tvec3<T, P>( + v1.x & v2.x, + v1.y & v2.y, + v1.z & v2.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator|(tvec3<T, P> const & v, T const & s) + { + return tvec3<T, P>( + v.x | s, + v.y | s, + v.z | s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator|(tvec3<T, P> const & v, tvec1<T, P> const & s) + { + return tvec3<T, P>( + v.x | s.x, + v.y | s.x, + v.z | s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator|(T const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s | v.x, + s | v.y, + s | v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator|(tvec1<T, P> const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s.x | v.x, + s.x | v.y, + s.x | v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator|(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return tvec3<T, P>( + v1.x | v2.x, + v1.y | v2.y, + v1.z | v2.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator^(tvec3<T, P> const & v, T const & s) + { + return tvec3<T, P>( + v.x ^ s, + v.y ^ s, + v.z ^ s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator^(tvec3<T, P> const & v, tvec1<T, P> const & s) + { + return tvec3<T, P>( + v.x ^ s.x, + v.y ^ s.x, + v.z ^ s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator^(T const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s ^ v.x, + s ^ v.y, + s ^ v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator^(tvec1<T, P> const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s.x ^ v.x, + s.x ^ v.y, + s.x ^ v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator^(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return tvec3<T, P>( + v1.x ^ v2.x, + v1.y ^ v2.y, + v1.z ^ v2.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator<<(tvec3<T, P> const & v, T const & s) + { + return tvec3<T, P>( + v.x << s, + v.y << s, + v.z << s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator<<(tvec3<T, P> const & v, tvec1<T, P> const & s) + { + return tvec3<T, P>( + v.x << s.x, + v.y << s.x, + v.z << s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator<<(T const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s << v.x, + s << v.y, + s << v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator<<(tvec1<T, P> const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s.x << v.x, + s.x << v.y, + s.x << v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator<<(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return tvec3<T, P>( + v1.x << v2.x, + v1.y << v2.y, + v1.z << v2.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator>>(tvec3<T, P> const & v, T const & s) + { + return tvec3<T, P>( + v.x >> s, + v.y >> s, + v.z >> s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator>>(tvec3<T, P> const & v, tvec1<T, P> const & s) + { + return tvec3<T, P>( + v.x >> s.x, + v.y >> s.x, + v.z >> s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator>>(T const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s >> v.x, + s >> v.y, + s >> v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator>>(tvec1<T, P> const & s, tvec3<T, P> const & v) + { + return tvec3<T, P>( + s.x >> v.x, + s.x >> v.y, + s.x >> v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator>>(tvec3<T, P> const & v1, tvec3<T, P> const & v2) + { + return tvec3<T, P>( + v1.x >> v2.x, + v1.y >> v2.y, + v1.z >> v2.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator~(tvec3<T, P> const & v) + { + return tvec3<T, P>( + ~v.x, + ~v.y, + ~v.z); + } +}//namespace glm diff --git a/extensions/common/glm/detail/type_vec4.hpp b/extensions/common/glm/detail/type_vec4.hpp new file mode 100644 index 0000000000..555827e24f --- /dev/null +++ b/extensions/common/glm/detail/type_vec4.hpp @@ -0,0 +1,531 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_vec4.hpp +/// @date 2008-08-22 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +//#include "../fwd.hpp" +#include "setup.hpp" +#include "type_vec.hpp" +#ifdef GLM_SWIZZLE +# if GLM_HAS_ANONYMOUS_UNION +# include "_swizzle.hpp" +# else +# include "_swizzle_func.hpp" +# endif +#endif //GLM_SWIZZLE +#include <cstddef> + +namespace glm{ +namespace detail +{ + template <typename T> + struct simd + { + typedef T type[4]; + }; + +# define GLM_NOT_BUGGY_VC32BITS !(GLM_MODEL == GLM_MODEL_32 && GLM_COMPILER & GLM_COMPILER_VC && GLM_COMPILER < GLM_COMPILER_VC2013) + +# if GLM_ARCH & GLM_ARCH_SSE2 && GLM_NOT_BUGGY_VC32BITS + template <> + struct simd<float> + { + typedef __m128 type; + }; + + template <> + struct simd<int> + { + typedef __m128i type; + }; + + template <> + struct simd<unsigned int> + { + typedef __m128i type; + }; +# endif + +# if GLM_ARCH & GLM_ARCH_AVX && GLM_NOT_BUGGY_VC32BITS + template <> + struct simd<double> + { + typedef __m256d type; + }; +# endif + +# if GLM_ARCH & GLM_ARCH_AVX2 && GLM_NOT_BUGGY_VC32BITS + template <> + struct simd<int64> + { + typedef __m256i type; + }; + + template <> + struct simd<uint64> + { + typedef __m256i type; + }; +# endif + +}//namespace detail + + template <typename T, precision P = defaultp> + struct tvec4 + { + ////////////////////////////////////// + // Implementation detail + + typedef tvec4<T, P> type; + typedef tvec4<bool, P> bool_type; + typedef T value_type; + + ////////////////////////////////////// + // Data + +# if GLM_HAS_ANONYMOUS_UNION + union + { + struct { T x, y, z, w;}; + struct { T r, g, b, a; }; + struct { T s, t, p, q; }; + + typename detail::simd<T>::type data; + +# ifdef GLM_SWIZZLE + _GLM_SWIZZLE4_2_MEMBERS(T, P, tvec2, x, y, z, w) + _GLM_SWIZZLE4_2_MEMBERS(T, P, tvec2, r, g, b, a) + _GLM_SWIZZLE4_2_MEMBERS(T, P, tvec2, s, t, p, q) + _GLM_SWIZZLE4_3_MEMBERS(T, P, tvec3, x, y, z, w) + _GLM_SWIZZLE4_3_MEMBERS(T, P, tvec3, r, g, b, a) + _GLM_SWIZZLE4_3_MEMBERS(T, P, tvec3, s, t, p, q) + _GLM_SWIZZLE4_4_MEMBERS(T, P, tvec4, x, y, z, w) + _GLM_SWIZZLE4_4_MEMBERS(T, P, tvec4, r, g, b, a) + _GLM_SWIZZLE4_4_MEMBERS(T, P, tvec4, s, t, p, q) +# endif//GLM_SWIZZLE + }; +# else + union { T x, r, s; }; + union { T y, g, t; }; + union { T z, b, p; }; + union { T w, a, q; }; + +# ifdef GLM_SWIZZLE + GLM_SWIZZLE_GEN_VEC_FROM_VEC4(T, P, tvec4, tvec2, tvec3, tvec4) +# endif//GLM_SWIZZLE +# endif//GLM_LANG + + ////////////////////////////////////// + // Component accesses + +# ifdef GLM_FORCE_SIZE_FUNC + /// Return the count of components of the vector + typedef size_t size_type; + GLM_FUNC_DECL GLM_CONSTEXPR size_type size() const; + + GLM_FUNC_DECL T & operator[](size_type i); + GLM_FUNC_DECL T const & operator[](size_type i) const; +# else + /// Return the count of components of the vector + typedef length_t length_type; + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL T & operator[](length_type i); + GLM_FUNC_DECL T const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Implicit basic constructors + + GLM_FUNC_DECL tvec4(); + GLM_FUNC_DECL tvec4(tvec4<T, P> const & v); + template <precision Q> + GLM_FUNC_DECL tvec4(tvec4<T, Q> const & v); + + ////////////////////////////////////// + // Explicit basic constructors + + GLM_FUNC_DECL explicit tvec4(ctor); + GLM_FUNC_DECL explicit tvec4(T s); + GLM_FUNC_DECL tvec4(T a, T b, T c, T d); + GLM_FUNC_DECL ~tvec4(){} + + ////////////////////////////////////// + // Conversion scalar constructors + + /// Explicit converions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, typename C, typename D> + GLM_FUNC_DECL tvec4(A a, B b, C c, D d); + template <typename A, typename B, typename C, typename D> + GLM_FUNC_DECL tvec4(tvec1<A, P> const & a, tvec1<B, P> const & b, tvec1<C, P> const & c, tvec1<D, P> const & d); + + ////////////////////////////////////// + // Conversion vector constructors + + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_DECL explicit tvec4(tvec2<A, Q> const & a, B b, C c); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_DECL explicit tvec4(tvec2<A, Q> const & a, tvec1<B, Q> const & b, tvec1<C, Q> const & c); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_DECL explicit tvec4(A a, tvec2<B, Q> const & b, C c); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_DECL explicit tvec4(tvec1<A, Q> const & a, tvec2<B, Q> const & b, tvec1<C, Q> const & c); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_DECL explicit tvec4(A a, B b, tvec2<C, Q> const & c); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_DECL explicit tvec4(tvec1<A, Q> const & a, tvec1<B, Q> const & b, tvec2<C, Q> const & c); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, precision Q> + GLM_FUNC_DECL explicit tvec4(tvec3<A, Q> const & a, B b); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, precision Q> + GLM_FUNC_DECL explicit tvec4(tvec3<A, Q> const & a, tvec1<B, Q> const & b); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, precision Q> + GLM_FUNC_DECL explicit tvec4(A a, tvec3<B, Q> const & b); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, precision Q> + GLM_FUNC_DECL explicit tvec4(tvec1<A, Q> const & a, tvec3<B, Q> const & b); + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename A, typename B, precision Q> + GLM_FUNC_DECL explicit tvec4(tvec2<A, Q> const & a, tvec2<B, Q> const & b); + +# ifdef GLM_FORCE_EXPLICIT_CTOR + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL explicit tvec4(tvec4<U, Q> const & v); +# else + //! Explicit conversions (From section 5.4.1 Conversion and scalar constructors of GLSL 1.30.08 specification) + template <typename U, precision Q> + GLM_FUNC_DECL tvec4(tvec4<U, Q> const & v); +# endif + + ////////////////////////////////////// + // Swizzle constructors + +# if GLM_HAS_ANONYMOUS_UNION && defined(GLM_SWIZZLE) + template <int E0, int E1, int E2, int E3> + GLM_FUNC_DECL tvec4(detail::_swizzle<4, T, P, tvec4<T, P>, E0, E1, E2, E3> const & that) + { + *this = that(); + } + + template <int E0, int E1, int F0, int F1> + GLM_FUNC_DECL tvec4(detail::_swizzle<2, T, P, tvec2<T, P>, E0, E1, -1, -2> const & v, detail::_swizzle<2, T, P, tvec2<T, P>, F0, F1, -1, -2> const & u) + { + *this = tvec4<T, P>(v(), u()); + } + + template <int E0, int E1> + GLM_FUNC_DECL tvec4(T const & x, T const & y, detail::_swizzle<2, T, P, tvec2<T, P>, E0, E1, -1, -2> const & v) + { + *this = tvec4<T, P>(x, y, v()); + } + + template <int E0, int E1> + GLM_FUNC_DECL tvec4(T const & x, detail::_swizzle<2, T, P, tvec2<T, P>, E0, E1, -1, -2> const & v, T const & w) + { + *this = tvec4<T, P>(x, v(), w); + } + + template <int E0, int E1> + GLM_FUNC_DECL tvec4(detail::_swizzle<2, T, P, tvec2<T, P>, E0, E1, -1, -2> const & v, T const & z, T const & w) + { + *this = tvec4<T, P>(v(), z, w); + } + + template <int E0, int E1, int E2> + GLM_FUNC_DECL tvec4(detail::_swizzle<3, T, P, tvec3<T, P>, E0, E1, E2, -1> const & v, T const & w) + { + *this = tvec4<T, P>(v(), w); + } + + template <int E0, int E1, int E2> + GLM_FUNC_DECL tvec4(T const & x, detail::_swizzle<3, T, P, tvec3<T, P>, E0, E1, E2, -1> const & v) + { + *this = tvec4<T, P>(x, v()); + } +# endif// GLM_HAS_ANONYMOUS_UNION && defined(GLM_SWIZZLE) + + ////////////////////////////////////// + // Unary arithmetic operators + + GLM_FUNC_DECL tvec4<T, P> & operator=(tvec4<T, P> const & v); + + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator=(tvec4<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator+=(U scalar); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator+=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator+=(tvec4<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator-=(U scalar); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator-=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator-=(tvec4<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator*=(U scalar); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator*=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator*=(tvec4<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator/=(U scalar); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator/=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator/=(tvec4<U, P> const & v); + + ////////////////////////////////////// + // Increment and decrement operators + + GLM_FUNC_DECL tvec4<T, P> & operator++(); + GLM_FUNC_DECL tvec4<T, P> & operator--(); + GLM_FUNC_DECL tvec4<T, P> operator++(int); + GLM_FUNC_DECL tvec4<T, P> operator--(int); + + ////////////////////////////////////// + // Unary bit operators + + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator%=(U scalar); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator%=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator%=(tvec4<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator&=(U scalar); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator&=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator&=(tvec4<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator|=(U scalar); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator|=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator|=(tvec4<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator^=(U scalar); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator^=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator^=(tvec4<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator<<=(U scalar); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator<<=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator<<=(tvec4<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator>>=(U scalar); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator>>=(tvec1<U, P> const & v); + template <typename U> + GLM_FUNC_DECL tvec4<T, P> & operator>>=(tvec4<U, P> const & v); + }; + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator+(tvec4<T, P> const & v, T scalar); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator+(tvec4<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator+(T scalar, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator+(tvec1<T, P> const & s, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator+(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator-(tvec4<T, P> const & v, T scalar); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator-(tvec4<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator-(T scalar, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator-(tvec1<T, P> const & s, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator-(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator*(tvec4<T, P> const & v, T scalar); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator*(tvec4<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator*(T scalar, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator*(tvec1<T, P> const & s, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator*(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator/(tvec4<T, P> const & v, T scalar); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator/(tvec4<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator/(T scalar, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator/(tvec1<T, P> const & s, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator/(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator-(tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL bool operator==(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL bool operator!=(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator%(tvec4<T, P> const & v, T scalar); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator%(tvec4<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator%(T scalar, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator%(tvec1<T, P> const & s, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator%(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator&(tvec4<T, P> const & v, T scalar); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator&(tvec4<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator&(T scalar, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator&(tvec1<T, P> const & s, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator&(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator|(tvec4<T, P> const & v, T scalar); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator|(tvec4<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator|(T scalar, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator|(tvec1<T, P> const & s, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator|(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator^(tvec4<T, P> const & v, T scalar); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator^(tvec4<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator^(T scalar, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator^(tvec1<T, P> const & s, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator^(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator<<(tvec4<T, P> const & v, T scalar); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator<<(tvec4<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator<<(T scalar, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator<<(tvec1<T, P> const & s, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator<<(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator>>(tvec4<T, P> const & v, T scalar); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator>>(tvec4<T, P> const & v, tvec1<T, P> const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator>>(T scalar, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator>>(tvec1<T, P> const & s, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator>>(tvec4<T, P> const & v1, tvec4<T, P> const & v2); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator~(tvec4<T, P> const & v); +}//namespace glm + +#ifndef GLM_EXTERNAL_TEMPLATE +#include "type_vec4.inl" +#endif//GLM_EXTERNAL_TEMPLATE diff --git a/extensions/common/glm/detail/type_vec4.inl b/extensions/common/glm/detail/type_vec4.inl new file mode 100644 index 0000000000..a3e9bb2995 --- /dev/null +++ b/extensions/common/glm/detail/type_vec4.inl @@ -0,0 +1,1124 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_tvec4.inl +/// @date 2008-08-23 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + ////////////////////////////////////// + // Implicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4() +# ifndef GLM_FORCE_NO_CTOR_INIT + : x(0), y(0), z(0), w(0) +# endif + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec4<T, P> const & v) + : x(v.x), y(v.y), z(v.z), w(v.w) + {} + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec4<T, Q> const & v) + : x(v.x), y(v.y), z(v.z), w(v.w) + {} + + ////////////////////////////////////// + // Explicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(T s) + : x(s), y(s), z(s), w(s) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(T a, T b, T c, T d) + : x(a), y(b), z(c), w(d) + {} + + ////////////////////////////////////// + // Conversion scalar constructors + + template <typename T, precision P> + template <typename A, typename B, typename C, typename D> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(A a, B b, C c, D d) : + x(static_cast<T>(a)), + y(static_cast<T>(b)), + z(static_cast<T>(c)), + w(static_cast<T>(d)) + {} + + template <typename T, precision P> + template <typename A, typename B, typename C, typename D> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec1<A, P> const & a, tvec1<B, P> const & b, tvec1<C, P> const & c, tvec1<D, P> const & d) : + x(static_cast<T>(a.x)), + y(static_cast<T>(b.x)), + z(static_cast<T>(c.x)), + w(static_cast<T>(d.x)) + {} + + ////////////////////////////////////// + // Conversion vector constructors + + template <typename T, precision P> + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec2<A, Q> const & a, B b, C c) : + x(static_cast<T>(a.x)), + y(static_cast<T>(a.y)), + z(static_cast<T>(b)), + w(static_cast<T>(c)) + {} + + template <typename T, precision P> + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec2<A, Q> const & a, tvec1<B, Q> const & b, tvec1<C, Q> const & c) : + x(static_cast<T>(a.x)), + y(static_cast<T>(a.y)), + z(static_cast<T>(b.x)), + w(static_cast<T>(c.x)) + {} + + template <typename T, precision P> + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(A s1, tvec2<B, Q> const & v, C s2) : + x(static_cast<T>(s1)), + y(static_cast<T>(v.x)), + z(static_cast<T>(v.y)), + w(static_cast<T>(s2)) + {} + + template <typename T, precision P> + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec1<A, Q> const & a, tvec2<B, Q> const & b, tvec1<C, Q> const & c) : + x(static_cast<T>(a.x)), + y(static_cast<T>(b.x)), + z(static_cast<T>(b.y)), + w(static_cast<T>(c.x)) + {} + + template <typename T, precision P> + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(A s1, B s2, tvec2<C, Q> const & v) : + x(static_cast<T>(s1)), + y(static_cast<T>(s2)), + z(static_cast<T>(v.x)), + w(static_cast<T>(v.y)) + {} + + template <typename T, precision P> + template <typename A, typename B, typename C, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec1<A, Q> const & a, tvec1<B, Q> const & b, tvec2<C, Q> const & c) : + x(static_cast<T>(a.x)), + y(static_cast<T>(b.x)), + z(static_cast<T>(c.x)), + w(static_cast<T>(c.y)) + {} + + template <typename T, precision P> + template <typename A, typename B, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec3<A, Q> const & a, B b) : + x(static_cast<T>(a.x)), + y(static_cast<T>(a.y)), + z(static_cast<T>(a.z)), + w(static_cast<T>(b)) + {} + + template <typename T, precision P> + template <typename A, typename B, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec3<A, Q> const & a, tvec1<B, Q> const & b) : + x(static_cast<T>(a.x)), + y(static_cast<T>(a.y)), + z(static_cast<T>(a.z)), + w(static_cast<T>(b.x)) + {} + + template <typename T, precision P> + template <typename A, typename B, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(A a, tvec3<B, Q> const & b) : + x(static_cast<T>(a)), + y(static_cast<T>(b.x)), + z(static_cast<T>(b.y)), + w(static_cast<T>(b.z)) + {} + + template <typename T, precision P> + template <typename A, typename B, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec1<A, Q> const & a, tvec3<B, Q> const & b) : + x(static_cast<T>(a.x)), + y(static_cast<T>(b.x)), + z(static_cast<T>(b.y)), + w(static_cast<T>(b.z)) + {} + + template <typename T, precision P> + template <typename A, typename B, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec2<A, Q> const & a, tvec2<B, Q> const & b) : + x(static_cast<T>(a.x)), + y(static_cast<T>(a.y)), + z(static_cast<T>(b.x)), + w(static_cast<T>(b.y)) + {} + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tvec4<T, P>::tvec4(tvec4<U, Q> const & v) : + x(static_cast<T>(v.x)), + y(static_cast<T>(v.y)), + z(static_cast<T>(v.z)), + w(static_cast<T>(v.w)) + {} + + ////////////////////////////////////// + // Component accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tvec4<T, P>::size_type tvec4<T, P>::size() const + { + return 4; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T & tvec4<T, P>::operator[](typename tvec4<T, P>::size_type i) + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T const & tvec4<T, P>::operator[](typename tvec4<T, P>::size_type i) const + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tvec4<T, P>::length_type tvec4<T, P>::length() const + { + return 4; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T & tvec4<T, P>::operator[](typename tvec4<T, P>::length_type i) + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T const & tvec4<T, P>::operator[](typename tvec4<T, P>::length_type i) const + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Unary arithmetic operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator=(tvec4<T, P> const & v) + { + this->x = v.x; + this->y = v.y; + this->z = v.z; + this->w = v.w; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator=(tvec4<U, P> const & v) + { + this->x = static_cast<T>(v.x); + this->y = static_cast<T>(v.y); + this->z = static_cast<T>(v.z); + this->w = static_cast<T>(v.w); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator+=(U scalar) + { + this->x += static_cast<T>(scalar); + this->y += static_cast<T>(scalar); + this->z += static_cast<T>(scalar); + this->w += static_cast<T>(scalar); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator+=(tvec1<U, P> const & v) + { + T const scalar = static_cast<T>(v.x); + this->x += scalar; + this->y += scalar; + this->z += scalar; + this->w += scalar; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator+=(tvec4<U, P> const & v) + { + this->x += static_cast<T>(v.x); + this->y += static_cast<T>(v.y); + this->z += static_cast<T>(v.z); + this->w += static_cast<T>(v.w); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator-=(U scalar) + { + this->x -= static_cast<T>(scalar); + this->y -= static_cast<T>(scalar); + this->z -= static_cast<T>(scalar); + this->w -= static_cast<T>(scalar); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator-=(tvec1<U, P> const & v) + { + T const scalar = static_cast<T>(v.x); + this->x -= scalar; + this->y -= scalar; + this->z -= scalar; + this->w -= scalar; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator-=(tvec4<U, P> const & v) + { + this->x -= static_cast<T>(v.x); + this->y -= static_cast<T>(v.y); + this->z -= static_cast<T>(v.z); + this->w -= static_cast<T>(v.w); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator*=(U s) + { + this->x *= static_cast<T>(s); + this->y *= static_cast<T>(s); + this->z *= static_cast<T>(s); + this->w *= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator*=(tvec1<U, P> const & v) + { + this->x *= static_cast<T>(v.x); + this->y *= static_cast<T>(v.x); + this->z *= static_cast<T>(v.x); + this->w *= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator*=(tvec4<U, P> const & v) + { + this->x *= static_cast<T>(v.x); + this->y *= static_cast<T>(v.y); + this->z *= static_cast<T>(v.z); + this->w *= static_cast<T>(v.w); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator/=(U s) + { + this->x /= static_cast<T>(s); + this->y /= static_cast<T>(s); + this->z /= static_cast<T>(s); + this->w /= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator/=(tvec1<U, P> const & v) + { + this->x /= static_cast<T>(v.x); + this->y /= static_cast<T>(v.x); + this->z /= static_cast<T>(v.x); + this->w /= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator/=(tvec4<U, P> const & v) + { + this->x /= static_cast<T>(v.x); + this->y /= static_cast<T>(v.y); + this->z /= static_cast<T>(v.z); + this->w /= static_cast<T>(v.w); + return *this; + } + + ////////////////////////////////////// + // Increment and decrement operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator++() + { + ++this->x; + ++this->y; + ++this->z; + ++this->w; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator--() + { + --this->x; + --this->y; + --this->z; + --this->w; + return *this; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> tvec4<T, P>::operator++(int) + { + tvec4<T, P> Result(*this); + ++*this; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> tvec4<T, P>::operator--(int) + { + tvec4<T, P> Result(*this); + --*this; + return Result; + } + + ////////////////////////////////////// + // Unary bit operators + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator%=(U scalar) + { + this->x %= static_cast<T>(scalar); + this->y %= static_cast<T>(scalar); + this->z %= static_cast<T>(scalar); + this->w %= static_cast<T>(scalar); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator%=(tvec1<U, P> const & v) + { + this->x %= static_cast<T>(v.x); + this->y %= static_cast<T>(v.x); + this->z %= static_cast<T>(v.x); + this->w %= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator%=(tvec4<U, P> const & v) + { + this->x %= static_cast<T>(v.x); + this->y %= static_cast<T>(v.y); + this->z %= static_cast<T>(v.z); + this->w %= static_cast<T>(v.w); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator&=(U scalar) + { + this->x &= static_cast<T>(scalar); + this->y &= static_cast<T>(scalar); + this->z &= static_cast<T>(scalar); + this->w &= static_cast<T>(scalar); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator&=(tvec1<U, P> const & v) + { + this->x &= static_cast<T>(v.x); + this->y &= static_cast<T>(v.x); + this->z &= static_cast<T>(v.x); + this->w &= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator&=(tvec4<U, P> const & v) + { + this->x &= static_cast<T>(v.x); + this->y &= static_cast<T>(v.y); + this->z &= static_cast<T>(v.z); + this->w &= static_cast<T>(v.w); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator|=(U scalar) + { + this->x |= static_cast<T>(scalar); + this->y |= static_cast<T>(scalar); + this->z |= static_cast<T>(scalar); + this->w |= static_cast<T>(scalar); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator|=(tvec1<U, P> const & v) + { + this->x |= static_cast<T>(v.x); + this->y |= static_cast<T>(v.x); + this->z |= static_cast<T>(v.x); + this->w |= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator|=(tvec4<U, P> const & v) + { + this->x |= static_cast<T>(v.x); + this->y |= static_cast<T>(v.y); + this->z |= static_cast<T>(v.z); + this->w |= static_cast<T>(v.w); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator^=(U scalar) + { + this->x ^= static_cast<T>(scalar); + this->y ^= static_cast<T>(scalar); + this->z ^= static_cast<T>(scalar); + this->w ^= static_cast<T>(scalar); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator^=(tvec1<U, P> const & v) + { + this->x ^= static_cast<T>(v.x); + this->y ^= static_cast<T>(v.x); + this->z ^= static_cast<T>(v.x); + this->w ^= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator^=(tvec4<U, P> const & v) + { + this->x ^= static_cast<T>(v.x); + this->y ^= static_cast<T>(v.y); + this->z ^= static_cast<T>(v.z); + this->w ^= static_cast<T>(v.w); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator<<=(U scalar) + { + this->x <<= static_cast<T>(scalar); + this->y <<= static_cast<T>(scalar); + this->z <<= static_cast<T>(scalar); + this->w <<= static_cast<T>(scalar); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator<<=(tvec1<U, P> const & v) + { + this->x <<= static_cast<T>(v.x); + this->y <<= static_cast<T>(v.x); + this->z <<= static_cast<T>(v.x); + this->w <<= static_cast<T>(v.x); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator<<=(tvec4<U, P> const & v) + { + this->x <<= static_cast<T>(v.x); + this->y <<= static_cast<T>(v.y); + this->z <<= static_cast<T>(v.z); + this->w <<= static_cast<T>(v.w); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator>>=(U scalar) + { + this->x >>= static_cast<T>(scalar); + this->y >>= static_cast<T>(scalar); + this->z >>= static_cast<T>(scalar); + this->w >>= static_cast<T>(scalar); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator>>=(tvec1<U, P> const & v) + { + this->x >>= static_cast<T>(v.x); + this->y >>= static_cast<T>(v.y); + this->z >>= static_cast<T>(v.z); + this->w >>= static_cast<T>(v.w); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<T, P> & tvec4<T, P>::operator>>=(tvec4<U, P> const & v) + { + this->x >>= static_cast<T>(v.x); + this->y >>= static_cast<T>(v.y); + this->z >>= static_cast<T>(v.z); + this->w >>= static_cast<T>(v.w); + return *this; + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z) && (v1.w == v2.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return (v1.x != v2.x) || (v1.y != v2.y) || (v1.z != v2.z) || (v1.w != v2.w); + } + + ////////////////////////////////////// + // Binary arithmetic operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator+(tvec4<T, P> const & v, T scalar) + { + return tvec4<T, P>( + v.x + scalar, + v.y + scalar, + v.z + scalar, + v.w + scalar); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator+(T scalar, tvec4<T, P> const & v) + { + return tvec4<T, P>( + scalar + v.x, + scalar + v.y, + scalar + v.z, + scalar + v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator+(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return tvec4<T, P>( + v1.x + v2.x, + v1.y + v2.y, + v1.z + v2.z, + v1.w + v2.w); + } + + //operator- + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator-(tvec4<T, P> const & v, T scalar) + { + return tvec4<T, P>( + v.x - scalar, + v.y - scalar, + v.z - scalar, + v.w - scalar); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator-(T scalar, tvec4<T, P> const & v) + { + return tvec4<T, P>( + scalar - v.x, + scalar - v.y, + scalar - v.z, + scalar - v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator-(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return tvec4<T, P>( + v1.x - v2.x, + v1.y - v2.y, + v1.z - v2.z, + v1.w - v2.w); + } + + //operator* + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator*(tvec4<T, P> const & v, T scalar) + { + return tvec4<T, P>( + v.x * scalar, + v.y * scalar, + v.z * scalar, + v.w * scalar); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator*(T scalar, tvec4<T, P> const & v) + { + return tvec4<T, P>( + scalar * v.x, + scalar * v.y, + scalar * v.z, + scalar * v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator*(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return tvec4<T, P>( + v1.x * v2.x, + v1.y * v2.y, + v1.z * v2.z, + v1.w * v2.w); + } + + //operator/ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator/(tvec4<T, P> const & v, T scalar) + { + return tvec4<T, P>( + v.x / scalar, + v.y / scalar, + v.z / scalar, + v.w / scalar); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator/(T scalar, tvec4<T, P> const & v) + { + return tvec4<T, P>( + scalar / v.x, + scalar / v.y, + scalar / v.z, + scalar / v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator/(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return tvec4<T, P>( + v1.x / v2.x, + v1.y / v2.y, + v1.z / v2.z, + v1.w / v2.w); + } + + // Unary constant operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator-(tvec4<T, P> const & v) + { + return tvec4<T, P>( + -v.x, + -v.y, + -v.z, + -v.w); + } + + ////////////////////////////////////// + // Binary bit operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator%(tvec4<T, P> const & v, T s) + { + return tvec4<T, P>( + v.x % s, + v.y % s, + v.z % s, + v.w % s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator%(tvec4<T, P> const & v, tvec1<T, P> const & s) + { + return tvec4<T, P>( + v.x % s.x, + v.y % s.x, + v.z % s.x, + v.w % s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator%(T s, tvec4<T, P> const & v) + { + return tvec4<T, P>( + s % v.x, + s % v.y, + s % v.z, + s % v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator%(tvec1<T, P> const & s, tvec4<T, P> const & v) + { + return tvec4<T, P>( + s.x % v.x, + s.x % v.y, + s.x % v.z, + s.x % v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator%(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return tvec4<T, P>( + v1.x % v2.x, + v1.y % v2.y, + v1.z % v2.z, + v1.w % v2.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator&(tvec4<T, P> const & v, T s) + { + return tvec4<T, P>( + v.x & s, + v.y & s, + v.z & s, + v.w & s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator&(tvec4<T, P> const & v, tvec1<T, P> const & s) + { + return tvec4<T, P>( + v.x & s.x, + v.y & s.x, + v.z & s.x, + v.w & s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator&(T s, tvec4<T, P> const & v) + { + return tvec4<T, P>( + s & v.x, + s & v.y, + s & v.z, + s & v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator&(tvec1<T, P> const & s, tvec4<T, P> const & v) + { + return tvec4<T, P>( + s.x & v.x, + s.x & v.y, + s.x & v.z, + s.x & v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator&(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return tvec4<T, P>( + v1.x & v2.x, + v1.y & v2.y, + v1.z & v2.z, + v1.w & v2.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator|(tvec4<T, P> const & v, T s) + { + return tvec4<T, P>( + v.x | s, + v.y | s, + v.z | s, + v.w | s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator|(tvec4<T, P> const & v, tvec1<T, P> const & s) + { + return tvec4<T, P>( + v.x | s.x, + v.y | s.x, + v.z | s.x, + v.w | s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator|(T s, tvec4<T, P> const & v) + { + return tvec4<T, P>( + s | v.x, + s | v.y, + s | v.z, + s | v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator|(tvec1<T, P> const & s, tvec4<T, P> const & v) + { + return tvec4<T, P>( + s.x | v.x, + s.x | v.y, + s.x | v.z, + s.x | v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator|(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return tvec4<T, P>( + v1.x | v2.x, + v1.y | v2.y, + v1.z | v2.z, + v1.w | v2.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator^(tvec4<T, P> const & v, T s) + { + return tvec4<T, P>( + v.x ^ s, + v.y ^ s, + v.z ^ s, + v.w ^ s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator^(tvec4<T, P> const & v, tvec1<T, P> const & s) + { + return tvec4<T, P>( + v.x ^ s.x, + v.y ^ s.x, + v.z ^ s.x, + v.w ^ s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator^(T scalar, tvec4<T, P> const & v) + { + return tvec4<T, P>( + scalar ^ v.x, + scalar ^ v.y, + scalar ^ v.z, + scalar ^ v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator^(tvec1<T, P> const & s, tvec4<T, P> const & v) + { + return tvec4<T, P>( + s.x ^ v.x, + s.x ^ v.y, + s.x ^ v.z, + s.x ^ v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator^(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return tvec4<T, P>( + v1.x ^ v2.x, + v1.y ^ v2.y, + v1.z ^ v2.z, + v1.w ^ v2.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator<<(tvec4<T, P> const & v, T scalar) + { + return tvec4<T, P>( + v.x << scalar, + v.y << scalar, + v.z << scalar, + v.w << scalar); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator<<(tvec4<T, P> const & v, tvec1<T, P> const & s) + { + return tvec4<T, P>( + v.x << s.x, + v.y << s.x, + v.z << s.x, + v.w << s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator<<(T scalar, tvec4<T, P> const & v) + { + return tvec4<T, P>( + scalar << v.x, + scalar << v.y, + scalar << v.z, + scalar << v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator<<(tvec1<T, P> const & s, tvec4<T, P> const & v) + { + return tvec4<T, P>( + s.x << v.x, + s.x << v.y, + s.x << v.z, + s.x << v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator<<(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return tvec4<T, P>( + v1.x << v2.x, + v1.y << v2.y, + v1.z << v2.z, + v1.w << v2.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator>>(tvec4<T, P> const & v, T scalar) + { + return tvec4<T, P>( + v.x >> scalar, + v.y >> scalar, + v.z >> scalar, + v.w >> scalar); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator>>(tvec4<T, P> const & v, tvec1<T, P> const & s) + { + return tvec4<T, P>( + v.x >> s.x, + v.y >> s.x, + v.z >> s.x, + v.w >> s.x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator>>(T scalar, tvec4<T, P> const & v) + { + return tvec4<T, P>( + scalar >> v.x, + scalar >> v.y, + scalar >> v.z, + scalar >> v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator>>(tvec1<T, P> const & s, tvec4<T, P> const & v) + { + return tvec4<T, P>( + s.x >> v.x, + s.x >> v.y, + s.x >> v.z, + s.x >> v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator>>(tvec4<T, P> const & v1, tvec4<T, P> const & v2) + { + return tvec4<T, P>( + v1.x >> v2.x, + v1.y >> v2.y, + v1.z >> v2.z, + v1.w >> v2.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator~(tvec4<T, P> const & v) + { + return tvec4<T, P>( + ~v.x, + ~v.y, + ~v.z, + ~v.w); + } +}//namespace glm + +#if GLM_HAS_ANONYMOUS_UNION && GLM_NOT_BUGGY_VC32BITS +#if GLM_ARCH & GLM_ARCH_SSE2 +# include "type_vec4_sse2.inl" +#endif +#if GLM_ARCH & GLM_ARCH_AVX +# include "type_vec4_avx.inl" +#endif +#if GLM_ARCH & GLM_ARCH_AVX2 +# include "type_vec4_avx2.inl" +#endif +#endif// diff --git a/extensions/common/glm/detail/type_vec4_avx.inl b/extensions/common/glm/detail/type_vec4_avx.inl new file mode 100644 index 0000000000..478430131e --- /dev/null +++ b/extensions/common/glm/detail/type_vec4_avx.inl @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_tvec4_avx.inl +/// @date 2014-12-01 / 2014-12-01 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail +{ + +}//namespace detail + + + +}//namespace glm diff --git a/extensions/common/glm/detail/type_vec4_avx2.inl b/extensions/common/glm/detail/type_vec4_avx2.inl new file mode 100644 index 0000000000..f6151d7fa1 --- /dev/null +++ b/extensions/common/glm/detail/type_vec4_avx2.inl @@ -0,0 +1,41 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_tvec4_avx2.inl +/// @date 2014-12-01 / 2014-12-01 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail +{ + +}//namespace detail + + + +}//namespace glm diff --git a/extensions/common/glm/detail/type_vec4_sse2.inl b/extensions/common/glm/detail/type_vec4_sse2.inl new file mode 100644 index 0000000000..ec3087b9d1 --- /dev/null +++ b/extensions/common/glm/detail/type_vec4_sse2.inl @@ -0,0 +1,120 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/detail/type_tvec4_sse2.inl +/// @date 2014-12-01 / 2014-12-01 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail +{ + +}//namespace detail + + template <> + GLM_FUNC_QUALIFIER tvec4<float, lowp>::tvec4() +# ifndef GLM_FORCE_NO_CTOR_INIT + : data(_mm_setzero_ps()) +# endif + {} + + template <> + GLM_FUNC_QUALIFIER tvec4<float, mediump>::tvec4() +# ifndef GLM_FORCE_NO_CTOR_INIT + : data(_mm_setzero_ps()) +# endif + {} + + template <> + GLM_FUNC_QUALIFIER tvec4<float, lowp>::tvec4(float s) : + data(_mm_set1_ps(s)) + {} + + template <> + GLM_FUNC_QUALIFIER tvec4<float, mediump>::tvec4(float s) : + data(_mm_set1_ps(s)) + {} + + template <> + GLM_FUNC_QUALIFIER tvec4<float, lowp>::tvec4(float a, float b, float c, float d) : + data(_mm_set_ps(d, c, b, a)) + {} + + template <> + GLM_FUNC_QUALIFIER tvec4<float, mediump>::tvec4(float a, float b, float c, float d) : + data(_mm_set_ps(d, c, b, a)) + {} + + template <> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<float, lowp> & tvec4<float, lowp>::operator+=(U scalar) + { + this->data = _mm_add_ps(this->data, _mm_set_ps1(static_cast<float>(scalar))); + return *this; + } + + template <> + template <> + GLM_FUNC_QUALIFIER tvec4<float, lowp> & tvec4<float, lowp>::operator+=<float>(float scalar) + { + this->data = _mm_add_ps(this->data, _mm_set_ps1(scalar)); + return *this; + } + + template <> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<float, mediump> & tvec4<float, mediump>::operator+=(U scalar) + { + this->data = _mm_add_ps(this->data, _mm_set_ps1(static_cast<float>(scalar))); + return *this; + } + + template <> + template <> + GLM_FUNC_QUALIFIER tvec4<float, mediump> & tvec4<float, mediump>::operator+=<float>(float scalar) + { + this->data = _mm_add_ps(this->data, _mm_set_ps1(scalar)); + return *this; + } + + template <> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<float, lowp> & tvec4<float, lowp>::operator+=(tvec1<U, lowp> const & v) + { + this->data = _mm_add_ps(this->data, _mm_set_ps1(static_cast<float>(v.x))); + return *this; + } + + template <> + template <typename U> + GLM_FUNC_QUALIFIER tvec4<float, mediump> & tvec4<float, mediump>::operator+=(tvec1<U, mediump> const & v) + { + this->data = _mm_add_ps(this->data, _mm_set_ps1(static_cast<float>(v.x))); + return *this; + } +}//namespace glm diff --git a/extensions/common/glm/exponential.hpp b/extensions/common/glm/exponential.hpp new file mode 100644 index 0000000000..9ca9d4ec11 --- /dev/null +++ b/extensions/common/glm/exponential.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/exponential.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/func_exponential.hpp" diff --git a/extensions/common/glm/ext.hpp b/extensions/common/glm/ext.hpp new file mode 100644 index 0000000000..b978be0415 --- /dev/null +++ b/extensions/common/glm/ext.hpp @@ -0,0 +1,143 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @file glm/glm.hpp +/// @date 2009-05-01 / 2011-05-16 +/// @author Christophe Riccio +/// +/// @ref core (Dependence) +/// +/// @defgroup gtc GTC Extensions (Stable) +/// +/// @brief Functions and types that the GLSL specification doesn't define, but useful to have for a C++ program. +/// +/// GTC extensions aim to be stable. +/// +/// Even if it's highly unrecommended, it's possible to include all the extensions at once by +/// including <glm/ext.hpp>. Otherwise, each extension needs to be included a specific file. +/// +/// @defgroup gtx GTX Extensions (Experimental) +/// +/// @brief Functions and types that the GLSL specification doesn't define, but +/// useful to have for a C++ program. +/// +/// Experimental extensions are useful functions and types, but the development of +/// their API and functionality is not necessarily stable. They can change +/// substantially between versions. Backwards compatibility is not much of an issue +/// for them. +/// +/// Even if it's highly unrecommended, it's possible to include all the extensions +/// at once by including <glm/ext.hpp>. Otherwise, each extension needs to be +/// included a specific file. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#if(defined(GLM_MESSAGES) && !defined(GLM_MESSAGE_EXT_INCLUDED_DISPLAYED)) +# define GLM_MESSAGE_EXT_INCLUDED_DISPLAYED +# pragma message("GLM: All extensions included (not recommanded)") +#endif//GLM_MESSAGES + +#include "./gtc/bitfield.hpp" +#include "./gtc/constants.hpp" +#include "./gtc/epsilon.hpp" +#include "./gtc/integer.hpp" +#include "./gtc/matrix_access.hpp" +#include "./gtc/matrix_integer.hpp" +#include "./gtc/matrix_inverse.hpp" +#include "./gtc/matrix_transform.hpp" +#include "./gtc/noise.hpp" +#include "./gtc/packing.hpp" +#include "./gtc/quaternion.hpp" +#include "./gtc/random.hpp" +#include "./gtc/reciprocal.hpp" +#include "./gtc/round.hpp" +#include "./gtc/type_precision.hpp" +#include "./gtc/type_ptr.hpp" +#include "./gtc/ulp.hpp" +#include "./gtc/vec1.hpp" + +#include "./gtx/associated_min_max.hpp" +#include "./gtx/bit.hpp" +#include "./gtx/closest_point.hpp" +#include "./gtx/color_space.hpp" +#include "./gtx/color_space_YCoCg.hpp" +#include "./gtx/compatibility.hpp" +#include "./gtx/component_wise.hpp" +#include "./gtx/dual_quaternion.hpp" +#include "./gtx/euler_angles.hpp" +#include "./gtx/extend.hpp" +#include "./gtx/extented_min_max.hpp" +#include "./gtx/fast_exponential.hpp" +#include "./gtx/fast_square_root.hpp" +#include "./gtx/fast_trigonometry.hpp" +#include "./gtx/gradient_paint.hpp" +#include "./gtx/handed_coordinate_space.hpp" +#include "./gtx/integer.hpp" +#include "./gtx/intersect.hpp" +#include "./gtx/log_base.hpp" +#include "./gtx/matrix_cross_product.hpp" +#include "./gtx/matrix_interpolation.hpp" +#include "./gtx/matrix_major_storage.hpp" +#include "./gtx/matrix_operation.hpp" +#include "./gtx/matrix_query.hpp" +#include "./gtx/mixed_product.hpp" +#include "./gtx/norm.hpp" +#include "./gtx/normal.hpp" +#include "./gtx/normalize_dot.hpp" +#include "./gtx/number_precision.hpp" +#include "./gtx/optimum_pow.hpp" +#include "./gtx/orthonormalize.hpp" +#include "./gtx/perpendicular.hpp" +#include "./gtx/polar_coordinates.hpp" +#include "./gtx/projection.hpp" +#include "./gtx/quaternion.hpp" +#include "./gtx/raw_data.hpp" +#include "./gtx/rotate_vector.hpp" +#include "./gtx/spline.hpp" +#include "./gtx/std_based_type.hpp" +#if !(GLM_COMPILER & GLM_COMPILER_CUDA) +# include "./gtx/string_cast.hpp" +#endif +#include "./gtx/transform.hpp" +#include "./gtx/transform2.hpp" +#include "./gtx/type_aligned.hpp" +#include "./gtx/vector_angle.hpp" +#include "./gtx/vector_query.hpp" +#include "./gtx/wrap.hpp" + +#if GLM_HAS_TEMPLATE_ALIASES +# include "./gtx/scalar_multiplication.hpp" +#endif + +#if GLM_HAS_RANGE_FOR +# include "./gtx/range.hpp" +#endif + +#if GLM_ARCH & GLM_ARCH_SSE2 +# include "./gtx/simd_vec4.hpp" +# include "./gtx/simd_mat4.hpp" +#endif diff --git a/extensions/common/glm/fwd.hpp b/extensions/common/glm/fwd.hpp new file mode 100644 index 0000000000..f3615bdaaf --- /dev/null +++ b/extensions/common/glm/fwd.hpp @@ -0,0 +1,2601 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/fwd.hpp +/// @date 2013-03-30 / 2013-03-31 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_int.hpp" +#include "detail/type_float.hpp" +#include "detail/type_vec.hpp" +#include "detail/type_mat.hpp" + +////////////////////// +// GLM_GTC_quaternion +namespace glm +{ + template <typename T, precision P> struct tquat; + + /// Quaternion of low single-precision floating-point numbers. + /// + /// @see gtc_quaternion + typedef tquat<float, lowp> lowp_quat; + + /// Quaternion of medium single-precision floating-point numbers. + /// + /// @see gtc_quaternion + typedef tquat<float, mediump> mediump_quat; + + /// Quaternion of high single-precision floating-point numbers. + /// + /// @see gtc_quaternion + typedef tquat<float, highp> highp_quat; + +#if(defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + typedef highp_quat quat; +#elif(!defined(GLM_PRECISION_HIGHP_FLOAT) && defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + typedef mediump_quat quat; +#elif(!defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && defined(GLM_PRECISION_LOWP_FLOAT)) + typedef lowp_quat quat; +#elif(!defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + /// Quaternion of default single-precision floating-point numbers. + typedef highp_quat quat; +#endif + + /// Quaternion of low single-precision floating-point numbers. + /// + /// @see gtc_quaternion + typedef lowp_quat lowp_fquat; + + /// Quaternion of medium single-precision floating-point numbers. + /// + /// @see gtc_quaternion + typedef mediump_quat mediump_fquat; + + /// Quaternion of high single-precision floating-point numbers. + /// + /// @see gtc_quaternion + typedef highp_quat highp_fquat; + + /// Quaternion of default single-precision floating-point numbers. + /// + /// @see gtc_quaternion + typedef quat fquat; + + + /// Quaternion of low double-precision floating-point numbers. + /// + /// @see gtc_quaternion + typedef tquat<double, lowp> lowp_dquat; + + /// Quaternion of medium double-precision floating-point numbers. + /// + /// @see gtc_quaternion + typedef tquat<double, mediump> mediump_dquat; + + /// Quaternion of high double-precision floating-point numbers. + /// + /// @see gtc_quaternion + typedef tquat<double, highp> highp_dquat; + +#if(defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef highp_dquat dquat; +#elif(!defined(GLM_PRECISION_HIGHP_DOUBLE) && defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef mediump_dquat dquat; +#elif(!defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef lowp_dquat dquat; +#elif(!defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + /// Quaternion of default double-precision floating-point numbers. + /// + /// @see gtc_quaternion + typedef highp_dquat dquat; +#endif + +}//namespace glm + +////////////////////// +// GLM_GTC_precision +namespace glm +{ + /// @addtogroup gtc_type_precision + /// @{ + + /// Low precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_int8; + + /// Low precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_int16; + + /// Low precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_int32; + + /// Low precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_int64; + + /// Low precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_int8_t; + + /// Low precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_int16_t; + + /// Low precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_int32_t; + + /// Low precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_int64_t; + + /// Low precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_i8; + + /// Low precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_i16; + + /// Low precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_i32; + + /// Low precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_i64; + + /// Medium precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_int8; + + /// Medium precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_int16; + + /// Medium precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_int32; + + /// Medium precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_int64; + + /// Medium precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_int8_t; + + /// Medium precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_int16_t; + + /// Medium precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_int32_t; + + /// Medium precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_int64_t; + + /// Medium precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_i8; + + /// Medium precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_i16; + + /// Medium precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_i32; + + /// Medium precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_i64; + + /// High precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_int8; + + /// High precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_int16; + + /// High precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_int32; + + /// High precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_int64; + + /// High precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_int8_t; + + /// High precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_int16_t; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_int32_t; + + /// High precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_int64_t; + + /// High precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_i8; + + /// High precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_i16; + + /// High precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_i32; + + /// High precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_i64; + + + /// 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 int8; + + /// 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 int16; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 int32; + + /// 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 int64; + + +#if GLM_HAS_EXTENDED_INTEGER_TYPE + using std::int8_t; + using std::int16_t; + using std::int32_t; + using std::int64_t; +#else + /// 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 int8_t; + + /// 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 int16_t; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 int32_t; + + /// 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 int64_t; +#endif + + /// 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 i8; + + /// 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 i16; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 i32; + + /// 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 i64; + + + + /// Low precision 8 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i8, lowp> lowp_i8vec1; + + /// Low precision 8 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i8, lowp> lowp_i8vec2; + + /// Low precision 8 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i8, lowp> lowp_i8vec3; + + /// Low precision 8 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i8, lowp> lowp_i8vec4; + + + /// Medium precision 8 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i8, mediump> mediump_i8vec1; + + /// Medium precision 8 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i8, mediump> mediump_i8vec2; + + /// Medium precision 8 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i8, mediump> mediump_i8vec3; + + /// Medium precision 8 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i8, mediump> mediump_i8vec4; + + + /// High precision 8 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i8, highp> highp_i8vec1; + + /// High precision 8 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i8, highp> highp_i8vec2; + + /// High precision 8 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i8, highp> highp_i8vec3; + + /// High precision 8 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i8, highp> highp_i8vec4; + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_i8vec1 i8vec1; + typedef lowp_i8vec2 i8vec2; + typedef lowp_i8vec3 i8vec3; + typedef lowp_i8vec4 i8vec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef mediump_i8vec1 i8vec1; + typedef mediump_i8vec2 i8vec2; + typedef mediump_i8vec3 i8vec3; + typedef mediump_i8vec4 i8vec4; +#else + /// Default precision 8 bit signed integer scalar type. + /// @see gtc_type_precision + typedef highp_i8vec1 i8vec1; + + /// Default precision 8 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef highp_i8vec2 i8vec2; + + /// Default precision 8 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef highp_i8vec3 i8vec3; + + /// Default precision 8 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef highp_i8vec4 i8vec4; +#endif + + + /// Low precision 16 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i16, lowp> lowp_i16vec1; + + /// Low precision 16 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i16, lowp> lowp_i16vec2; + + /// Low precision 16 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i16, lowp> lowp_i16vec3; + + /// Low precision 16 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i16, lowp> lowp_i16vec4; + + + /// Medium precision 16 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i16, mediump> mediump_i16vec1; + + /// Medium precision 16 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i16, mediump> mediump_i16vec2; + + /// Medium precision 16 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i16, mediump> mediump_i16vec3; + + /// Medium precision 16 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i16, mediump> mediump_i16vec4; + + + /// High precision 16 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i16, highp> highp_i16vec1; + + /// High precision 16 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i16, highp> highp_i16vec2; + + /// High precision 16 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i16, highp> highp_i16vec3; + + /// High precision 16 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i16, highp> highp_i16vec4; + + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_i16vec1 i16vec1; + typedef lowp_i16vec2 i16vec2; + typedef lowp_i16vec3 i16vec3; + typedef lowp_i16vec4 i16vec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef mediump_i16vec1 i16vec1; + typedef mediump_i16vec2 i16vec2; + typedef mediump_i16vec3 i16vec3; + typedef mediump_i16vec4 i16vec4; +#else + /// Default precision 16 bit signed integer scalar type. + /// @see gtc_type_precision + typedef highp_i16vec1 i16vec1; + + /// Default precision 16 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef highp_i16vec2 i16vec2; + + /// Default precision 16 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef highp_i16vec3 i16vec3; + + /// Default precision 16 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef highp_i16vec4 i16vec4; +#endif + + + /// Low precision 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i32, lowp> lowp_i32vec1; + + /// Low precision 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i32, lowp> lowp_i32vec2; + + /// Low precision 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i32, lowp> lowp_i32vec3; + + /// Low precision 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i32, lowp> lowp_i32vec4; + + + /// Medium precision 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i32, mediump> mediump_i32vec1; + + /// Medium precision 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i32, mediump> mediump_i32vec2; + + /// Medium precision 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i32, mediump> mediump_i32vec3; + + /// Medium precision 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i32, mediump> mediump_i32vec4; + + + /// High precision 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i32, highp> highp_i32vec1; + + /// High precision 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i32, highp> highp_i32vec2; + + /// High precision 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i32, highp> highp_i32vec3; + + /// High precision 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i32, highp> highp_i32vec4; + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_i32vec1 i32vec1; + typedef lowp_i32vec2 i32vec2; + typedef lowp_i32vec3 i32vec3; + typedef lowp_i32vec4 i32vec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef mediump_i32vec1 i32vec1; + typedef mediump_i32vec2 i32vec2; + typedef mediump_i32vec3 i32vec3; + typedef mediump_i32vec4 i32vec4; +#else + /// Default precision 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef highp_i32vec1 i32vec1; + + /// Default precision 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef highp_i32vec2 i32vec2; + + /// Default precision 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef highp_i32vec3 i32vec3; + + /// Default precision 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef highp_i32vec4 i32vec4; +#endif + + + /// Low precision 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i32, lowp> lowp_i32vec1; + + /// Low precision 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i32, lowp> lowp_i32vec2; + + /// Low precision 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i32, lowp> lowp_i32vec3; + + /// Low precision 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i32, lowp> lowp_i32vec4; + + + /// Medium precision 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i32, mediump> mediump_i32vec1; + + /// Medium precision 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i32, mediump> mediump_i32vec2; + + /// Medium precision 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i32, mediump> mediump_i32vec3; + + /// Medium precision 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i32, mediump> mediump_i32vec4; + + + /// High precision 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i32, highp> highp_i32vec1; + + /// High precision 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i32, highp> highp_i32vec2; + + /// High precision 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i32, highp> highp_i32vec3; + + /// High precision 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i32, highp> highp_i32vec4; + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_i32vec1 i32vec1; + typedef lowp_i32vec2 i32vec2; + typedef lowp_i32vec3 i32vec3; + typedef lowp_i32vec4 i32vec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef mediump_i32vec1 i32vec1; + typedef mediump_i32vec2 i32vec2; + typedef mediump_i32vec3 i32vec3; + typedef mediump_i32vec4 i32vec4; +#else + /// Default precision 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef highp_i32vec1 i32vec1; + + /// Default precision 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef highp_i32vec2 i32vec2; + + /// Default precision 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef highp_i32vec3 i32vec3; + + /// Default precision 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef highp_i32vec4 i32vec4; +#endif + + + + /// Low precision 64 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i64, lowp> lowp_i64vec1; + + /// Low precision 64 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i64, lowp> lowp_i64vec2; + + /// Low precision 64 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i64, lowp> lowp_i64vec3; + + /// Low precision 64 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i64, lowp> lowp_i64vec4; + + + /// Medium precision 64 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i64, mediump> mediump_i64vec1; + + /// Medium precision 64 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i64, mediump> mediump_i64vec2; + + /// Medium precision 64 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i64, mediump> mediump_i64vec3; + + /// Medium precision 64 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i64, mediump> mediump_i64vec4; + + + /// High precision 64 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i64, highp> highp_i64vec1; + + /// High precision 64 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i64, highp> highp_i64vec2; + + /// High precision 64 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i64, highp> highp_i64vec3; + + /// High precision 64 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i64, highp> highp_i64vec4; + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_i64vec1 i64vec1; + typedef lowp_i64vec2 i64vec2; + typedef lowp_i64vec3 i64vec3; + typedef lowp_i64vec4 i64vec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef mediump_i64vec1 i64vec1; + typedef mediump_i64vec2 i64vec2; + typedef mediump_i64vec3 i64vec3; + typedef mediump_i64vec4 i64vec4; +#else + /// Default precision 64 bit signed integer scalar type. + /// @see gtc_type_precision + typedef highp_i64vec1 i64vec1; + + /// Default precision 64 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef highp_i64vec2 i64vec2; + + /// Default precision 64 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef highp_i64vec3 i64vec3; + + /// Default precision 64 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef highp_i64vec4 i64vec4; +#endif + + + ///////////////////////////// + // Unsigned int vector types + + /// Low precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_uint8; + + /// Low precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_uint16; + + /// Low precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_uint32; + + /// Low precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_uint64; + + + /// Low precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_uint8_t; + + /// Low precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_uint16_t; + + /// Low precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_uint32_t; + + /// Low precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_uint64_t; + + + /// Low precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_u8; + + /// Low precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_u16; + + /// Low precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_u32; + + /// Low precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_u64; + + + + /// Medium precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_uint8; + + /// Medium precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_uint16; + + /// Medium precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_uint32; + + /// Medium precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_uint64; + + /// Medium precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_uint8_t; + + /// Medium precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_uint16_t; + + /// Medium precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_uint32_t; + + /// Medium precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_uint64_t; + + /// Medium precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_u8; + + /// Medium precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_u16; + + /// Medium precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_u32; + + /// Medium precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_u64; + + + + /// Medium precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_uint8; + + /// Medium precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_uint16; + + /// Medium precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_uint32; + + /// Medium precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_uint64; + + /// Medium precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_uint8_t; + + /// Medium precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_uint16_t; + + /// Medium precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_uint32_t; + + /// Medium precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_uint64_t; + + /// Medium precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_u8; + + /// Medium precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_u16; + + /// Medium precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_u32; + + /// Medium precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_u64; + + + + /// 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 uint8; + + /// 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 uint16; + + /// 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 uint32; + + /// 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 uint64; + +#if GLM_HAS_EXTENDED_INTEGER_TYPE + using std::uint8_t; + using std::uint16_t; + using std::uint32_t; + using std::uint64_t; +#else + /// 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 uint8_t; + + /// 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 uint16_t; + + /// 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 uint32_t; + + /// 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 uint64_t; +#endif + + /// 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 u8; + + /// 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 u16; + + /// 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 u32; + + /// 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 u64; + + + + /// Low precision 8 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u8, lowp> lowp_u8vec1; + + /// Low precision 8 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u8, lowp> lowp_u8vec2; + + /// Low precision 8 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u8, lowp> lowp_u8vec3; + + /// Low precision 8 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u8, lowp> lowp_u8vec4; + + + /// Medium precision 8 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u8, mediump> mediump_u8vec1; + + /// Medium precision 8 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u8, mediump> mediump_u8vec2; + + /// Medium precision 8 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u8, mediump> mediump_u8vec3; + + /// Medium precision 8 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u8, mediump> mediump_u8vec4; + + + /// High precision 8 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u8, highp> highp_u8vec1; + + /// High precision 8 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u8, highp> highp_u8vec2; + + /// High precision 8 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u8, highp> highp_u8vec3; + + /// High precision 8 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u8, highp> highp_u8vec4; + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_u8vec1 u8vec1; + typedef lowp_u8vec2 u8vec2; + typedef lowp_u8vec3 u8vec3; + typedef lowp_u8vec4 u8vec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef mediump_u8vec1 u8vec1; + typedef mediump_u8vec2 u8vec2; + typedef mediump_u8vec3 u8vec3; + typedef mediump_u8vec4 u8vec4; +#else + /// Default precision 8 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef highp_u8vec1 u8vec1; + + /// Default precision 8 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef highp_u8vec2 u8vec2; + + /// Default precision 8 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef highp_u8vec3 u8vec3; + + /// Default precision 8 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef highp_u8vec4 u8vec4; +#endif + + + /// Low precision 16 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u16, lowp> lowp_u16vec1; + + /// Low precision 16 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u16, lowp> lowp_u16vec2; + + /// Low precision 16 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u16, lowp> lowp_u16vec3; + + /// Low precision 16 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u16, lowp> lowp_u16vec4; + + + /// Medium precision 16 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u16, mediump> mediump_u16vec1; + + /// Medium precision 16 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u16, mediump> mediump_u16vec2; + + /// Medium precision 16 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u16, mediump> mediump_u16vec3; + + /// Medium precision 16 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u16, mediump> mediump_u16vec4; + + + /// High precision 16 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u16, highp> highp_u16vec1; + + /// High precision 16 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u16, highp> highp_u16vec2; + + /// High precision 16 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u16, highp> highp_u16vec3; + + /// High precision 16 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u16, highp> highp_u16vec4; + + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_u16vec1 u16vec1; + typedef lowp_u16vec2 u16vec2; + typedef lowp_u16vec3 u16vec3; + typedef lowp_u16vec4 u16vec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef mediump_u16vec1 u16vec1; + typedef mediump_u16vec2 u16vec2; + typedef mediump_u16vec3 u16vec3; + typedef mediump_u16vec4 u16vec4; +#else + /// Default precision 16 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef highp_u16vec1 u16vec1; + + /// Default precision 16 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef highp_u16vec2 u16vec2; + + /// Default precision 16 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef highp_u16vec3 u16vec3; + + /// Default precision 16 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef highp_u16vec4 u16vec4; +#endif + + + /// Low precision 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u32, lowp> lowp_u32vec1; + + /// Low precision 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u32, lowp> lowp_u32vec2; + + /// Low precision 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u32, lowp> lowp_u32vec3; + + /// Low precision 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u32, lowp> lowp_u32vec4; + + + /// Medium precision 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u32, mediump> mediump_u32vec1; + + /// Medium precision 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u32, mediump> mediump_u32vec2; + + /// Medium precision 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u32, mediump> mediump_u32vec3; + + /// Medium precision 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u32, mediump> mediump_u32vec4; + + + /// High precision 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u32, highp> highp_u32vec1; + + /// High precision 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u32, highp> highp_u32vec2; + + /// High precision 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u32, highp> highp_u32vec3; + + /// High precision 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u32, highp> highp_u32vec4; + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_u32vec1 u32vec1; + typedef lowp_u32vec2 u32vec2; + typedef lowp_u32vec3 u32vec3; + typedef lowp_u32vec4 u32vec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef mediump_u32vec1 u32vec1; + typedef mediump_u32vec2 u32vec2; + typedef mediump_u32vec3 u32vec3; + typedef mediump_u32vec4 u32vec4; +#else + /// Default precision 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef highp_u32vec1 u32vec1; + + /// Default precision 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef highp_u32vec2 u32vec2; + + /// Default precision 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef highp_u32vec3 u32vec3; + + /// Default precision 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef highp_u32vec4 u32vec4; +#endif + + + /// Low precision 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u32, lowp> lowp_u32vec1; + + /// Low precision 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u32, lowp> lowp_u32vec2; + + /// Low precision 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u32, lowp> lowp_u32vec3; + + /// Low precision 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u32, lowp> lowp_u32vec4; + + + /// Medium precision 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u32, mediump> mediump_u32vec1; + + /// Medium precision 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u32, mediump> mediump_u32vec2; + + /// Medium precision 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u32, mediump> mediump_u32vec3; + + /// Medium precision 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u32, mediump> mediump_u32vec4; + + + /// High precision 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u32, highp> highp_u32vec1; + + /// High precision 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u32, highp> highp_u32vec2; + + /// High precision 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u32, highp> highp_u32vec3; + + /// High precision 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u32, highp> highp_u32vec4; + +#if(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_u32vec1 u32vec1; + typedef lowp_u32vec2 u32vec2; + typedef lowp_u32vec3 u32vec3; + typedef lowp_u32vec4 u32vec4; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef mediump_u32vec1 u32vec1; + typedef mediump_u32vec2 u32vec2; + typedef mediump_u32vec3 u32vec3; + typedef mediump_u32vec4 u32vec4; +#else + /// Default precision 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef highp_u32vec1 u32vec1; + + /// Default precision 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef highp_u32vec2 u32vec2; + + /// Default precision 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef highp_u32vec3 u32vec3; + + /// Default precision 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef highp_u32vec4 u32vec4; +#endif + + + + /// Low precision 64 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u64, lowp> lowp_u64vec1; + + /// Low precision 64 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u64, lowp> lowp_u64vec2; + + /// Low precision 64 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u64, lowp> lowp_u64vec3; + + /// Low precision 64 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u64, lowp> lowp_u64vec4; + + + /// Medium precision 64 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u64, mediump> mediump_u64vec1; + + /// Medium precision 64 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u64, mediump> mediump_u64vec2; + + /// Medium precision 64 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u64, mediump> mediump_u64vec3; + + /// Medium precision 64 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u64, mediump> mediump_u64vec4; + + + /// High precision 64 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u64, highp> highp_u64vec1; + + /// High precision 64 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u64, highp> highp_u64vec2; + + /// High precision 64 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u64, highp> highp_u64vec3; + + /// High precision 64 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u64, highp> highp_u64vec4; + +#if(defined(GLM_PRECISION_LOWP_UINT)) + typedef lowp_u64vec1 u64vec1; + typedef lowp_u64vec2 u64vec2; + typedef lowp_u64vec3 u64vec3; + typedef lowp_u64vec4 u64vec4; +#elif(defined(GLM_PRECISION_MEDIUMP_UINT)) + typedef mediump_u64vec1 u64vec1; + typedef mediump_u64vec2 u64vec2; + typedef mediump_u64vec3 u64vec3; + typedef mediump_u64vec4 u64vec4; +#else + /// Default precision 64 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef highp_u64vec1 u64vec1; + + /// Default precision 64 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef highp_u64vec2 u64vec2; + + /// Default precision 64 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef highp_u64vec3 u64vec3; + + /// Default precision 64 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef highp_u64vec4 u64vec4; +#endif + + + ////////////////////// + // Float vector types + + /// Low 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 lowp_float32; + + /// Low 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 lowp_float64; + + /// Low 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 lowp_float32_t; + + /// Low 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 lowp_float64_t; + + /// Low 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_f32; + + /// Low 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_f64; + + /// Low 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 lowp_float32; + + /// Low 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 lowp_float64; + + /// Low 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 lowp_float32_t; + + /// Low 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 lowp_float64_t; + + /// Low 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_f32; + + /// Low 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_f64; + + + /// Low 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 lowp_float32; + + /// Low 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 lowp_float64; + + /// Low 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 lowp_float32_t; + + /// Low 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 lowp_float64_t; + + /// Low 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef float32 lowp_f32; + + /// Low 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef float64 lowp_f64; + + + /// Medium 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 mediump_float32; + + /// Medium 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 mediump_float64; + + /// Medium 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 mediump_float32_t; + + /// Medium 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 mediump_float64_t; + + /// Medium 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef float32 mediump_f32; + + /// Medium 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef float64 mediump_f64; + + + /// High 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 highp_float32; + + /// High 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 highp_float64; + + /// High 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 highp_float32_t; + + /// High 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 highp_float64_t; + + /// High 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef float32 highp_f32; + + /// High 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef float64 highp_f64; + + +#if(defined(GLM_PRECISION_LOWP_FLOAT)) + /// Default 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef lowp_float32 float32; + + /// Default 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef lowp_float64 float64; + + /// Default 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef lowp_float32_t float32_t; + + /// Default 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef lowp_float64_t float64_t; + + /// Default 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef lowp_f32 f32; + + /// Default 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef lowp_f64 f64; + +#elif(defined(GLM_PRECISION_MEDIUMP_FLOAT)) + + /// Default 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float32 float32; + + /// Default 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float64 float64; + + /// Default 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float32 float32_t; + + /// Default 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float64 float64_t; + + /// Default 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float32 f32; + + /// Default 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef mediump_float64 f64; + +#else//(defined(GLM_PRECISION_HIGHP_FLOAT)) + + /// Default 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef highp_float32 float32; + + /// Default 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef highp_float64 float64; + + /// Default 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef highp_float32_t float32_t; + + /// Default 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef highp_float64_t float64_t; + + /// Default 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef highp_float32_t f32; + + /// Default 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef highp_float64_t f64; +#endif + + + /// Low single-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<float, lowp> lowp_vec1; + + /// Low single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<float, lowp> lowp_vec2; + + /// Low single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<float, lowp> lowp_vec3; + + /// Low single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<float, lowp> lowp_vec4; + + /// Low single-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<float, lowp> lowp_fvec1; + + /// Low single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<float, lowp> lowp_fvec2; + + /// Low single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<float, lowp> lowp_fvec3; + + /// Low single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<float, lowp> lowp_fvec4; + + + /// Medium single-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<float, mediump> mediump_vec1; + + /// Medium Single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<float, mediump> mediump_vec2; + + /// Medium Single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<float, mediump> mediump_vec3; + + /// Medium Single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<float, mediump> mediump_vec4; + + /// Medium single-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<float, mediump> mediump_fvec1; + + /// Medium Single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<float, mediump> mediump_fvec2; + + /// Medium Single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<float, mediump> mediump_fvec3; + + /// Medium Single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<float, mediump> mediump_fvec4; + + + /// High single-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<float, highp> highp_vec1; + + /// High Single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<float, highp> highp_vec2; + + /// High Single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<float, highp> highp_vec3; + + /// High Single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<float, highp> highp_vec4; + + /// High single-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<float, highp> highp_fvec1; + + /// High Single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<float, highp> highp_fvec2; + + /// High Single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<float, highp> highp_fvec3; + + /// High Single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<float, highp> highp_fvec4; + + + /// Low single-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<f32, lowp> lowp_f32vec1; + + /// Low single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<f32, lowp> lowp_f32vec2; + + /// Low single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<f32, lowp> lowp_f32vec3; + + /// Low single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<f32, lowp> lowp_f32vec4; + + /// Medium single-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<f32, mediump> mediump_f32vec1; + + /// Medium single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<f32, mediump> mediump_f32vec2; + + /// Medium single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<f32, mediump> mediump_f32vec3; + + /// Medium single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<f32, mediump> mediump_f32vec4; + + /// High single-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<f32, highp> highp_f32vec1; + + /// High single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<f32, highp> highp_f32vec2; + + /// High single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<f32, highp> highp_f32vec3; + + /// High single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<f32, highp> highp_f32vec4; + + + /// Low double-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<f64, lowp> lowp_f64vec1; + + /// Low double-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<f64, lowp> lowp_f64vec2; + + /// Low double-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<f64, lowp> lowp_f64vec3; + + /// Low double-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<f64, lowp> lowp_f64vec4; + + /// Medium double-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<f64, mediump> mediump_f64vec1; + + /// Medium double-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<f64, mediump> mediump_f64vec2; + + /// Medium double-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<f64, mediump> mediump_f64vec3; + + /// Medium double-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<f64, mediump> mediump_f64vec4; + + /// High double-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<f64, highp> highp_f64vec1; + + /// High double-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<f64, highp> highp_f64vec2; + + /// High double-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<f64, highp> highp_f64vec3; + + /// High double-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<f64, highp> highp_f64vec4; + + + ////////////////////// + // Float matrix types + + /// Low single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef lowp_f32 lowp_fmat1x1; + + /// Low single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f32, lowp> lowp_fmat2x2; + + /// Low single-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f32, lowp> lowp_fmat2x3; + + /// Low single-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f32, lowp> lowp_fmat2x4; + + /// Low single-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f32, lowp> lowp_fmat3x2; + + /// Low single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f32, lowp> lowp_fmat3x3; + + /// Low single-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f32, lowp> lowp_fmat3x4; + + /// Low single-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f32, lowp> lowp_fmat4x2; + + /// Low single-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f32, lowp> lowp_fmat4x3; + + /// Low single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f32, lowp> lowp_fmat4x4; + + /// Low single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef lowp_fmat1x1 lowp_fmat1; + + /// Low single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef lowp_fmat2x2 lowp_fmat2; + + /// Low single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef lowp_fmat3x3 lowp_fmat3; + + /// Low single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef lowp_fmat4x4 lowp_fmat4; + + + /// Medium single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef mediump_f32 mediump_fmat1x1; + + /// Medium single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f32, mediump> mediump_fmat2x2; + + /// Medium single-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f32, mediump> mediump_fmat2x3; + + /// Medium single-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f32, mediump> mediump_fmat2x4; + + /// Medium single-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f32, mediump> mediump_fmat3x2; + + /// Medium single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f32, mediump> mediump_fmat3x3; + + /// Medium single-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f32, mediump> mediump_fmat3x4; + + /// Medium single-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f32, mediump> mediump_fmat4x2; + + /// Medium single-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f32, mediump> mediump_fmat4x3; + + /// Medium single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f32, mediump> mediump_fmat4x4; + + /// Medium single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef mediump_fmat1x1 mediump_fmat1; + + /// Medium single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mediump_fmat2x2 mediump_fmat2; + + /// Medium single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mediump_fmat3x3 mediump_fmat3; + + /// Medium single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mediump_fmat4x4 mediump_fmat4; + + + /// High single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef highp_f32 highp_fmat1x1; + + /// High single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f32, highp> highp_fmat2x2; + + /// High single-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f32, highp> highp_fmat2x3; + + /// High single-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f32, highp> highp_fmat2x4; + + /// High single-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f32, highp> highp_fmat3x2; + + /// High single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f32, highp> highp_fmat3x3; + + /// High single-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f32, highp> highp_fmat3x4; + + /// High single-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f32, highp> highp_fmat4x2; + + /// High single-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f32, highp> highp_fmat4x3; + + /// High single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f32, highp> highp_fmat4x4; + + /// High single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef highp_fmat1x1 highp_fmat1; + + /// High single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_fmat2x2 highp_fmat2; + + /// High single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_fmat3x3 highp_fmat3; + + /// High single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_fmat4x4 highp_fmat4; + + + /// Low single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 lowp_f32mat1x1; + + /// Low single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f32, lowp> lowp_f32mat2x2; + + /// Low single-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f32, lowp> lowp_f32mat2x3; + + /// Low single-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f32, lowp> lowp_f32mat2x4; + + /// Low single-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f32, lowp> lowp_f32mat3x2; + + /// Low single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f32, lowp> lowp_f32mat3x3; + + /// Low single-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f32, lowp> lowp_f32mat3x4; + + /// Low single-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f32, lowp> lowp_f32mat4x2; + + /// Low single-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f32, lowp> lowp_f32mat4x3; + + /// Low single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f32, lowp> lowp_f32mat4x4; + + /// Low single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1<f32, lowp> lowp_f32mat1; + + /// Low single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef lowp_f32mat2x2 lowp_f32mat2; + + /// Low single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef lowp_f32mat3x3 lowp_f32mat3; + + /// Low single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef lowp_f32mat4x4 lowp_f32mat4; + + + /// High single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 mediump_f32mat1x1; + + /// Low single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f32, mediump> mediump_f32mat2x2; + + /// Medium single-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f32, mediump> mediump_f32mat2x3; + + /// Medium single-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f32, mediump> mediump_f32mat2x4; + + /// Medium single-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f32, mediump> mediump_f32mat3x2; + + /// Medium single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f32, mediump> mediump_f32mat3x3; + + /// Medium single-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f32, mediump> mediump_f32mat3x4; + + /// Medium single-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f32, mediump> mediump_f32mat4x2; + + /// Medium single-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f32, mediump> mediump_f32mat4x3; + + /// Medium single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f32, mediump> mediump_f32mat4x4; + + /// Medium single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1<f32, mediump> f32mat1; + + /// Medium single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mediump_f32mat2x2 mediump_f32mat2; + + /// Medium single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mediump_f32mat3x3 mediump_f32mat3; + + /// Medium single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mediump_f32mat4x4 mediump_f32mat4; + + + /// High single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 highp_f32mat1x1; + + /// High single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f32, highp> highp_f32mat2x2; + + /// High single-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f32, highp> highp_f32mat2x3; + + /// High single-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f32, highp> highp_f32mat2x4; + + /// High single-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f32, highp> highp_f32mat3x2; + + /// High single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f32, highp> highp_f32mat3x3; + + /// High single-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f32, highp> highp_f32mat3x4; + + /// High single-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f32, highp> highp_f32mat4x2; + + /// High single-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f32, highp> highp_f32mat4x3; + + /// High single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f32, highp> highp_f32mat4x4; + + /// High single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1<f32, highp> f32mat1; + + /// High single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_f32mat2x2 highp_f32mat2; + + /// High single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_f32mat3x3 highp_f32mat3; + + /// High single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_f32mat4x4 highp_f32mat4; + + + /// Low double-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 lowp_f64mat1x1; + + /// Low double-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f64, lowp> lowp_f64mat2x2; + + /// Low double-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f64, lowp> lowp_f64mat2x3; + + /// Low double-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f64, lowp> lowp_f64mat2x4; + + /// Low double-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f64, lowp> lowp_f64mat3x2; + + /// Low double-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f64, lowp> lowp_f64mat3x3; + + /// Low double-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f64, lowp> lowp_f64mat3x4; + + /// Low double-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f64, lowp> lowp_f64mat4x2; + + /// Low double-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f64, lowp> lowp_f64mat4x3; + + /// Low double-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f64, lowp> lowp_f64mat4x4; + + /// Low double-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef lowp_f64mat1x1 lowp_f64mat1; + + /// Low double-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef lowp_f64mat2x2 lowp_f64mat2; + + /// Low double-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef lowp_f64mat3x3 lowp_f64mat3; + + /// Low double-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef lowp_f64mat4x4 lowp_f64mat4; + + + /// Medium double-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 Highp_f64mat1x1; + + /// Medium double-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f64, mediump> mediump_f64mat2x2; + + /// Medium double-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f64, mediump> mediump_f64mat2x3; + + /// Medium double-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f64, mediump> mediump_f64mat2x4; + + /// Medium double-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f64, mediump> mediump_f64mat3x2; + + /// Medium double-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f64, mediump> mediump_f64mat3x3; + + /// Medium double-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f64, mediump> mediump_f64mat3x4; + + /// Medium double-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f64, mediump> mediump_f64mat4x2; + + /// Medium double-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f64, mediump> mediump_f64mat4x3; + + /// Medium double-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f64, mediump> mediump_f64mat4x4; + + /// Medium double-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef mediump_f64mat1x1 mediump_f64mat1; + + /// Medium double-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef mediump_f64mat2x2 mediump_f64mat2; + + /// Medium double-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef mediump_f64mat3x3 mediump_f64mat3; + + /// Medium double-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef mediump_f64mat4x4 mediump_f64mat4; + + /// High double-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 highp_f64mat1x1; + + /// High double-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f64, highp> highp_f64mat2x2; + + /// High double-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f64, highp> highp_f64mat2x3; + + /// High double-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f64, highp> highp_f64mat2x4; + + /// High double-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f64, highp> highp_f64mat3x2; + + /// High double-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f64, highp> highp_f64mat3x3; + + /// High double-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f64, highp> highp_f64mat3x4; + + /// High double-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f64, highp> highp_f64mat4x2; + + /// High double-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f64, highp> highp_f64mat4x3; + + /// High double-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f64, highp> highp_f64mat4x4; + + /// High double-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef highp_f64mat1x1 highp_f64mat1; + + /// High double-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_f64mat2x2 highp_f64mat2; + + /// High double-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_f64mat3x3 highp_f64mat3; + + /// High double-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_f64mat4x4 highp_f64mat4; + + ////////////////////////// + // Quaternion types + + /// Low single-precision floating-point quaternion. + /// @see gtc_type_precision + typedef tquat<f32, lowp> lowp_f32quat; + + /// Low double-precision floating-point quaternion. + /// @see gtc_type_precision + typedef tquat<f64, lowp> lowp_f64quat; + + /// Medium single-precision floating-point quaternion. + /// @see gtc_type_precision + typedef tquat<f32, mediump> mediump_f32quat; + + /// Medium double-precision floating-point quaternion. + /// @see gtc_type_precision + typedef tquat<f64, mediump> mediump_f64quat; + + /// High single-precision floating-point quaternion. + /// @see gtc_type_precision + typedef tquat<f32, highp> highp_f32quat; + + /// High double-precision floating-point quaternion. + /// @see gtc_type_precision + typedef tquat<f64, highp> highp_f64quat; + + +#if(defined(GLM_PRECISION_LOWP_FLOAT)) + typedef lowp_f32vec1 fvec1; + typedef lowp_f32vec2 fvec2; + typedef lowp_f32vec3 fvec3; + typedef lowp_f32vec4 fvec4; + typedef lowp_f32mat2 fmat2; + typedef lowp_f32mat3 fmat3; + typedef lowp_f32mat4 fmat4; + typedef lowp_f32mat2x2 fmat2x2; + typedef lowp_f32mat3x2 fmat3x2; + typedef lowp_f32mat4x2 fmat4x2; + typedef lowp_f32mat2x3 fmat2x3; + typedef lowp_f32mat3x3 fmat3x3; + typedef lowp_f32mat4x3 fmat4x3; + typedef lowp_f32mat2x4 fmat2x4; + typedef lowp_f32mat3x4 fmat3x4; + typedef lowp_f32mat4x4 fmat4x4; + typedef lowp_f32quat fquat; + + typedef lowp_f32vec1 f32vec1; + typedef lowp_f32vec2 f32vec2; + typedef lowp_f32vec3 f32vec3; + typedef lowp_f32vec4 f32vec4; + typedef lowp_f32mat2 f32mat2; + typedef lowp_f32mat3 f32mat3; + typedef lowp_f32mat4 f32mat4; + typedef lowp_f32mat2x2 f32mat2x2; + typedef lowp_f32mat3x2 f32mat3x2; + typedef lowp_f32mat4x2 f32mat4x2; + typedef lowp_f32mat2x3 f32mat2x3; + typedef lowp_f32mat3x3 f32mat3x3; + typedef lowp_f32mat4x3 f32mat4x3; + typedef lowp_f32mat2x4 f32mat2x4; + typedef lowp_f32mat3x4 f32mat3x4; + typedef lowp_f32mat4x4 f32mat4x4; + typedef lowp_f32quat f32quat; +#elif(defined(GLM_PRECISION_MEDIUMP_FLOAT)) + typedef mediump_f32vec1 fvec1; + typedef mediump_f32vec2 fvec2; + typedef mediump_f32vec3 fvec3; + typedef mediump_f32vec4 fvec4; + typedef mediump_f32mat2 fmat2; + typedef mediump_f32mat3 fmat3; + typedef mediump_f32mat4 fmat4; + typedef mediump_f32mat2x2 fmat2x2; + typedef mediump_f32mat3x2 fmat3x2; + typedef mediump_f32mat4x2 fmat4x2; + typedef mediump_f32mat2x3 fmat2x3; + typedef mediump_f32mat3x3 fmat3x3; + typedef mediump_f32mat4x3 fmat4x3; + typedef mediump_f32mat2x4 fmat2x4; + typedef mediump_f32mat3x4 fmat3x4; + typedef mediump_f32mat4x4 fmat4x4; + typedef mediump_f32quat fquat; + + typedef mediump_f32vec1 f32vec1; + typedef mediump_f32vec2 f32vec2; + typedef mediump_f32vec3 f32vec3; + typedef mediump_f32vec4 f32vec4; + typedef mediump_f32mat2 f32mat2; + typedef mediump_f32mat3 f32mat3; + typedef mediump_f32mat4 f32mat4; + typedef mediump_f32mat2x2 f32mat2x2; + typedef mediump_f32mat3x2 f32mat3x2; + typedef mediump_f32mat4x2 f32mat4x2; + typedef mediump_f32mat2x3 f32mat2x3; + typedef mediump_f32mat3x3 f32mat3x3; + typedef mediump_f32mat4x3 f32mat4x3; + typedef mediump_f32mat2x4 f32mat2x4; + typedef mediump_f32mat3x4 f32mat3x4; + typedef mediump_f32mat4x4 f32mat4x4; + typedef mediump_f32quat f32quat; +#else//if(defined(GLM_PRECISION_HIGHP_FLOAT)) + /// Default single-precision floating-point vector of 1 components. + /// @see gtc_type_precision + typedef highp_f32vec1 fvec1; + + /// Default single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef highp_f32vec2 fvec2; + + /// Default single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef highp_f32vec3 fvec3; + + /// Default single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef highp_f32vec4 fvec4; + + /// Default single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_f32mat2x2 fmat2x2; + + /// Default single-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef highp_f32mat2x3 fmat2x3; + + /// Default single-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef highp_f32mat2x4 fmat2x4; + + /// Default single-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef highp_f32mat3x2 fmat3x2; + + /// Default single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_f32mat3x3 fmat3x3; + + /// Default single-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef highp_f32mat3x4 fmat3x4; + + /// Default single-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef highp_f32mat4x2 fmat4x2; + + /// Default single-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef highp_f32mat4x3 fmat4x3; + + /// Default single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_f32mat4x4 fmat4x4; + + /// Default single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef fmat2x2 fmat2; + + /// Default single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef fmat3x3 fmat3; + + /// Default single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef fmat4x4 fmat4; + + /// Default single-precision floating-point quaternion. + /// @see gtc_type_precision + typedef highp_fquat fquat; + + + + /// Default single-precision floating-point vector of 1 components. + /// @see gtc_type_precision + typedef highp_f32vec1 f32vec1; + + /// Default single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef highp_f32vec2 f32vec2; + + /// Default single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef highp_f32vec3 f32vec3; + + /// Default single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef highp_f32vec4 f32vec4; + + /// Default single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_f32mat2x2 f32mat2x2; + + /// Default single-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef highp_f32mat2x3 f32mat2x3; + + /// Default single-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef highp_f32mat2x4 f32mat2x4; + + /// Default single-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef highp_f32mat3x2 f32mat3x2; + + /// Default single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_f32mat3x3 f32mat3x3; + + /// Default single-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef highp_f32mat3x4 f32mat3x4; + + /// Default single-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef highp_f32mat4x2 f32mat4x2; + + /// Default single-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef highp_f32mat4x3 f32mat4x3; + + /// Default single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_f32mat4x4 f32mat4x4; + + /// Default single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef f32mat2x2 f32mat2; + + /// Default single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef f32mat3x3 f32mat3; + + /// Default single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef f32mat4x4 f32mat4; + + /// Default single-precision floating-point quaternion. + /// @see gtc_type_precision + typedef highp_f32quat f32quat; +#endif + +#if(defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef lowp_f64vec1 f64vec1; + typedef lowp_f64vec2 f64vec2; + typedef lowp_f64vec3 f64vec3; + typedef lowp_f64vec4 f64vec4; + typedef lowp_f64mat2 f64mat2; + typedef lowp_f64mat3 f64mat3; + typedef lowp_f64mat4 f64mat4; + typedef lowp_f64mat2x2 f64mat2x2; + typedef lowp_f64mat3x2 f64mat3x2; + typedef lowp_f64mat4x2 f64mat4x2; + typedef lowp_f64mat2x3 f64mat2x3; + typedef lowp_f64mat3x3 f64mat3x3; + typedef lowp_f64mat4x3 f64mat4x3; + typedef lowp_f64mat2x4 f64mat2x4; + typedef lowp_f64mat3x4 f64mat3x4; + typedef lowp_f64mat4x4 f64mat4x4; + typedef lowp_f64quat f64quat; +#elif(defined(GLM_PRECISION_MEDIUMP_DOUBLE)) + typedef mediump_f64vec1 f64vec1; + typedef mediump_f64vec2 f64vec2; + typedef mediump_f64vec3 f64vec3; + typedef mediump_f64vec4 f64vec4; + typedef mediump_f64mat2 f64mat2; + typedef mediump_f64mat3 f64mat3; + typedef mediump_f64mat4 f64mat4; + typedef mediump_f64mat2x2 f64mat2x2; + typedef mediump_f64mat3x2 f64mat3x2; + typedef mediump_f64mat4x2 f64mat4x2; + typedef mediump_f64mat2x3 f64mat2x3; + typedef mediump_f64mat3x3 f64mat3x3; + typedef mediump_f64mat4x3 f64mat4x3; + typedef mediump_f64mat2x4 f64mat2x4; + typedef mediump_f64mat3x4 f64mat3x4; + typedef mediump_f64mat4x4 f64mat4x4; + typedef mediump_f64quat f64quat; +#else + /// Default double-precision floating-point vector of 1 components. + /// @see gtc_type_precision + typedef highp_f64vec1 f64vec1; + + /// Default double-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef highp_f64vec2 f64vec2; + + /// Default double-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef highp_f64vec3 f64vec3; + + /// Default double-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef highp_f64vec4 f64vec4; + + /// Default double-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef highp_f64mat2x2 f64mat2x2; + + /// Default double-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef highp_f64mat2x3 f64mat2x3; + + /// Default double-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef highp_f64mat2x4 f64mat2x4; + + /// Default double-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef highp_f64mat3x2 f64mat3x2; + + /// Default double-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef highp_f64mat3x3 f64mat3x3; + + /// Default double-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef highp_f64mat3x4 f64mat3x4; + + /// Default double-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef highp_f64mat4x2 f64mat4x2; + + /// Default double-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef highp_f64mat4x3 f64mat4x3; + + /// Default double-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef highp_f64mat4x4 f64mat4x4; + + /// Default double-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef f64mat2x2 f64mat2; + + /// Default double-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef f64mat3x3 f64mat3; + + /// Default double-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef f64mat4x4 f64mat4; + + /// Default double-precision floating-point quaternion. + /// @see gtc_type_precision + typedef highp_f64quat f64quat; +#endif +}//namespace glm diff --git a/extensions/common/glm/geometric.hpp b/extensions/common/glm/geometric.hpp new file mode 100644 index 0000000000..8e9ee798b7 --- /dev/null +++ b/extensions/common/glm/geometric.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/geometric.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/func_geometric.hpp" diff --git a/extensions/common/glm/glm.hpp b/extensions/common/glm/glm.hpp new file mode 100644 index 0000000000..82f295c24f --- /dev/null +++ b/extensions/common/glm/glm.hpp @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/glm.hpp +/// @date 2005-01-14 / 2011-10-24 +/// @author Christophe Riccio +/// +/// @defgroup core GLM Core +/// +/// @brief The core of GLM, which implements exactly and only the GLSL specification to the degree possible. +/// +/// The GLM core consists of @ref core_types "C++ types that mirror GLSL types" and +/// C++ functions that mirror the GLSL functions. It also includes +/// @ref core_precision "a set of precision-based types" that can be used in the appropriate +/// functions. The C++ types are all based on a basic set of @ref core_template "template types". +/// +/// The best documentation for GLM Core is the current GLSL specification, +/// <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.clean.pdf">version 4.2 +/// (pdf file)</a>. +/// +/// GLM core functionnalities require <glm/glm.hpp> to be included to be used. +/// +/// @defgroup core_types Types +/// +/// @brief The standard types defined by the specification. +/// +/// These types are all typedefs of more generalized, template types. To see the definiton +/// of these template types, go to @ref core_template. +/// +/// @ingroup core +/// +/// @defgroup core_precision Precision types +/// +/// @brief Non-GLSL types that are used to define precision-based types. +/// +/// The GLSL language allows the user to define the precision of a particular variable. +/// In OpenGL's GLSL, these precision qualifiers have no effect; they are there for compatibility +/// with OpenGL ES's precision qualifiers, where they @em do have an effect. +/// +/// C++ has no language equivalent to precision qualifiers. So GLM provides the next-best thing: +/// a number of typedefs of the @ref core_template that use a particular precision. +/// +/// None of these types make any guarantees about the actual precision used. +/// +/// @ingroup core +/// +/// @defgroup core_template Template types +/// +/// @brief The generic template types used as the basis for the core types. +/// +/// These types are all templates used to define the actual @ref core_types. +/// These templetes are implementation details of GLM types and should not be used explicitly. +/// +/// @ingroup core +/////////////////////////////////////////////////////////////////////////////////// + +#include "detail/_fixes.hpp" + +#pragma once + +#include <cmath> +#include <climits> +#include <cfloat> +#include <limits> +#include <cassert> +#include "fwd.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_MESSAGE_CORE_INCLUDED_DISPLAYED)) +# define GLM_MESSAGE_CORE_INCLUDED_DISPLAYED +# pragma message("GLM: Core library included") +#endif//GLM_MESSAGE + +#include "vec2.hpp" +#include "vec3.hpp" +#include "vec4.hpp" +#include "mat2x2.hpp" +#include "mat2x3.hpp" +#include "mat2x4.hpp" +#include "mat3x2.hpp" +#include "mat3x3.hpp" +#include "mat3x4.hpp" +#include "mat4x2.hpp" +#include "mat4x3.hpp" +#include "mat4x4.hpp" + +#include "trigonometric.hpp" +#include "exponential.hpp" +#include "common.hpp" +#include "packing.hpp" +#include "geometric.hpp" +#include "matrix.hpp" +#include "vector_relational.hpp" +#include "integer.hpp" diff --git a/extensions/common/glm/gtc/bitfield.hpp b/extensions/common/glm/gtc/bitfield.hpp new file mode 100644 index 0000000000..54d5cb567e --- /dev/null +++ b/extensions/common/glm/gtc/bitfield.hpp @@ -0,0 +1,236 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_bitfield +/// @file glm/gtc/bitfield.hpp +/// @date 2014-10-25 / 2014-10-25 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_bitfield (dependence) +/// +/// @defgroup gtc_bitfield GLM_GTC_bitfield +/// @ingroup gtc +/// +/// @brief Allow to perform bit operations on integer values +/// +/// <glm/gtc/bitfield.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/precision.hpp" +#include "../detail/type_int.hpp" +#include "../detail/_vectorize.hpp" +#include <limits> + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_bitfield extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_bitfield + /// @{ + + /// Build a mask of 'count' bits + /// + /// @see gtc_bitfield + template <typename genIUType> + GLM_FUNC_DECL genIUType mask(genIUType Bits); + + /// Build a mask of 'count' bits + /// + /// @see gtc_bitfield + template <typename T, precision P, template <typename, precision> class vecIUType> + GLM_FUNC_DECL vecIUType<T, P> mask(vecIUType<T, P> const & v); + + /// Rotate all bits to the right. All the bits dropped in the right side are inserted back on the left side. + /// + /// @see gtc_bitfield + template <typename genIUType> + GLM_FUNC_DECL genIUType bitfieldRotateRight(genIUType In, int Shift); + + /// Rotate all bits to the right. All the bits dropped in the right side are inserted back on the left side. + /// + /// @see gtc_bitfield + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> bitfieldRotateRight(vecType<T, P> const & In, int Shift); + + /// Rotate all bits to the left. All the bits dropped in the left side are inserted back on the right side. + /// + /// @see gtc_bitfield + template <typename genIUType> + GLM_FUNC_DECL genIUType bitfieldRotateLeft(genIUType In, int Shift); + + /// Rotate all bits to the left. All the bits dropped in the left side are inserted back on the right side. + /// + /// @see gtc_bitfield + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> bitfieldRotateLeft(vecType<T, P> const & In, int Shift); + + /// Set to 1 a range of bits. + /// + /// @see gtc_bitfield + template <typename genIUType> + GLM_FUNC_DECL genIUType bitfieldFillOne(genIUType Value, int FirstBit, int BitCount); + + /// Set to 1 a range of bits. + /// + /// @see gtc_bitfield + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> bitfieldFillOne(vecType<T, P> const & Value, int FirstBit, int BitCount); + + /// Set to 0 a range of bits. + /// + /// @see gtc_bitfield + template <typename genIUType> + GLM_FUNC_DECL genIUType bitfieldFillZero(genIUType Value, int FirstBit, int BitCount); + + /// Set to 0 a range of bits. + /// + /// @see gtc_bitfield + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> bitfieldFillZero(vecType<T, P> const & Value, int FirstBit, int BitCount); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int16 bitfieldInterleave(int8 x, int8 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint16 bitfieldInterleave(uint8 x, uint8 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int32 bitfieldInterleave(int16 x, int16 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint32 bitfieldInterleave(uint16 x, uint16 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int32 x, int32 y); + + /// Interleaves the bits of x and y. + /// The first bit is the first bit of x followed by the first bit of y. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint32 x, uint32 y); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int32 bitfieldInterleave(int8 x, int8 y, int8 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int16 x, int16 y, int16 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int32 x, int32 y, int32 z); + + /// Interleaves the bits of x, y and z. + /// The first bit is the first bit of x followed by the first bit of y and the first bit of z. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint32 x, uint32 y, uint32 z); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int32 bitfieldInterleave(int8 x, int8 y, int8 z, int8 w); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z, uint8 w); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL int64 bitfieldInterleave(int16 x, int16 y, int16 z, int16 w); + + /// Interleaves the bits of x, y, z and w. + /// The first bit is the first bit of x followed by the first bit of y, the first bit of z and finally the first bit of w. + /// The other bits are interleaved following the previous sequence. + /// + /// @see gtc_bitfield + GLM_FUNC_DECL uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z, uint16 w); + + /// @} +} //namespace glm + +#include "bitfield.inl" diff --git a/extensions/common/glm/gtc/bitfield.inl b/extensions/common/glm/gtc/bitfield.inl new file mode 100644 index 0000000000..ddd8fc00b9 --- /dev/null +++ b/extensions/common/glm/gtc/bitfield.inl @@ -0,0 +1,542 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_bitfield +/// @file glm/gtc/bitfield.inl +/// @date 2011-10-14 / 2012-01-25 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail +{ + template <typename PARAM, typename RET> + GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y); + + template <typename PARAM, typename RET> + GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y, PARAM z); + + template <typename PARAM, typename RET> + GLM_FUNC_DECL RET bitfieldInterleave(PARAM x, PARAM y, PARAM z, PARAM w); + + template <> + GLM_FUNC_QUALIFIER glm::uint16 bitfieldInterleave(glm::uint8 x, glm::uint8 y) + { + glm::uint16 REG1(x); + glm::uint16 REG2(y); + + REG1 = ((REG1 << 4) | REG1) & glm::uint16(0x0F0F); + REG2 = ((REG2 << 4) | REG2) & glm::uint16(0x0F0F); + + REG1 = ((REG1 << 2) | REG1) & glm::uint16(0x3333); + REG2 = ((REG2 << 2) | REG2) & glm::uint16(0x3333); + + REG1 = ((REG1 << 1) | REG1) & glm::uint16(0x5555); + REG2 = ((REG2 << 1) | REG2) & glm::uint16(0x5555); + + return REG1 | (REG2 << 1); + } + + template <> + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint16 x, glm::uint16 y) + { + glm::uint32 REG1(x); + glm::uint32 REG2(y); + + REG1 = ((REG1 << 8) | REG1) & glm::uint32(0x00FF00FF); + REG2 = ((REG2 << 8) | REG2) & glm::uint32(0x00FF00FF); + + REG1 = ((REG1 << 4) | REG1) & glm::uint32(0x0F0F0F0F); + REG2 = ((REG2 << 4) | REG2) & glm::uint32(0x0F0F0F0F); + + REG1 = ((REG1 << 2) | REG1) & glm::uint32(0x33333333); + REG2 = ((REG2 << 2) | REG2) & glm::uint32(0x33333333); + + REG1 = ((REG1 << 1) | REG1) & glm::uint32(0x55555555); + REG2 = ((REG2 << 1) | REG2) & glm::uint32(0x55555555); + + return REG1 | (REG2 << 1); + } + + template <> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint32 x, glm::uint32 y) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + + REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x0000FFFF0000FFFF); + REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x0000FFFF0000FFFF); + + REG1 = ((REG1 << 8) | REG1) & glm::uint64(0x00FF00FF00FF00FF); + REG2 = ((REG2 << 8) | REG2) & glm::uint64(0x00FF00FF00FF00FF); + + REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x0F0F0F0F0F0F0F0F); + REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x0F0F0F0F0F0F0F0F); + + REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x3333333333333333); + REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x3333333333333333); + + REG1 = ((REG1 << 1) | REG1) & glm::uint64(0x5555555555555555); + REG2 = ((REG2 << 1) | REG2) & glm::uint64(0x5555555555555555); + + return REG1 | (REG2 << 1); + } + + template <> + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint8 x, glm::uint8 y, glm::uint8 z) + { + glm::uint32 REG1(x); + glm::uint32 REG2(y); + glm::uint32 REG3(z); + + REG1 = ((REG1 << 16) | REG1) & glm::uint32(0x00FF0000FF0000FF); + REG2 = ((REG2 << 16) | REG2) & glm::uint32(0x00FF0000FF0000FF); + REG3 = ((REG3 << 16) | REG3) & glm::uint32(0x00FF0000FF0000FF); + + REG1 = ((REG1 << 8) | REG1) & glm::uint32(0xF00F00F00F00F00F); + REG2 = ((REG2 << 8) | REG2) & glm::uint32(0xF00F00F00F00F00F); + REG3 = ((REG3 << 8) | REG3) & glm::uint32(0xF00F00F00F00F00F); + + REG1 = ((REG1 << 4) | REG1) & glm::uint32(0x30C30C30C30C30C3); + REG2 = ((REG2 << 4) | REG2) & glm::uint32(0x30C30C30C30C30C3); + REG3 = ((REG3 << 4) | REG3) & glm::uint32(0x30C30C30C30C30C3); + + REG1 = ((REG1 << 2) | REG1) & glm::uint32(0x9249249249249249); + REG2 = ((REG2 << 2) | REG2) & glm::uint32(0x9249249249249249); + REG3 = ((REG3 << 2) | REG3) & glm::uint32(0x9249249249249249); + + return REG1 | (REG2 << 1) | (REG3 << 2); + } + + template <> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint16 x, glm::uint16 y, glm::uint16 z) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + glm::uint64 REG3(z); + + REG1 = ((REG1 << 32) | REG1) & glm::uint64(0xFFFF00000000FFFF); + REG2 = ((REG2 << 32) | REG2) & glm::uint64(0xFFFF00000000FFFF); + REG3 = ((REG3 << 32) | REG3) & glm::uint64(0xFFFF00000000FFFF); + + REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x00FF0000FF0000FF); + REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x00FF0000FF0000FF); + REG3 = ((REG3 << 16) | REG3) & glm::uint64(0x00FF0000FF0000FF); + + REG1 = ((REG1 << 8) | REG1) & glm::uint64(0xF00F00F00F00F00F); + REG2 = ((REG2 << 8) | REG2) & glm::uint64(0xF00F00F00F00F00F); + REG3 = ((REG3 << 8) | REG3) & glm::uint64(0xF00F00F00F00F00F); + + REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x30C30C30C30C30C3); + REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x30C30C30C30C30C3); + REG3 = ((REG3 << 4) | REG3) & glm::uint64(0x30C30C30C30C30C3); + + REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x9249249249249249); + REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x9249249249249249); + REG3 = ((REG3 << 2) | REG3) & glm::uint64(0x9249249249249249); + + return REG1 | (REG2 << 1) | (REG3 << 2); + } + + template <> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint32 x, glm::uint32 y, glm::uint32 z) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + glm::uint64 REG3(z); + + REG1 = ((REG1 << 32) | REG1) & glm::uint64(0xFFFF00000000FFFF); + REG2 = ((REG2 << 32) | REG2) & glm::uint64(0xFFFF00000000FFFF); + REG3 = ((REG3 << 32) | REG3) & glm::uint64(0xFFFF00000000FFFF); + + REG1 = ((REG1 << 16) | REG1) & glm::uint64(0x00FF0000FF0000FF); + REG2 = ((REG2 << 16) | REG2) & glm::uint64(0x00FF0000FF0000FF); + REG3 = ((REG3 << 16) | REG3) & glm::uint64(0x00FF0000FF0000FF); + + REG1 = ((REG1 << 8) | REG1) & glm::uint64(0xF00F00F00F00F00F); + REG2 = ((REG2 << 8) | REG2) & glm::uint64(0xF00F00F00F00F00F); + REG3 = ((REG3 << 8) | REG3) & glm::uint64(0xF00F00F00F00F00F); + + REG1 = ((REG1 << 4) | REG1) & glm::uint64(0x30C30C30C30C30C3); + REG2 = ((REG2 << 4) | REG2) & glm::uint64(0x30C30C30C30C30C3); + REG3 = ((REG3 << 4) | REG3) & glm::uint64(0x30C30C30C30C30C3); + + REG1 = ((REG1 << 2) | REG1) & glm::uint64(0x9249249249249249); + REG2 = ((REG2 << 2) | REG2) & glm::uint64(0x9249249249249249); + REG3 = ((REG3 << 2) | REG3) & glm::uint64(0x9249249249249249); + + return REG1 | (REG2 << 1) | (REG3 << 2); + } + + template <> + GLM_FUNC_QUALIFIER glm::uint32 bitfieldInterleave(glm::uint8 x, glm::uint8 y, glm::uint8 z, glm::uint8 w) + { + glm::uint32 REG1(x); + glm::uint32 REG2(y); + glm::uint32 REG3(z); + glm::uint32 REG4(w); + + REG1 = ((REG1 << 12) | REG1) & glm::uint32(0x000F000F000F000F); + REG2 = ((REG2 << 12) | REG2) & glm::uint32(0x000F000F000F000F); + REG3 = ((REG3 << 12) | REG3) & glm::uint32(0x000F000F000F000F); + REG4 = ((REG4 << 12) | REG4) & glm::uint32(0x000F000F000F000F); + + REG1 = ((REG1 << 6) | REG1) & glm::uint32(0x0303030303030303); + REG2 = ((REG2 << 6) | REG2) & glm::uint32(0x0303030303030303); + REG3 = ((REG3 << 6) | REG3) & glm::uint32(0x0303030303030303); + REG4 = ((REG4 << 6) | REG4) & glm::uint32(0x0303030303030303); + + REG1 = ((REG1 << 3) | REG1) & glm::uint32(0x1111111111111111); + REG2 = ((REG2 << 3) | REG2) & glm::uint32(0x1111111111111111); + REG3 = ((REG3 << 3) | REG3) & glm::uint32(0x1111111111111111); + REG4 = ((REG4 << 3) | REG4) & glm::uint32(0x1111111111111111); + + return REG1 | (REG2 << 1) | (REG3 << 2) | (REG4 << 3); + } + + template <> + GLM_FUNC_QUALIFIER glm::uint64 bitfieldInterleave(glm::uint16 x, glm::uint16 y, glm::uint16 z, glm::uint16 w) + { + glm::uint64 REG1(x); + glm::uint64 REG2(y); + glm::uint64 REG3(z); + glm::uint64 REG4(w); + + REG1 = ((REG1 << 24) | REG1) & glm::uint64(0x000000FF000000FF); + REG2 = ((REG2 << 24) | REG2) & glm::uint64(0x000000FF000000FF); + REG3 = ((REG3 << 24) | REG3) & glm::uint64(0x000000FF000000FF); + REG4 = ((REG4 << 24) | REG4) & glm::uint64(0x000000FF000000FF); + + REG1 = ((REG1 << 12) | REG1) & glm::uint64(0x000F000F000F000F); + REG2 = ((REG2 << 12) | REG2) & glm::uint64(0x000F000F000F000F); + REG3 = ((REG3 << 12) | REG3) & glm::uint64(0x000F000F000F000F); + REG4 = ((REG4 << 12) | REG4) & glm::uint64(0x000F000F000F000F); + + REG1 = ((REG1 << 6) | REG1) & glm::uint64(0x0303030303030303); + REG2 = ((REG2 << 6) | REG2) & glm::uint64(0x0303030303030303); + REG3 = ((REG3 << 6) | REG3) & glm::uint64(0x0303030303030303); + REG4 = ((REG4 << 6) | REG4) & glm::uint64(0x0303030303030303); + + REG1 = ((REG1 << 3) | REG1) & glm::uint64(0x1111111111111111); + REG2 = ((REG2 << 3) | REG2) & glm::uint64(0x1111111111111111); + REG3 = ((REG3 << 3) | REG3) & glm::uint64(0x1111111111111111); + REG4 = ((REG4 << 3) | REG4) & glm::uint64(0x1111111111111111); + + return REG1 | (REG2 << 1) | (REG3 << 2) | (REG4 << 3); + } +}//namespace detail + + template <typename genIUType> + GLM_FUNC_QUALIFIER genIUType mask(genIUType Bits) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIUType>::is_integer, "'mask' accepts only integer values"); + + return Bits >= sizeof(genIUType) * 8 ? ~static_cast<genIUType>(0) : (static_cast<genIUType>(1) << Bits) - static_cast<genIUType>(1); + } + + template <typename T, precision P, template <typename, precision> class vecIUType> + GLM_FUNC_QUALIFIER vecIUType<T, P> mask(vecIUType<T, P> const & v) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'mask' accepts only integer values"); + + return detail::functor1<T, T, P, vecIUType>::call(mask, v); + } + + template <typename genIType> + GLM_FUNC_QUALIFIER genIType bitfieldRotateRight(genIType In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIType>::is_integer, "'bitfieldRotateRight' accepts only integer values"); + + int const BitSize = static_cast<genIType>(sizeof(genIType) * 8); + return (In << static_cast<genIType>(Shift)) | (In >> static_cast<genIType>(BitSize - Shift)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> bitfieldRotateRight(vecType<T, P> const & In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldRotateRight' accepts only integer values"); + + int const BitSize = static_cast<int>(sizeof(T) * 8); + return (In << static_cast<T>(Shift)) | (In >> static_cast<T>(BitSize - Shift)); + } + + template <typename genIType> + GLM_FUNC_QUALIFIER genIType bitfieldRotateLeft(genIType In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits<genIType>::is_integer, "'bitfieldRotateLeft' accepts only integer values"); + + int const BitSize = static_cast<genIType>(sizeof(genIType) * 8); + return (In >> static_cast<genIType>(Shift)) | (In << static_cast<genIType>(BitSize - Shift)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> bitfieldRotateLeft(vecType<T, P> const & In, int Shift) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_integer, "'bitfieldRotateLeft' accepts only integer values"); + + int const BitSize = static_cast<int>(sizeof(T) * 8); + return (In >> static_cast<T>(Shift)) | (In << static_cast<T>(BitSize - Shift)); + } + + template <typename genIUType> + GLM_FUNC_QUALIFIER genIUType bitfieldFillOne(genIUType Value, int FirstBit, int BitCount) + { + return Value | static_cast<genIUType>(mask(BitCount) << FirstBit); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> bitfieldFillOne(vecType<T, P> const & Value, int FirstBit, int BitCount) + { + return Value | static_cast<T>(mask(BitCount) << FirstBit); + } + + template <typename genIUType> + GLM_FUNC_QUALIFIER genIUType bitfieldFillZero(genIUType Value, int FirstBit, int BitCount) + { + return Value & static_cast<genIUType>(~(mask(BitCount) << FirstBit)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> bitfieldFillZero(vecType<T, P> const & Value, int FirstBit, int BitCount) + { + return Value & static_cast<T>(~(mask(BitCount) << FirstBit)); + } + + GLM_FUNC_QUALIFIER int16 bitfieldInterleave(int8 x, int8 y) + { + union sign8 + { + int8 i; + uint8 u; + } sign_x, sign_y; + + union sign16 + { + int16 i; + uint16 u; + } result; + + sign_x.i = x; + sign_y.i = y; + result.u = bitfieldInterleave(sign_x.u, sign_y.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint16 bitfieldInterleave(uint8 x, uint8 y) + { + return detail::bitfieldInterleave<uint8, uint16>(x, y); + } + + GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int16 x, int16 y) + { + union sign16 + { + int16 i; + uint16 u; + } sign_x, sign_y; + + union sign32 + { + int32 i; + uint32 u; + } result; + + sign_x.i = x; + sign_y.i = y; + result.u = bitfieldInterleave(sign_x.u, sign_y.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint16 x, uint16 y) + { + return detail::bitfieldInterleave<uint16, uint32>(x, y); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int32 x, int32 y) + { + union sign32 + { + int32 i; + uint32 u; + } sign_x, sign_y; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + result.u = bitfieldInterleave(sign_x.u, sign_y.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint32 x, uint32 y) + { + return detail::bitfieldInterleave<uint32, uint64>(x, y); + } + + GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int8 x, int8 y, int8 z) + { + union sign8 + { + int8 i; + uint8 u; + } sign_x, sign_y, sign_z; + + union sign32 + { + int32 i; + uint32 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z) + { + return detail::bitfieldInterleave<uint8, uint32>(x, y, z); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int16 x, int16 y, int16 z) + { + union sign16 + { + int16 i; + uint16 u; + } sign_x, sign_y, sign_z; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z) + { + return detail::bitfieldInterleave<uint32, uint64>(x, y, z); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int32 x, int32 y, int32 z) + { + union sign16 + { + int32 i; + uint32 u; + } sign_x, sign_y, sign_z; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint32 x, uint32 y, uint32 z) + { + return detail::bitfieldInterleave<uint32, uint64>(x, y, z); + } + + GLM_FUNC_QUALIFIER int32 bitfieldInterleave(int8 x, int8 y, int8 z, int8 w) + { + union sign8 + { + int8 i; + uint8 u; + } sign_x, sign_y, sign_z, sign_w; + + union sign32 + { + int32 i; + uint32 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + sign_w.i = w; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u, sign_w.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint32 bitfieldInterleave(uint8 x, uint8 y, uint8 z, uint8 w) + { + return detail::bitfieldInterleave<uint8, uint32>(x, y, z, w); + } + + GLM_FUNC_QUALIFIER int64 bitfieldInterleave(int16 x, int16 y, int16 z, int16 w) + { + union sign16 + { + int16 i; + uint16 u; + } sign_x, sign_y, sign_z, sign_w; + + union sign64 + { + int64 i; + uint64 u; + } result; + + sign_x.i = x; + sign_y.i = y; + sign_z.i = z; + sign_w.i = w; + result.u = bitfieldInterleave(sign_x.u, sign_y.u, sign_z.u, sign_w.u); + + return result.i; + } + + GLM_FUNC_QUALIFIER uint64 bitfieldInterleave(uint16 x, uint16 y, uint16 z, uint16 w) + { + return detail::bitfieldInterleave<uint16, uint64>(x, y, z, w); + } +}//namespace glm diff --git a/extensions/common/glm/gtc/constants.hpp b/extensions/common/glm/gtc/constants.hpp new file mode 100644 index 0000000000..0de7f9695d --- /dev/null +++ b/extensions/common/glm/gtc/constants.hpp @@ -0,0 +1,205 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_constants +/// @file glm/gtc/constants.hpp +/// @date 2011-09-30 / 2012-01-25 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// +/// @defgroup gtc_constants GLM_GTC_constants +/// @ingroup gtc +/// +/// @brief Provide a list of constants and precomputed useful values. +/// +/// <glm/gtc/constants.hpp> need to be included to use these features. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_constants extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_constants + /// @{ + + /// Return the epsilon constant for floating point types. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType epsilon(); + + /// Return 0. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType zero(); + + /// Return 1. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType one(); + + /// Return the pi constant. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType pi(); + + /// Return pi * 2. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType two_pi(); + + /// Return square root of pi. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType root_pi(); + + /// Return pi / 2. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType half_pi(); + + /// Return pi / 2 * 3. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType three_over_two_pi(); + + /// Return pi / 4. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType quarter_pi(); + + /// Return 1 / pi. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType one_over_pi(); + + /// Return 1 / (pi * 2). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType one_over_two_pi(); + + /// Return 2 / pi. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType two_over_pi(); + + /// Return 4 / pi. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType four_over_pi(); + + /// Return 2 / sqrt(pi). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType two_over_root_pi(); + + /// Return 1 / sqrt(2). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType one_over_root_two(); + + /// Return sqrt(pi / 2). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType root_half_pi(); + + /// Return sqrt(2 * pi). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType root_two_pi(); + + /// Return sqrt(ln(4)). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType root_ln_four(); + + /// Return e constant. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType e(); + + /// Return Euler's constant. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType euler(); + + /// Return sqrt(2). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType root_two(); + + /// Return sqrt(3). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType root_three(); + + /// Return sqrt(5). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType root_five(); + + /// Return ln(2). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType ln_two(); + + /// Return ln(10). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType ln_ten(); + + /// Return ln(ln(2)). + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType ln_ln_two(); + + /// Return 1 / 3. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType third(); + + /// Return 2 / 3. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType two_thirds(); + + /// Return the golden ratio constant. + /// @see gtc_constants + template <typename genType> + GLM_FUNC_DECL genType golden_ratio(); + + /// @} +} //namespace glm + +#include "constants.inl" diff --git a/extensions/common/glm/gtc/constants.inl b/extensions/common/glm/gtc/constants.inl new file mode 100644 index 0000000000..ef5ec9fb57 --- /dev/null +++ b/extensions/common/glm/gtc/constants.inl @@ -0,0 +1,210 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_constants +/// @file glm/gtc/constants.inl +/// @date 2011-10-14 / 2014-10-25 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include <limits> + +namespace glm +{ + template <typename genType> + GLM_FUNC_QUALIFIER genType epsilon() + { + return std::numeric_limits<genType>::epsilon(); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType zero() + { + return genType(0); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType one() + { + return genType(1); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType pi() + { + return genType(3.14159265358979323846264338327950288); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType two_pi() + { + return genType(6.28318530717958647692528676655900576); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType root_pi() + { + return genType(1.772453850905516027); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType half_pi() + { + return genType(1.57079632679489661923132169163975144); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType three_over_two_pi() + { + return genType(4.71238898038468985769396507491925432); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType quarter_pi() + { + return genType(0.785398163397448309615660845819875721); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType one_over_pi() + { + return genType(0.318309886183790671537767526745028724); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType one_over_two_pi() + { + return genType(0.159154943091895335768883763372514362); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType two_over_pi() + { + return genType(0.636619772367581343075535053490057448); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType four_over_pi() + { + return genType(1.273239544735162686151070106980114898); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType two_over_root_pi() + { + return genType(1.12837916709551257389615890312154517); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType one_over_root_two() + { + return genType(0.707106781186547524400844362104849039); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType root_half_pi() + { + return genType(1.253314137315500251); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType root_two_pi() + { + return genType(2.506628274631000502); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType root_ln_four() + { + return genType(1.17741002251547469); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType e() + { + return genType(2.71828182845904523536); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType euler() + { + return genType(0.577215664901532860606); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType root_two() + { + return genType(1.41421356237309504880168872420969808); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType root_three() + { + return genType(1.73205080756887729352744634150587236); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType root_five() + { + return genType(2.23606797749978969640917366873127623); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType ln_two() + { + return genType(0.693147180559945309417232121458176568); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType ln_ten() + { + return genType(2.30258509299404568401799145468436421); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType ln_ln_two() + { + return genType(-0.3665129205816643); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType third() + { + return genType(0.3333333333333333333333333333333333333333); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType two_thirds() + { + return genType(0.666666666666666666666666666666666666667); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType golden_ratio() + { + return genType(1.61803398874989484820458683436563811); + } +} //namespace glm diff --git a/extensions/common/glm/gtc/epsilon.hpp b/extensions/common/glm/gtc/epsilon.hpp new file mode 100644 index 0000000000..4b63597a2b --- /dev/null +++ b/extensions/common/glm/gtc/epsilon.hpp @@ -0,0 +1,102 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_epsilon +/// @file glm/gtc/epsilon.hpp +/// @date 2012-04-07 / 2012-04-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtc_epsilon GLM_GTC_epsilon +/// @ingroup gtc +/// +/// @brief Comparison functions for a user defined epsilon values. +/// +/// <glm/gtc/epsilon.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/precision.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_epsilon extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_epsilon + /// @{ + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @see gtc_epsilon + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> epsilonEqual( + vecType<T, P> const & x, + vecType<T, P> const & y, + T const & epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is satisfied. + /// + /// @see gtc_epsilon + template <typename genType> + GLM_FUNC_DECL bool epsilonEqual( + genType const & x, + genType const & y, + genType const & epsilon); + + /// Returns the component-wise comparison of |x - y| < epsilon. + /// True if this expression is not satisfied. + /// + /// @see gtc_epsilon + template <typename genType> + GLM_FUNC_DECL typename genType::boolType epsilonNotEqual( + genType const & x, + genType const & y, + typename genType::value_type const & epsilon); + + /// Returns the component-wise comparison of |x - y| >= epsilon. + /// True if this expression is not satisfied. + /// + /// @see gtc_epsilon + template <typename genType> + GLM_FUNC_DECL bool epsilonNotEqual( + genType const & x, + genType const & y, + genType const & epsilon); + + /// @} +}//namespace glm + +#include "epsilon.inl" diff --git a/extensions/common/glm/gtc/epsilon.inl b/extensions/common/glm/gtc/epsilon.inl new file mode 100644 index 0000000000..e02c28788e --- /dev/null +++ b/extensions/common/glm/gtc/epsilon.inl @@ -0,0 +1,154 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_epsilon +/// @file glm/gtc/epsilon.inl +/// @date 2012-04-07 / 2012-04-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +// Dependency: +#include "quaternion.hpp" +#include "../vector_relational.hpp" +#include "../common.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" + +namespace glm +{ + template <> + GLM_FUNC_QUALIFIER bool epsilonEqual + ( + float const & x, + float const & y, + float const & epsilon + ) + { + return abs(x - y) < epsilon; + } + + template <> + GLM_FUNC_QUALIFIER bool epsilonEqual + ( + double const & x, + double const & y, + double const & epsilon + ) + { + return abs(x - y) < epsilon; + } + + template <> + GLM_FUNC_QUALIFIER bool epsilonNotEqual + ( + float const & x, + float const & y, + float const & epsilon + ) + { + return abs(x - y) >= epsilon; + } + + template <> + GLM_FUNC_QUALIFIER bool epsilonNotEqual + ( + double const & x, + double const & y, + double const & epsilon + ) + { + return abs(x - y) >= epsilon; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> epsilonEqual + ( + vecType<T, P> const & x, + vecType<T, P> const & y, + T const & epsilon + ) + { + return lessThan(abs(x - y), vecType<T, P>(epsilon)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> epsilonEqual + ( + vecType<T, P> const & x, + vecType<T, P> const & y, + vecType<T, P> const & epsilon + ) + { + return lessThan(abs(x - y), vecType<T, P>(epsilon)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> epsilonNotEqual + ( + vecType<T, P> const & x, + vecType<T, P> const & y, + T const & epsilon + ) + { + return greaterThanEqual(abs(x - y), vecType<T, P>(epsilon)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> epsilonNotEqual + ( + vecType<T, P> const & x, + vecType<T, P> const & y, + vecType<T, P> const & epsilon + ) + { + return greaterThanEqual(abs(x - y), vecType<T, P>(epsilon)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<bool, P> epsilonEqual + ( + tquat<T, P> const & x, + tquat<T, P> const & y, + T const & epsilon + ) + { + tvec4<T, P> v(x.x - y.x, x.y - y.y, x.z - y.z, x.w - y.w); + return lessThan(abs(v), tvec4<T, P>(epsilon)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<bool, P> epsilonNotEqual + ( + tquat<T, P> const & x, + tquat<T, P> const & y, + T const & epsilon + ) + { + tvec4<T, P> v(x.x - y.x, x.y - y.y, x.z - y.z, x.w - y.w); + return greaterThanEqual(abs(v), tvec4<T, P>(epsilon)); + } +}//namespace glm diff --git a/extensions/common/glm/gtc/integer.hpp b/extensions/common/glm/gtc/integer.hpp new file mode 100644 index 0000000000..47b0cfbc2c --- /dev/null +++ b/extensions/common/glm/gtc/integer.hpp @@ -0,0 +1,105 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_integer +/// @file glm/gtc/integer.hpp +/// @date 2014-11-17 / 2014-11-17 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_integer (dependence) +/// +/// @defgroup gtc_integer GLM_GTC_integer +/// @ingroup gtc +/// +/// @brief Allow to perform bit operations on integer values +/// +/// <glm/gtc/integer.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/precision.hpp" +#include "../detail/func_common.hpp" +#include "../detail/func_integer.hpp" +#include "../detail/func_exponential.hpp" +#include <limits> + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_integer + /// @{ + + /// Returns the log2 of x for integer values. Can be reliably using to compute mipmap count from the texture size. + /// @see gtc_integer + template <typename genIUType> + GLM_FUNC_DECL genIUType log2(genIUType x); + + /// Modulus. Returns x % y + /// for each component in x using the floating point value y. + /// + /// @tparam genIUType Integer-point scalar or vector types. + /// + /// @see gtc_integer + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml">GLSL mod man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genIUType> + GLM_FUNC_DECL genIUType mod(genIUType x, genIUType y); + + /// Modulus. Returns x % y + /// for each component in x using the floating point value y. + /// + /// @tparam T Integer scalar types. + /// @tparam vecType vector types. + /// + /// @see gtc_integer + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml">GLSL mod man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> mod(vecType<T, P> const & x, T y); + + /// Modulus. Returns x % y + /// for each component in x using the floating point value y. + /// + /// @tparam T Integer scalar types. + /// @tparam vecType vector types. + /// + /// @see gtc_integer + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/mod.xml">GLSL mod man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> mod(vecType<T, P> const & x, vecType<T, P> const & y); + + /// @} +} //namespace glm + +#include "integer.inl" diff --git a/extensions/common/glm/gtc/integer.inl b/extensions/common/glm/gtc/integer.inl new file mode 100644 index 0000000000..c2961b80c5 --- /dev/null +++ b/extensions/common/glm/gtc/integer.inl @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_integer +/// @file glm/gtc/integer.inl +/// @date 2014-11-17 / 2014-11-17 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail +{ + template <typename T, precision P, template <class, precision> class vecType> + struct compute_log2<T, P, vecType, false> + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & vec) + { + //Equivalent to return findMSB(vec); but save one function call in ASM with VC + //return findMSB(vec); + return vecType<T, P>(detail::compute_findMSB_vec<T, P, vecType, sizeof(T) * 8>::call(vec)); + } + }; + +# if GLM_HAS_BITSCAN_WINDOWS + template <precision P> + struct compute_log2<int, P, tvec4, false> + { + GLM_FUNC_QUALIFIER static tvec4<int, P> call(tvec4<int, P> const & vec) + { + tvec4<int, P> Result(glm::uninitialize); + + _BitScanReverse(reinterpret_cast<unsigned long*>(&Result.x), vec.x); + _BitScanReverse(reinterpret_cast<unsigned long*>(&Result.y), vec.y); + _BitScanReverse(reinterpret_cast<unsigned long*>(&Result.z), vec.z); + _BitScanReverse(reinterpret_cast<unsigned long*>(&Result.w), vec.w); + + return Result; + } + }; +# endif//GLM_HAS_BITSCAN_WINDOWS + + template <typename T, precision P, template <class, precision> class vecType, typename genType> + struct compute_mod<T, P, vecType, genType, false> + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & a, genType const & b) + { + return a % b; + } + }; +}//namespace detail +}//namespace glm diff --git a/extensions/common/glm/gtc/matrix_access.hpp b/extensions/common/glm/gtc/matrix_access.hpp new file mode 100644 index 0000000000..f2354110be --- /dev/null +++ b/extensions/common/glm/gtc/matrix_access.hpp @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_matrix_access +/// @file glm/gtc/matrix_access.hpp +/// @date 2005-12-27 / 2011-05-16 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtc_matrix_access GLM_GTC_matrix_access +/// @ingroup gtc +/// +/// Defines functions to access rows or columns of a matrix easily. +/// <glm/gtc/matrix_access.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../detail/setup.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_matrix_access extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_matrix_access + /// @{ + + /// Get a specific row of a matrix. + /// @see gtc_matrix_access + template <typename genType> + GLM_FUNC_DECL typename genType::row_type row( + genType const & m, + length_t index); + + /// Set a specific row to a matrix. + /// @see gtc_matrix_access + template <typename genType> + GLM_FUNC_DECL genType row( + genType const & m, + length_t index, + typename genType::row_type const & x); + + /// Get a specific column of a matrix. + /// @see gtc_matrix_access + template <typename genType> + GLM_FUNC_DECL typename genType::col_type column( + genType const & m, + length_t index); + + /// Set a specific column to a matrix. + /// @see gtc_matrix_access + template <typename genType> + GLM_FUNC_DECL genType column( + genType const & m, + length_t index, + typename genType::col_type const & x); + + /// @} +}//namespace glm + +#include "matrix_access.inl" diff --git a/extensions/common/glm/gtc/matrix_access.inl b/extensions/common/glm/gtc/matrix_access.inl new file mode 100644 index 0000000000..aba94ba8b1 --- /dev/null +++ b/extensions/common/glm/gtc/matrix_access.inl @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_matrix_access +/// @file glm/gtc/matrix_access.inl +/// @date 2005-12-27 / 2011-06-05 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename genType> + GLM_FUNC_QUALIFIER genType row + ( + genType const & m, + length_t index, + typename genType::row_type const & x + ) + { + assert(index >= 0 && static_cast<detail::component_count_t>(index) < detail::component_count(m[0])); + + genType Result = m; + for(detail::component_count_t i = 0; i < detail::component_count(m); ++i) + Result[i][index] = x[i]; + return Result; + } + + template <typename genType> + GLM_FUNC_QUALIFIER typename genType::row_type row + ( + genType const & m, + length_t index + ) + { + assert(index >= 0 && static_cast<detail::component_count_t>(index) < detail::component_count(m[0])); + + typename genType::row_type Result; + for(detail::component_count_t i = 0; i < detail::component_count(m); ++i) + Result[i] = m[i][index]; + return Result; + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType column + ( + genType const & m, + length_t index, + typename genType::col_type const & x + ) + { + assert(index >= 0 && static_cast<detail::component_count_t>(index) < detail::component_count(m)); + + genType Result = m; + Result[index] = x; + return Result; + } + + template <typename genType> + GLM_FUNC_QUALIFIER typename genType::col_type column + ( + genType const & m, + length_t index + ) + { + assert(index >= 0 && static_cast<detail::component_count_t>(index) < detail::component_count(m)); + + return m[index]; + } +}//namespace glm diff --git a/extensions/common/glm/gtc/matrix_integer.hpp b/extensions/common/glm/gtc/matrix_integer.hpp new file mode 100644 index 0000000000..f29e7793ac --- /dev/null +++ b/extensions/common/glm/gtc/matrix_integer.hpp @@ -0,0 +1,515 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_matrix_integer +/// @file glm/gtc/matrix_integer.hpp +/// @date 2011-01-20 / 2011-06-05 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtc_matrix_integer GLM_GTC_matrix_integer +/// @ingroup gtc +/// +/// Defines a number of matrices with integer types. +/// <glm/gtc/matrix_integer.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../mat2x2.hpp" +#include "../mat2x3.hpp" +#include "../mat2x4.hpp" +#include "../mat3x2.hpp" +#include "../mat3x3.hpp" +#include "../mat3x4.hpp" +#include "../mat4x2.hpp" +#include "../mat4x3.hpp" +#include "../mat4x4.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_matrix_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_matrix_integer + /// @{ + + /// High-precision signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<int, highp> highp_imat2; + + /// High-precision signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<int, highp> highp_imat3; + + /// High-precision signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<int, highp> highp_imat4; + + /// High-precision signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<int, highp> highp_imat2x2; + + /// High-precision signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef tmat2x3<int, highp> highp_imat2x3; + + /// High-precision signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef tmat2x4<int, highp> highp_imat2x4; + + /// High-precision signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef tmat3x2<int, highp> highp_imat3x2; + + /// High-precision signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<int, highp> highp_imat3x3; + + /// High-precision signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef tmat3x4<int, highp> highp_imat3x4; + + /// High-precision signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef tmat4x2<int, highp> highp_imat4x2; + + /// High-precision signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef tmat4x3<int, highp> highp_imat4x3; + + /// High-precision signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<int, highp> highp_imat4x4; + + + /// Medium-precision signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<int, mediump> mediump_imat2; + + /// Medium-precision signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<int, mediump> mediump_imat3; + + /// Medium-precision signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<int, mediump> mediump_imat4; + + + /// Medium-precision signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<int, mediump> mediump_imat2x2; + + /// Medium-precision signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef tmat2x3<int, mediump> mediump_imat2x3; + + /// Medium-precision signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef tmat2x4<int, mediump> mediump_imat2x4; + + /// Medium-precision signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef tmat3x2<int, mediump> mediump_imat3x2; + + /// Medium-precision signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<int, mediump> mediump_imat3x3; + + /// Medium-precision signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef tmat3x4<int, mediump> mediump_imat3x4; + + /// Medium-precision signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef tmat4x2<int, mediump> mediump_imat4x2; + + /// Medium-precision signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef tmat4x3<int, mediump> mediump_imat4x3; + + /// Medium-precision signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<int, mediump> mediump_imat4x4; + + + /// Low-precision signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<int, lowp> lowp_imat2; + + /// Low-precision signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<int, lowp> lowp_imat3; + + /// Low-precision signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<int, lowp> lowp_imat4; + + + /// Low-precision signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<int, lowp> lowp_imat2x2; + + /// Low-precision signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef tmat2x3<int, lowp> lowp_imat2x3; + + /// Low-precision signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef tmat2x4<int, lowp> lowp_imat2x4; + + /// Low-precision signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef tmat3x2<int, lowp> lowp_imat3x2; + + /// Low-precision signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<int, lowp> lowp_imat3x3; + + /// Low-precision signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef tmat3x4<int, lowp> lowp_imat3x4; + + /// Low-precision signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef tmat4x2<int, lowp> lowp_imat4x2; + + /// Low-precision signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef tmat4x3<int, lowp> lowp_imat4x3; + + /// Low-precision signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<int, lowp> lowp_imat4x4; + + + /// High-precision unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<uint, highp> highp_umat2; + + /// High-precision unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<uint, highp> highp_umat3; + + /// High-precision unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<uint, highp> highp_umat4; + + /// High-precision unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<uint, highp> highp_umat2x2; + + /// High-precision unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef tmat2x3<uint, highp> highp_umat2x3; + + /// High-precision unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef tmat2x4<uint, highp> highp_umat2x4; + + /// High-precision unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef tmat3x2<uint, highp> highp_umat3x2; + + /// High-precision unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<uint, highp> highp_umat3x3; + + /// High-precision unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef tmat3x4<uint, highp> highp_umat3x4; + + /// High-precision unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef tmat4x2<uint, highp> highp_umat4x2; + + /// High-precision unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef tmat4x3<uint, highp> highp_umat4x3; + + /// High-precision unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<uint, highp> highp_umat4x4; + + + /// Medium-precision unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<uint, mediump> mediump_umat2; + + /// Medium-precision unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<uint, mediump> mediump_umat3; + + /// Medium-precision unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<uint, mediump> mediump_umat4; + + + /// Medium-precision unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<uint, mediump> mediump_umat2x2; + + /// Medium-precision unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef tmat2x3<uint, mediump> mediump_umat2x3; + + /// Medium-precision unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef tmat2x4<uint, mediump> mediump_umat2x4; + + /// Medium-precision unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef tmat3x2<uint, mediump> mediump_umat3x2; + + /// Medium-precision unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<uint, mediump> mediump_umat3x3; + + /// Medium-precision unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef tmat3x4<uint, mediump> mediump_umat3x4; + + /// Medium-precision unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef tmat4x2<uint, mediump> mediump_umat4x2; + + /// Medium-precision unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef tmat4x3<uint, mediump> mediump_umat4x3; + + /// Medium-precision unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<uint, mediump> mediump_umat4x4; + + + /// Low-precision unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<uint, lowp> lowp_umat2; + + /// Low-precision unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<uint, lowp> lowp_umat3; + + /// Low-precision unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<uint, lowp> lowp_umat4; + + + /// Low-precision unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef tmat2x2<uint, lowp> lowp_umat2x2; + + /// Low-precision unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef tmat2x3<uint, lowp> lowp_umat2x3; + + /// Low-precision unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef tmat2x4<uint, lowp> lowp_umat2x4; + + /// Low-precision unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef tmat3x2<uint, lowp> lowp_umat3x2; + + /// Low-precision unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef tmat3x3<uint, lowp> lowp_umat3x3; + + /// Low-precision unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef tmat3x4<uint, lowp> lowp_umat3x4; + + /// Low-precision unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef tmat4x2<uint, lowp> lowp_umat4x2; + + /// Low-precision unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef tmat4x3<uint, lowp> lowp_umat4x3; + + /// Low-precision unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef tmat4x4<uint, lowp> lowp_umat4x4; + +#if(defined(GLM_PRECISION_HIGHP_INT)) + typedef highp_imat2 imat2; + typedef highp_imat3 imat3; + typedef highp_imat4 imat4; + typedef highp_imat2x2 imat2x2; + typedef highp_imat2x3 imat2x3; + typedef highp_imat2x4 imat2x4; + typedef highp_imat3x2 imat3x2; + typedef highp_imat3x3 imat3x3; + typedef highp_imat3x4 imat3x4; + typedef highp_imat4x2 imat4x2; + typedef highp_imat4x3 imat4x3; + typedef highp_imat4x4 imat4x4; +#elif(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_imat2 imat2; + typedef lowp_imat3 imat3; + typedef lowp_imat4 imat4; + typedef lowp_imat2x2 imat2x2; + typedef lowp_imat2x3 imat2x3; + typedef lowp_imat2x4 imat2x4; + typedef lowp_imat3x2 imat3x2; + typedef lowp_imat3x3 imat3x3; + typedef lowp_imat3x4 imat3x4; + typedef lowp_imat4x2 imat4x2; + typedef lowp_imat4x3 imat4x3; + typedef lowp_imat4x4 imat4x4; +#else //if(defined(GLM_PRECISION_MEDIUMP_INT)) + + /// Signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat2 imat2; + + /// Signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat3 imat3; + + /// Signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat4 imat4; + + /// Signed integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat2x2 imat2x2; + + /// Signed integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat2x3 imat2x3; + + /// Signed integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat2x4 imat2x4; + + /// Signed integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat3x2 imat3x2; + + /// Signed integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat3x3 imat3x3; + + /// Signed integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat3x4 imat3x4; + + /// Signed integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat4x2 imat4x2; + + /// Signed integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat4x3 imat4x3; + + /// Signed integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mediump_imat4x4 imat4x4; +#endif//GLM_PRECISION + +#if(defined(GLM_PRECISION_HIGHP_UINT)) + typedef highp_umat2 umat2; + typedef highp_umat3 umat3; + typedef highp_umat4 umat4; + typedef highp_umat2x2 umat2x2; + typedef highp_umat2x3 umat2x3; + typedef highp_umat2x4 umat2x4; + typedef highp_umat3x2 umat3x2; + typedef highp_umat3x3 umat3x3; + typedef highp_umat3x4 umat3x4; + typedef highp_umat4x2 umat4x2; + typedef highp_umat4x3 umat4x3; + typedef highp_umat4x4 umat4x4; +#elif(defined(GLM_PRECISION_LOWP_UINT)) + typedef lowp_umat2 umat2; + typedef lowp_umat3 umat3; + typedef lowp_umat4 umat4; + typedef lowp_umat2x2 umat2x2; + typedef lowp_umat2x3 umat2x3; + typedef lowp_umat2x4 umat2x4; + typedef lowp_umat3x2 umat3x2; + typedef lowp_umat3x3 umat3x3; + typedef lowp_umat3x4 umat3x4; + typedef lowp_umat4x2 umat4x2; + typedef lowp_umat4x3 umat4x3; + typedef lowp_umat4x4 umat4x4; +#else //if(defined(GLM_PRECISION_MEDIUMP_UINT)) + + /// Unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat2 umat2; + + /// Unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat3 umat3; + + /// Unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat4 umat4; + + /// Unsigned integer 2x2 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat2x2 umat2x2; + + /// Unsigned integer 2x3 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat2x3 umat2x3; + + /// Unsigned integer 2x4 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat2x4 umat2x4; + + /// Unsigned integer 3x2 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat3x2 umat3x2; + + /// Unsigned integer 3x3 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat3x3 umat3x3; + + /// Unsigned integer 3x4 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat3x4 umat3x4; + + /// Unsigned integer 4x2 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat4x2 umat4x2; + + /// Unsigned integer 4x3 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat4x3 umat4x3; + + /// Unsigned integer 4x4 matrix. + /// @see gtc_matrix_integer + typedef mediump_umat4x4 umat4x4; +#endif//GLM_PRECISION + + /// @} +}//namespace glm diff --git a/extensions/common/glm/gtc/matrix_inverse.hpp b/extensions/common/glm/gtc/matrix_inverse.hpp new file mode 100644 index 0000000000..ea33678c50 --- /dev/null +++ b/extensions/common/glm/gtc/matrix_inverse.hpp @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_matrix_inverse +/// @file glm/gtc/matrix_inverse.hpp +/// @date 2005-12-21 / 2011-06-05 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtc_matrix_inverse GLM_GTC_matrix_inverse +/// @ingroup gtc +/// +/// Defines additional matrix inverting functions. +/// <glm/gtc/matrix_inverse.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../matrix.hpp" +#include "../mat2x2.hpp" +#include "../mat3x3.hpp" +#include "../mat4x4.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_matrix_inverse extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_matrix_inverse + /// @{ + + /// Fast matrix inverse for affine matrix. + /// + /// @param m Input matrix to invert. + /// @tparam genType Squared floating-point matrix: half, float or double. Inverse of matrix based of half-precision floating point value is highly innacurate. + /// @see gtc_matrix_inverse + template <typename genType> + GLM_FUNC_DECL genType affineInverse(genType const & m); + + /// Compute the inverse transpose of a matrix. + /// + /// @param m Input matrix to invert transpose. + /// @tparam genType Squared floating-point matrix: half, float or double. Inverse of matrix based of half-precision floating point value is highly innacurate. + /// @see gtc_matrix_inverse + template <typename genType> + GLM_FUNC_DECL genType inverseTranspose(genType const & m); + + /// @} +}//namespace glm + +#include "matrix_inverse.inl" diff --git a/extensions/common/glm/gtc/matrix_inverse.inl b/extensions/common/glm/gtc/matrix_inverse.inl new file mode 100644 index 0000000000..526c1c6283 --- /dev/null +++ b/extensions/common/glm/gtc/matrix_inverse.inl @@ -0,0 +1,148 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_matrix_inverse +/// @file glm/gtc/matrix_inverse.inl +/// @date 2005-12-21 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> affineInverse(tmat3x3<T, P> const & m) + { + tmat3x3<T, P> Result(m); + Result[2] = tvec3<T, P>(0, 0, 1); + Result = transpose(Result); + tvec3<T, P> Translation = Result * tvec3<T, P>(-tvec2<T, P>(m[2]), m[2][2]); + Result[2] = Translation; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> affineInverse(tmat4x4<T, P> const & m) + { + tmat4x4<T, P> Result(m); + Result[3] = tvec4<T, P>(0, 0, 0, 1); + Result = transpose(Result); + tvec4<T, P> Translation = Result * tvec4<T, P>(-tvec3<T, P>(m[3]), m[3][3]); + Result[3] = Translation; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> inverseTranspose(tmat2x2<T, P> const & m) + { + T Determinant = m[0][0] * m[1][1] - m[1][0] * m[0][1]; + + tmat2x2<T, P> Inverse( + + m[1][1] / Determinant, + - m[0][1] / Determinant, + - m[1][0] / Determinant, + + m[0][0] / Determinant); + + return Inverse; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> inverseTranspose(tmat3x3<T, P> const & m) + { + T Determinant = + + m[0][0] * (m[1][1] * m[2][2] - m[1][2] * m[2][1]) + - m[0][1] * (m[1][0] * m[2][2] - m[1][2] * m[2][0]) + + m[0][2] * (m[1][0] * m[2][1] - m[1][1] * m[2][0]); + + tmat3x3<T, P> Inverse(uninitialize); + Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]); + Inverse[0][1] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]); + Inverse[0][2] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]); + Inverse[1][0] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]); + Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]); + Inverse[1][2] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]); + Inverse[2][0] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]); + Inverse[2][1] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]); + Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]); + Inverse /= Determinant; + + return Inverse; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> inverseTranspose(tmat4x4<T, P> const & m) + { + T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3]; + T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3]; + T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2]; + T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3]; + T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2]; + T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1]; + T SubFactor06 = m[1][2] * m[3][3] - m[3][2] * m[1][3]; + T SubFactor07 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + T SubFactor08 = m[1][1] * m[3][2] - m[3][1] * m[1][2]; + T SubFactor09 = m[1][0] * m[3][3] - m[3][0] * m[1][3]; + T SubFactor10 = m[1][0] * m[3][2] - m[3][0] * m[1][2]; + T SubFactor11 = m[1][1] * m[3][3] - m[3][1] * m[1][3]; + T SubFactor12 = m[1][0] * m[3][1] - m[3][0] * m[1][1]; + T SubFactor13 = m[1][2] * m[2][3] - m[2][2] * m[1][3]; + T SubFactor14 = m[1][1] * m[2][3] - m[2][1] * m[1][3]; + T SubFactor15 = m[1][1] * m[2][2] - m[2][1] * m[1][2]; + T SubFactor16 = m[1][0] * m[2][3] - m[2][0] * m[1][3]; + T SubFactor17 = m[1][0] * m[2][2] - m[2][0] * m[1][2]; + T SubFactor18 = m[1][0] * m[2][1] - m[2][0] * m[1][1]; + + tmat4x4<T, P> Inverse(uninitialize); + Inverse[0][0] = + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02); + Inverse[0][1] = - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04); + Inverse[0][2] = + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05); + Inverse[0][3] = - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05); + + Inverse[1][0] = - (m[0][1] * SubFactor00 - m[0][2] * SubFactor01 + m[0][3] * SubFactor02); + Inverse[1][1] = + (m[0][0] * SubFactor00 - m[0][2] * SubFactor03 + m[0][3] * SubFactor04); + Inverse[1][2] = - (m[0][0] * SubFactor01 - m[0][1] * SubFactor03 + m[0][3] * SubFactor05); + Inverse[1][3] = + (m[0][0] * SubFactor02 - m[0][1] * SubFactor04 + m[0][2] * SubFactor05); + + Inverse[2][0] = + (m[0][1] * SubFactor06 - m[0][2] * SubFactor07 + m[0][3] * SubFactor08); + Inverse[2][1] = - (m[0][0] * SubFactor06 - m[0][2] * SubFactor09 + m[0][3] * SubFactor10); + Inverse[2][2] = + (m[0][0] * SubFactor11 - m[0][1] * SubFactor09 + m[0][3] * SubFactor12); + Inverse[2][3] = - (m[0][0] * SubFactor08 - m[0][1] * SubFactor10 + m[0][2] * SubFactor12); + + Inverse[3][0] = - (m[0][1] * SubFactor13 - m[0][2] * SubFactor14 + m[0][3] * SubFactor15); + Inverse[3][1] = + (m[0][0] * SubFactor13 - m[0][2] * SubFactor16 + m[0][3] * SubFactor17); + Inverse[3][2] = - (m[0][0] * SubFactor14 - m[0][1] * SubFactor16 + m[0][3] * SubFactor18); + Inverse[3][3] = + (m[0][0] * SubFactor15 - m[0][1] * SubFactor17 + m[0][2] * SubFactor18); + + T Determinant = + + m[0][0] * Inverse[0][0] + + m[0][1] * Inverse[0][1] + + m[0][2] * Inverse[0][2] + + m[0][3] * Inverse[0][3]; + + Inverse /= Determinant; + + return Inverse; + } +}//namespace glm diff --git a/extensions/common/glm/gtc/matrix_transform.hpp b/extensions/common/glm/gtc/matrix_transform.hpp new file mode 100644 index 0000000000..f6d4365205 --- /dev/null +++ b/extensions/common/glm/gtc/matrix_transform.hpp @@ -0,0 +1,304 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_matrix_transform +/// @file glm/gtc/matrix_transform.hpp +/// @date 2009-04-29 / 2011-05-16 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_transform +/// @see gtx_transform2 +/// +/// @defgroup gtc_matrix_transform GLM_GTC_matrix_transform +/// @ingroup gtc +/// +/// @brief Defines functions that generate common transformation matrices. +/// +/// The matrices generated by this extension use standard OpenGL fixed-function +/// conventions. For example, the lookAt function generates a transform from world +/// space into the specific eye space that the projective matrix functions +/// (perspective, ortho, etc) are designed to expect. The OpenGL compatibility +/// specifications defines the particular layout of this eye space. +/// +/// <glm/gtc/matrix_transform.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../mat4x4.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../gtc/constants.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_matrix_transform extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_matrix_transform + /// @{ + + /// Builds a translation 4 * 4 matrix created from a vector of 3 components. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param v Coordinates of a translation vector. + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @code + /// #include <glm/glm.hpp> + /// #include <glm/gtc/matrix_transform.hpp> + /// ... + /// glm::mat4 m = glm::translate(glm::mat4(1.0f), glm::vec3(1.0f)); + /// // m[0][0] == 1.0f, m[0][1] == 0.0f, m[0][2] == 0.0f, m[0][3] == 0.0f + /// // m[1][0] == 0.0f, m[1][1] == 1.0f, m[1][2] == 0.0f, m[1][3] == 0.0f + /// // m[2][0] == 0.0f, m[2][1] == 0.0f, m[2][2] == 1.0f, m[2][3] == 0.0f + /// // m[3][0] == 1.0f, m[3][1] == 1.0f, m[3][2] == 1.0f, m[3][3] == 1.0f + /// @endcode + /// @see gtc_matrix_transform + /// @see - translate(tmat4x4<T, P> const & m, T x, T y, T z) + /// @see - translate(tvec3<T, P> const & v) + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> translate( + tmat4x4<T, P> const & m, + tvec3<T, P> const & v); + + /// Builds a rotation 4 * 4 matrix created from an axis vector and an angle. + /// + /// @param m Input matrix multiplied by this rotation matrix. + /// @param angle Rotation angle expressed in radians. + /// @param axis Rotation axis, recommanded to be normalized. + /// @tparam T Value type used to build the matrix. Supported: half, float or double. + /// @see gtc_matrix_transform + /// @see - rotate(tmat4x4<T, P> const & m, T angle, T x, T y, T z) + /// @see - rotate(T angle, tvec3<T, P> const & v) + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> rotate( + tmat4x4<T, P> const & m, + T angle, + tvec3<T, P> const & axis); + + /// Builds a scale 4 * 4 matrix created from 3 scalars. + /// + /// @param m Input matrix multiplied by this scale matrix. + /// @param v Ratio of scaling for each axis. + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + /// @see - scale(tmat4x4<T, P> const & m, T x, T y, T z) + /// @see - scale(tvec3<T, P> const & v) + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> scale( + tmat4x4<T, P> const & m, + tvec3<T, P> const & v); + + /// Creates a matrix for an orthographic parallel viewing volume. + /// + /// @param left + /// @param right + /// @param bottom + /// @param top + /// @param zNear + /// @param zFar + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + /// @see - glm::ortho(T const & left, T const & right, T const & bottom, T const & top) + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> ortho( + T left, + T right, + T bottom, + T top, + T zNear, + T zFar); + + /// Creates a matrix for projecting two-dimensional coordinates onto the screen. + /// + /// @param left + /// @param right + /// @param bottom + /// @param top + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + /// @see - glm::ortho(T const & left, T const & right, T const & bottom, T const & top, T const & zNear, T const & zFar) + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> ortho( + T left, + T right, + T bottom, + T top); + + /// Creates a frustum matrix. + /// + /// @param left + /// @param right + /// @param bottom + /// @param top + /// @param near + /// @param far + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> frustum( + T left, + T right, + T bottom, + T top, + T near, + T far); + + /// Creates a matrix for a symetric perspective-view frustum. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> perspective( + T fovy, + T aspect, + T near, + T far); + + /// Builds a perspective projection matrix based on a field of view. + /// + /// @param fov Expressed in radians. + /// @param width + /// @param height + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param far Specifies the distance from the viewer to the far clipping plane (always positive). + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> perspectiveFov( + T fov, + T width, + T height, + T near, + T far); + + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> infinitePerspective( + T fovy, T aspect, T near); + + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite for graphics hardware that doesn't support depth clamping. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> tweakedInfinitePerspective( + T fovy, T aspect, T near); + + /// Creates a matrix for a symmetric perspective-view frustum with far plane at infinite for graphics hardware that doesn't support depth clamping. + /// + /// @param fovy Specifies the field of view angle, in degrees, in the y direction. Expressed in radians. + /// @param aspect Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height). + /// @param near Specifies the distance from the viewer to the near clipping plane (always positive). + /// @param ep + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// @see gtc_matrix_transform + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> tweakedInfinitePerspective( + T fovy, T aspect, T near, T ep); + + /// Map the specified object coordinates (obj.x, obj.y, obj.z) into window coordinates. + /// + /// @param obj Specify the object coordinates. + /// @param model Specifies the current modelview matrix + /// @param proj Specifies the current projection matrix + /// @param viewport Specifies the current viewport + /// @return Return the computed window coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommanded), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// @see gtc_matrix_transform + template <typename T, typename U, precision P> + GLM_FUNC_DECL tvec3<T, P> project( + tvec3<T, P> const & obj, + tmat4x4<T, P> const & model, + tmat4x4<T, P> const & proj, + tvec4<U, P> const & viewport); + + /// Map the specified window coordinates (win.x, win.y, win.z) into object coordinates. + /// + /// @param win Specify the window coordinates to be mapped. + /// @param model Specifies the modelview matrix + /// @param proj Specifies the projection matrix + /// @param viewport Specifies the viewport + /// @return Returns the computed object coordinates. + /// @tparam T Native type used for the computation. Currently supported: half (not recommanded), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// @see gtc_matrix_transform + template <typename T, typename U, precision P> + GLM_FUNC_DECL tvec3<T, P> unProject( + tvec3<T, P> const & win, + tmat4x4<T, P> const & model, + tmat4x4<T, P> const & proj, + tvec4<U, P> const & viewport); + + /// Define a picking region + /// + /// @param center + /// @param delta + /// @param viewport + /// @tparam T Native type used for the computation. Currently supported: half (not recommanded), float or double. + /// @tparam U Currently supported: Floating-point types and integer types. + /// @see gtc_matrix_transform + template <typename T, precision P, typename U> + GLM_FUNC_DECL tmat4x4<T, P> pickMatrix( + tvec2<T, P> const & center, + tvec2<T, P> const & delta, + tvec4<U, P> const & viewport); + + /// Build a look at view matrix. + /// + /// @param eye Position of the camera + /// @param center Position where the camera is looking at + /// @param up Normalized up vector, how the camera is oriented. Typically (0, 0, 1) + /// @see gtc_matrix_transform + /// @see - frustum(T const & left, T const & right, T const & bottom, T const & top, T const & nearVal, T const & farVal) frustum(T const & left, T const & right, T const & bottom, T const & top, T const & nearVal, T const & farVal) + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> lookAt( + tvec3<T, P> const & eye, + tvec3<T, P> const & center, + tvec3<T, P> const & up); + + /// @} +}//namespace glm + +#include "matrix_transform.inl" diff --git a/extensions/common/glm/gtc/matrix_transform.inl b/extensions/common/glm/gtc/matrix_transform.inl new file mode 100644 index 0000000000..ac7ad093d4 --- /dev/null +++ b/extensions/common/glm/gtc/matrix_transform.inl @@ -0,0 +1,413 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_matrix_transform +/// @file glm/gtc/matrix_transform.inl +/// @date 2009-04-29 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "../geometric.hpp" +#include "../trigonometric.hpp" +#include "../matrix.hpp" + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> translate + ( + tmat4x4<T, P> const & m, + tvec3<T, P> const & v + ) + { + tmat4x4<T, P> Result(m); + Result[3] = m[0] * v[0] + m[1] * v[1] + m[2] * v[2] + m[3]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> rotate + ( + tmat4x4<T, P> const & m, + T angle, + tvec3<T, P> const & v + ) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + + tvec3<T, P> axis(normalize(v)); + tvec3<T, P> temp((T(1) - c) * axis); + + tmat4x4<T, P> Rotate(uninitialize); + Rotate[0][0] = c + temp[0] * axis[0]; + Rotate[0][1] = 0 + temp[0] * axis[1] + s * axis[2]; + Rotate[0][2] = 0 + temp[0] * axis[2] - s * axis[1]; + + Rotate[1][0] = 0 + temp[1] * axis[0] - s * axis[2]; + Rotate[1][1] = c + temp[1] * axis[1]; + Rotate[1][2] = 0 + temp[1] * axis[2] + s * axis[0]; + + Rotate[2][0] = 0 + temp[2] * axis[0] + s * axis[1]; + Rotate[2][1] = 0 + temp[2] * axis[1] - s * axis[0]; + Rotate[2][2] = c + temp[2] * axis[2]; + + tmat4x4<T, P> Result(uninitialize); + Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2]; + Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2]; + Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2]; + Result[3] = m[3]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> rotate_slow + ( + tmat4x4<T, P> const & m, + T angle, + tvec3<T, P> const & v + ) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + tmat4x4<T, P> Result; + + tvec3<T, P> axis = normalize(v); + + Result[0][0] = c + (1 - c) * axis.x * axis.x; + Result[0][1] = (1 - c) * axis.x * axis.y + s * axis.z; + Result[0][2] = (1 - c) * axis.x * axis.z - s * axis.y; + Result[0][3] = 0; + + Result[1][0] = (1 - c) * axis.y * axis.x - s * axis.z; + Result[1][1] = c + (1 - c) * axis.y * axis.y; + Result[1][2] = (1 - c) * axis.y * axis.z + s * axis.x; + Result[1][3] = 0; + + Result[2][0] = (1 - c) * axis.z * axis.x + s * axis.y; + Result[2][1] = (1 - c) * axis.z * axis.y - s * axis.x; + Result[2][2] = c + (1 - c) * axis.z * axis.z; + Result[2][3] = 0; + + Result[3] = tvec4<T, P>(0, 0, 0, 1); + return m * Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> scale + ( + tmat4x4<T, P> const & m, + tvec3<T, P> const & v + ) + { + tmat4x4<T, P> Result(uninitialize); + Result[0] = m[0] * v[0]; + Result[1] = m[1] * v[1]; + Result[2] = m[2] * v[2]; + Result[3] = m[3]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> scale_slow + ( + tmat4x4<T, P> const & m, + tvec3<T, P> const & v + ) + { + tmat4x4<T, P> Result(T(1)); + Result[0][0] = v.x; + Result[1][1] = v.y; + Result[2][2] = v.z; + return m * Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> ortho + ( + T left, + T right, + T bottom, + T top, + T zNear, + T zFar + ) + { + tmat4x4<T, defaultp> Result(1); + Result[0][0] = static_cast<T>(2) / (right - left); + Result[1][1] = static_cast<T>(2) / (top - bottom); + Result[2][2] = - static_cast<T>(2) / (zFar - zNear); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + Result[3][2] = - (zFar + zNear) / (zFar - zNear); + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> ortho + ( + T left, + T right, + T bottom, + T top + ) + { + tmat4x4<T, defaultp> Result(1); + Result[0][0] = static_cast<T>(2) / (right - left); + Result[1][1] = static_cast<T>(2) / (top - bottom); + Result[2][2] = - static_cast<T>(1); + Result[3][0] = - (right + left) / (right - left); + Result[3][1] = - (top + bottom) / (top - bottom); + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> frustum + ( + T left, + T right, + T bottom, + T top, + T nearVal, + T farVal + ) + { + tmat4x4<T, defaultp> Result(0); + Result[0][0] = (static_cast<T>(2) * nearVal) / (right - left); + Result[1][1] = (static_cast<T>(2) * nearVal) / (top - bottom); + Result[2][0] = (right + left) / (right - left); + Result[2][1] = (top + bottom) / (top - bottom); + Result[2][2] = -(farVal + nearVal) / (farVal - nearVal); + Result[2][3] = static_cast<T>(-1); + Result[3][2] = -(static_cast<T>(2) * farVal * nearVal) / (farVal - nearVal); + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> perspective + ( + T fovy, + T aspect, + T zNear, + T zFar + ) + { + assert(abs(aspect - std::numeric_limits<T>::epsilon()) > static_cast<T>(0)); + + T const tanHalfFovy = tan(fovy / static_cast<T>(2)); + + tmat4x4<T, defaultp> Result(static_cast<T>(0)); + Result[0][0] = static_cast<T>(1) / (aspect * tanHalfFovy); + Result[1][1] = static_cast<T>(1) / (tanHalfFovy); + Result[2][2] = - (zFar + zNear) / (zFar - zNear); + Result[2][3] = - static_cast<T>(1); + Result[3][2] = - (static_cast<T>(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> perspectiveFov + ( + T fov, + T width, + T height, + T zNear, + T zFar + ) + { + assert(width > static_cast<T>(0)); + assert(height > static_cast<T>(0)); + assert(fov > static_cast<T>(0)); + + T const rad = fov; + T const h = glm::cos(static_cast<T>(0.5) * rad) / glm::sin(static_cast<T>(0.5) * rad); + T const w = h * height / width; ///todo max(width , Height) / min(width , Height)? + + tmat4x4<T, defaultp> Result(static_cast<T>(0)); + Result[0][0] = w; + Result[1][1] = h; + Result[2][2] = - (zFar + zNear) / (zFar - zNear); + Result[2][3] = - static_cast<T>(1); + Result[3][2] = - (static_cast<T>(2) * zFar * zNear) / (zFar - zNear); + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> infinitePerspective + ( + T fovy, + T aspect, + T zNear + ) + { + T const range = tan(fovy / T(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + tmat4x4<T, defaultp> Result(T(0)); + Result[0][0] = (T(2) * zNear) / (right - left); + Result[1][1] = (T(2) * zNear) / (top - bottom); + Result[2][2] = - T(1); + Result[2][3] = - T(1); + Result[3][2] = - T(2) * zNear; + return Result; + } + + // Infinite projection matrix: http://www.terathon.com/gdc07_lengyel.pdf + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> tweakedInfinitePerspective + ( + T fovy, + T aspect, + T zNear, + T ep + ) + { + T const range = tan(fovy / T(2)) * zNear; + T const left = -range * aspect; + T const right = range * aspect; + T const bottom = -range; + T const top = range; + + tmat4x4<T, defaultp> Result(T(0)); + Result[0][0] = (static_cast<T>(2) * zNear) / (right - left); + Result[1][1] = (static_cast<T>(2) * zNear) / (top - bottom); + Result[2][2] = ep - static_cast<T>(1); + Result[2][3] = static_cast<T>(-1); + Result[3][2] = (ep - static_cast<T>(2)) * zNear; + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> tweakedInfinitePerspective + ( + T fovy, + T aspect, + T zNear + ) + { + return tweakedInfinitePerspective(fovy, aspect, zNear, epsilon<T>()); + } + + template <typename T, typename U, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> project + ( + tvec3<T, P> const & obj, + tmat4x4<T, P> const & model, + tmat4x4<T, P> const & proj, + tvec4<U, P> const & viewport + ) + { + tvec4<T, P> tmp = tvec4<T, P>(obj, T(1)); + tmp = model * tmp; + tmp = proj * tmp; + + tmp /= tmp.w; + tmp = tmp * T(0.5) + T(0.5); + tmp[0] = tmp[0] * T(viewport[2]) + T(viewport[0]); + tmp[1] = tmp[1] * T(viewport[3]) + T(viewport[1]); + + return tvec3<T, P>(tmp); + } + + template <typename T, typename U, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> unProject + ( + tvec3<T, P> const & win, + tmat4x4<T, P> const & model, + tmat4x4<T, P> const & proj, + tvec4<U, P> const & viewport + ) + { + tmat4x4<T, P> Inverse = inverse(proj * model); + + tvec4<T, P> tmp = tvec4<T, P>(win, T(1)); + tmp.x = (tmp.x - T(viewport[0])) / T(viewport[2]); + tmp.y = (tmp.y - T(viewport[1])) / T(viewport[3]); + tmp = tmp * T(2) - T(1); + + tvec4<T, P> obj = Inverse * tmp; + obj /= obj.w; + + return tvec3<T, P>(obj); + } + + template <typename T, precision P, typename U> + GLM_FUNC_QUALIFIER tmat4x4<T, P> pickMatrix + ( + tvec2<T, P> const & center, + tvec2<T, P> const & delta, + tvec4<U, P> const & viewport + ) + { + assert(delta.x > T(0) && delta.y > T(0)); + tmat4x4<T, P> Result(1.0f); + + if(!(delta.x > T(0) && delta.y > T(0))) + return Result; // Error + + tvec3<T, P> Temp( + (T(viewport[2]) - T(2) * (center.x - T(viewport[0]))) / delta.x, + (T(viewport[3]) - T(2) * (center.y - T(viewport[1]))) / delta.y, + T(0)); + + // Translate and scale the picked region to the entire window + Result = translate(Result, Temp); + return scale(Result, tvec3<T, P>(T(viewport[2]) / delta.x, T(viewport[3]) / delta.y, T(1))); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> lookAt + ( + tvec3<T, P> const & eye, + tvec3<T, P> const & center, + tvec3<T, P> const & up + ) + { + tvec3<T, P> const f(normalize(center - eye)); + tvec3<T, P> const s(normalize(cross(f, up))); + tvec3<T, P> const u(cross(s, f)); + + tmat4x4<T, P> Result(1); + Result[0][0] = s.x; + Result[1][0] = s.y; + Result[2][0] = s.z; + Result[0][1] = u.x; + Result[1][1] = u.y; + Result[2][1] = u.z; + Result[0][2] =-f.x; + Result[1][2] =-f.y; + Result[2][2] =-f.z; + Result[3][0] =-dot(s, eye); + Result[3][1] =-dot(u, eye); + Result[3][2] = dot(f, eye); + return Result; + } +}//namespace glm diff --git a/extensions/common/glm/gtc/noise.hpp b/extensions/common/glm/gtc/noise.hpp new file mode 100644 index 0000000000..adb82ae238 --- /dev/null +++ b/extensions/common/glm/gtc/noise.hpp @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_noise +/// @file glm/gtc/noise.hpp +/// @date 2011-04-21 / 2011-09-27 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtc_noise GLM_GTC_noise +/// @ingroup gtc +/// +/// Defines 2D, 3D and 4D procedural noise functions +/// Based on the work of Stefan Gustavson and Ashima Arts on "webgl-noise": +/// https://github.com/ashima/webgl-noise +/// Following Stefan Gustavson's paper "Simplex noise demystified": +/// http://www.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf +/// <glm/gtc/noise.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/precision.hpp" +#include "../detail/_noise.hpp" +#include "../geometric.hpp" +#include "../common.hpp" +#include "../vector_relational.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_noise extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_noise + /// @{ + + /// Classic perlin noise. + /// @see gtc_noise + template <typename T, precision P, template<typename, precision> class vecType> + GLM_FUNC_DECL T perlin( + vecType<T, P> const & p); + + /// Periodic perlin noise. + /// @see gtc_noise + template <typename T, precision P, template<typename, precision> class vecType> + GLM_FUNC_DECL T perlin( + vecType<T, P> const & p, + vecType<T, P> const & rep); + + /// Simplex noise. + /// @see gtc_noise + template <typename T, precision P, template<typename, precision> class vecType> + GLM_FUNC_DECL T simplex( + vecType<T, P> const & p); + + /// @} +}//namespace glm + +#include "noise.inl" diff --git a/extensions/common/glm/gtc/noise.inl b/extensions/common/glm/gtc/noise.inl new file mode 100644 index 0000000000..00ff073619 --- /dev/null +++ b/extensions/common/glm/gtc/noise.inl @@ -0,0 +1,837 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_noise +/// @file glm/gtc/noise.inl +/// @date 2011-04-21 / 2012-04-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// +// Based on the work of Stefan Gustavson and Ashima Arts on "webgl-noise": +// https://github.com/ashima/webgl-noise +// Following Stefan Gustavson's paper "Simplex noise demystified": +// http://www.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace gtc +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> grad4(T const & j, tvec4<T, P> const & ip) + { + tvec3<T, P> pXYZ = floor(fract(tvec3<T, P>(j) * tvec3<T, P>(ip)) * T(7)) * ip[2] - T(1); + T pW = static_cast<T>(1.5) - dot(abs(pXYZ), tvec3<T, P>(1)); + tvec4<T, P> s = tvec4<T, P>(lessThan(tvec4<T, P>(pXYZ, pW), tvec4<T, P>(0.0))); + pXYZ = pXYZ + (tvec3<T, P>(s) * T(2) - T(1)) * s.w; + return tvec4<T, P>(pXYZ, pW); + } +}//namespace gtc + + // Classic Perlin noise + template <typename T, precision P> + GLM_FUNC_QUALIFIER T perlin(tvec2<T, P> const & Position) + { + tvec4<T, P> Pi = glm::floor(tvec4<T, P>(Position.x, Position.y, Position.x, Position.y)) + tvec4<T, P>(0.0, 0.0, 1.0, 1.0); + tvec4<T, P> Pf = glm::fract(tvec4<T, P>(Position.x, Position.y, Position.x, Position.y)) - tvec4<T, P>(0.0, 0.0, 1.0, 1.0); + Pi = mod(Pi, tvec4<T, P>(289)); // To avoid truncation effects in permutation + tvec4<T, P> ix(Pi.x, Pi.z, Pi.x, Pi.z); + tvec4<T, P> iy(Pi.y, Pi.y, Pi.w, Pi.w); + tvec4<T, P> fx(Pf.x, Pf.z, Pf.x, Pf.z); + tvec4<T, P> fy(Pf.y, Pf.y, Pf.w, Pf.w); + + tvec4<T, P> i = detail::permute(detail::permute(ix) + iy); + + tvec4<T, P> gx = static_cast<T>(2) * glm::fract(i / T(41)) - T(1); + tvec4<T, P> gy = glm::abs(gx) - T(0.5); + tvec4<T, P> tx = glm::floor(gx + T(0.5)); + gx = gx - tx; + + tvec2<T, P> g00(gx.x, gy.x); + tvec2<T, P> g10(gx.y, gy.y); + tvec2<T, P> g01(gx.z, gy.z); + tvec2<T, P> g11(gx.w, gy.w); + + tvec4<T, P> norm = detail::taylorInvSqrt(tvec4<T, P>(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11))); + g00 *= norm.x; + g01 *= norm.y; + g10 *= norm.z; + g11 *= norm.w; + + T n00 = dot(g00, tvec2<T, P>(fx.x, fy.x)); + T n10 = dot(g10, tvec2<T, P>(fx.y, fy.y)); + T n01 = dot(g01, tvec2<T, P>(fx.z, fy.z)); + T n11 = dot(g11, tvec2<T, P>(fx.w, fy.w)); + + tvec2<T, P> fade_xy = detail::fade(tvec2<T, P>(Pf.x, Pf.y)); + tvec2<T, P> n_x = mix(tvec2<T, P>(n00, n01), tvec2<T, P>(n10, n11), fade_xy.x); + T n_xy = mix(n_x.x, n_x.y, fade_xy.y); + return T(2.3) * n_xy; + } + + // Classic Perlin noise + template <typename T, precision P> + GLM_FUNC_QUALIFIER T perlin(tvec3<T, P> const & Position) + { + tvec3<T, P> Pi0 = floor(Position); // Integer part for indexing + tvec3<T, P> Pi1 = Pi0 + T(1); // Integer part + 1 + Pi0 = detail::mod289(Pi0); + Pi1 = detail::mod289(Pi1); + tvec3<T, P> Pf0 = fract(Position); // Fractional part for interpolation + tvec3<T, P> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + tvec4<T, P> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + tvec4<T, P> iy = tvec4<T, P>(tvec2<T, P>(Pi0.y), tvec2<T, P>(Pi1.y)); + tvec4<T, P> iz0(Pi0.z); + tvec4<T, P> iz1(Pi1.z); + + tvec4<T, P> ixy = detail::permute(detail::permute(ix) + iy); + tvec4<T, P> ixy0 = detail::permute(ixy + iz0); + tvec4<T, P> ixy1 = detail::permute(ixy + iz1); + + tvec4<T, P> gx0 = ixy0 * T(1.0 / 7.0); + tvec4<T, P> gy0 = fract(floor(gx0) * T(1.0 / 7.0)) - T(0.5); + gx0 = fract(gx0); + tvec4<T, P> gz0 = tvec4<T, P>(0.5) - abs(gx0) - abs(gy0); + tvec4<T, P> sz0 = step(gz0, tvec4<T, P>(0.0)); + gx0 -= sz0 * (step(T(0), gx0) - T(0.5)); + gy0 -= sz0 * (step(T(0), gy0) - T(0.5)); + + tvec4<T, P> gx1 = ixy1 * T(1.0 / 7.0); + tvec4<T, P> gy1 = fract(floor(gx1) * T(1.0 / 7.0)) - T(0.5); + gx1 = fract(gx1); + tvec4<T, P> gz1 = tvec4<T, P>(0.5) - abs(gx1) - abs(gy1); + tvec4<T, P> sz1 = step(gz1, tvec4<T, P>(0.0)); + gx1 -= sz1 * (step(T(0), gx1) - T(0.5)); + gy1 -= sz1 * (step(T(0), gy1) - T(0.5)); + + tvec3<T, P> g000(gx0.x, gy0.x, gz0.x); + tvec3<T, P> g100(gx0.y, gy0.y, gz0.y); + tvec3<T, P> g010(gx0.z, gy0.z, gz0.z); + tvec3<T, P> g110(gx0.w, gy0.w, gz0.w); + tvec3<T, P> g001(gx1.x, gy1.x, gz1.x); + tvec3<T, P> g101(gx1.y, gy1.y, gz1.y); + tvec3<T, P> g011(gx1.z, gy1.z, gz1.z); + tvec3<T, P> g111(gx1.w, gy1.w, gz1.w); + + tvec4<T, P> norm0 = detail::taylorInvSqrt(tvec4<T, P>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + tvec4<T, P> norm1 = detail::taylorInvSqrt(tvec4<T, P>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + T n000 = dot(g000, Pf0); + T n100 = dot(g100, tvec3<T, P>(Pf1.x, Pf0.y, Pf0.z)); + T n010 = dot(g010, tvec3<T, P>(Pf0.x, Pf1.y, Pf0.z)); + T n110 = dot(g110, tvec3<T, P>(Pf1.x, Pf1.y, Pf0.z)); + T n001 = dot(g001, tvec3<T, P>(Pf0.x, Pf0.y, Pf1.z)); + T n101 = dot(g101, tvec3<T, P>(Pf1.x, Pf0.y, Pf1.z)); + T n011 = dot(g011, tvec3<T, P>(Pf0.x, Pf1.y, Pf1.z)); + T n111 = dot(g111, Pf1); + + tvec3<T, P> fade_xyz = detail::fade(Pf0); + tvec4<T, P> n_z = mix(tvec4<T, P>(n000, n100, n010, n110), tvec4<T, P>(n001, n101, n011, n111), fade_xyz.z); + tvec2<T, P> n_yz = mix(tvec2<T, P>(n_z.x, n_z.y), tvec2<T, P>(n_z.z, n_z.w), fade_xyz.y); + T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return T(2.2) * n_xyz; + } + /* + // Classic Perlin noise + template <typename T, precision P> + GLM_FUNC_QUALIFIER T perlin(tvec3<T, P> const & P) + { + tvec3<T, P> Pi0 = floor(P); // Integer part for indexing + tvec3<T, P> Pi1 = Pi0 + T(1); // Integer part + 1 + Pi0 = mod(Pi0, T(289)); + Pi1 = mod(Pi1, T(289)); + tvec3<T, P> Pf0 = fract(P); // Fractional part for interpolation + tvec3<T, P> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + tvec4<T, P> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + tvec4<T, P> iy(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + tvec4<T, P> iz0(Pi0.z); + tvec4<T, P> iz1(Pi1.z); + + tvec4<T, P> ixy = permute(permute(ix) + iy); + tvec4<T, P> ixy0 = permute(ixy + iz0); + tvec4<T, P> ixy1 = permute(ixy + iz1); + + tvec4<T, P> gx0 = ixy0 / T(7); + tvec4<T, P> gy0 = fract(floor(gx0) / T(7)) - T(0.5); + gx0 = fract(gx0); + tvec4<T, P> gz0 = tvec4<T, P>(0.5) - abs(gx0) - abs(gy0); + tvec4<T, P> sz0 = step(gz0, tvec4<T, P>(0.0)); + gx0 -= sz0 * (step(0.0, gx0) - T(0.5)); + gy0 -= sz0 * (step(0.0, gy0) - T(0.5)); + + tvec4<T, P> gx1 = ixy1 / T(7); + tvec4<T, P> gy1 = fract(floor(gx1) / T(7)) - T(0.5); + gx1 = fract(gx1); + tvec4<T, P> gz1 = tvec4<T, P>(0.5) - abs(gx1) - abs(gy1); + tvec4<T, P> sz1 = step(gz1, tvec4<T, P>(0.0)); + gx1 -= sz1 * (step(T(0), gx1) - T(0.5)); + gy1 -= sz1 * (step(T(0), gy1) - T(0.5)); + + tvec3<T, P> g000(gx0.x, gy0.x, gz0.x); + tvec3<T, P> g100(gx0.y, gy0.y, gz0.y); + tvec3<T, P> g010(gx0.z, gy0.z, gz0.z); + tvec3<T, P> g110(gx0.w, gy0.w, gz0.w); + tvec3<T, P> g001(gx1.x, gy1.x, gz1.x); + tvec3<T, P> g101(gx1.y, gy1.y, gz1.y); + tvec3<T, P> g011(gx1.z, gy1.z, gz1.z); + tvec3<T, P> g111(gx1.w, gy1.w, gz1.w); + + tvec4<T, P> norm0 = taylorInvSqrt(tvec4<T, P>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + tvec4<T, P> norm1 = taylorInvSqrt(tvec4<T, P>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + T n000 = dot(g000, Pf0); + T n100 = dot(g100, tvec3<T, P>(Pf1.x, Pf0.y, Pf0.z)); + T n010 = dot(g010, tvec3<T, P>(Pf0.x, Pf1.y, Pf0.z)); + T n110 = dot(g110, tvec3<T, P>(Pf1.x, Pf1.y, Pf0.z)); + T n001 = dot(g001, tvec3<T, P>(Pf0.x, Pf0.y, Pf1.z)); + T n101 = dot(g101, tvec3<T, P>(Pf1.x, Pf0.y, Pf1.z)); + T n011 = dot(g011, tvec3<T, P>(Pf0.x, Pf1.y, Pf1.z)); + T n111 = dot(g111, Pf1); + + tvec3<T, P> fade_xyz = fade(Pf0); + tvec4<T, P> n_z = mix(tvec4<T, P>(n000, n100, n010, n110), tvec4<T, P>(n001, n101, n011, n111), fade_xyz.z); + tvec2<T, P> n_yz = mix( + tvec2<T, P>(n_z.x, n_z.y), + tvec2<T, P>(n_z.z, n_z.w), fade_xyz.y); + T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return T(2.2) * n_xyz; + } + */ + // Classic Perlin noise + template <typename T, precision P> + GLM_FUNC_QUALIFIER T perlin(tvec4<T, P> const & Position) + { + tvec4<T, P> Pi0 = floor(Position); // Integer part for indexing + tvec4<T, P> Pi1 = Pi0 + T(1); // Integer part + 1 + Pi0 = mod(Pi0, tvec4<T, P>(289)); + Pi1 = mod(Pi1, tvec4<T, P>(289)); + tvec4<T, P> Pf0 = fract(Position); // Fractional part for interpolation + tvec4<T, P> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + tvec4<T, P> ix(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + tvec4<T, P> iy(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + tvec4<T, P> iz0(Pi0.z); + tvec4<T, P> iz1(Pi1.z); + tvec4<T, P> iw0(Pi0.w); + tvec4<T, P> iw1(Pi1.w); + + tvec4<T, P> ixy = detail::permute(detail::permute(ix) + iy); + tvec4<T, P> ixy0 = detail::permute(ixy + iz0); + tvec4<T, P> ixy1 = detail::permute(ixy + iz1); + tvec4<T, P> ixy00 = detail::permute(ixy0 + iw0); + tvec4<T, P> ixy01 = detail::permute(ixy0 + iw1); + tvec4<T, P> ixy10 = detail::permute(ixy1 + iw0); + tvec4<T, P> ixy11 = detail::permute(ixy1 + iw1); + + tvec4<T, P> gx00 = ixy00 / T(7); + tvec4<T, P> gy00 = floor(gx00) / T(7); + tvec4<T, P> gz00 = floor(gy00) / T(6); + gx00 = fract(gx00) - T(0.5); + gy00 = fract(gy00) - T(0.5); + gz00 = fract(gz00) - T(0.5); + tvec4<T, P> gw00 = tvec4<T, P>(0.75) - abs(gx00) - abs(gy00) - abs(gz00); + tvec4<T, P> sw00 = step(gw00, tvec4<T, P>(0.0)); + gx00 -= sw00 * (step(T(0), gx00) - T(0.5)); + gy00 -= sw00 * (step(T(0), gy00) - T(0.5)); + + tvec4<T, P> gx01 = ixy01 / T(7); + tvec4<T, P> gy01 = floor(gx01) / T(7); + tvec4<T, P> gz01 = floor(gy01) / T(6); + gx01 = fract(gx01) - T(0.5); + gy01 = fract(gy01) - T(0.5); + gz01 = fract(gz01) - T(0.5); + tvec4<T, P> gw01 = tvec4<T, P>(0.75) - abs(gx01) - abs(gy01) - abs(gz01); + tvec4<T, P> sw01 = step(gw01, tvec4<T, P>(0.0)); + gx01 -= sw01 * (step(T(0), gx01) - T(0.5)); + gy01 -= sw01 * (step(T(0), gy01) - T(0.5)); + + tvec4<T, P> gx10 = ixy10 / T(7); + tvec4<T, P> gy10 = floor(gx10) / T(7); + tvec4<T, P> gz10 = floor(gy10) / T(6); + gx10 = fract(gx10) - T(0.5); + gy10 = fract(gy10) - T(0.5); + gz10 = fract(gz10) - T(0.5); + tvec4<T, P> gw10 = tvec4<T, P>(0.75) - abs(gx10) - abs(gy10) - abs(gz10); + tvec4<T, P> sw10 = step(gw10, tvec4<T, P>(0)); + gx10 -= sw10 * (step(T(0), gx10) - T(0.5)); + gy10 -= sw10 * (step(T(0), gy10) - T(0.5)); + + tvec4<T, P> gx11 = ixy11 / T(7); + tvec4<T, P> gy11 = floor(gx11) / T(7); + tvec4<T, P> gz11 = floor(gy11) / T(6); + gx11 = fract(gx11) - T(0.5); + gy11 = fract(gy11) - T(0.5); + gz11 = fract(gz11) - T(0.5); + tvec4<T, P> gw11 = tvec4<T, P>(0.75) - abs(gx11) - abs(gy11) - abs(gz11); + tvec4<T, P> sw11 = step(gw11, tvec4<T, P>(0.0)); + gx11 -= sw11 * (step(T(0), gx11) - T(0.5)); + gy11 -= sw11 * (step(T(0), gy11) - T(0.5)); + + tvec4<T, P> g0000(gx00.x, gy00.x, gz00.x, gw00.x); + tvec4<T, P> g1000(gx00.y, gy00.y, gz00.y, gw00.y); + tvec4<T, P> g0100(gx00.z, gy00.z, gz00.z, gw00.z); + tvec4<T, P> g1100(gx00.w, gy00.w, gz00.w, gw00.w); + tvec4<T, P> g0010(gx10.x, gy10.x, gz10.x, gw10.x); + tvec4<T, P> g1010(gx10.y, gy10.y, gz10.y, gw10.y); + tvec4<T, P> g0110(gx10.z, gy10.z, gz10.z, gw10.z); + tvec4<T, P> g1110(gx10.w, gy10.w, gz10.w, gw10.w); + tvec4<T, P> g0001(gx01.x, gy01.x, gz01.x, gw01.x); + tvec4<T, P> g1001(gx01.y, gy01.y, gz01.y, gw01.y); + tvec4<T, P> g0101(gx01.z, gy01.z, gz01.z, gw01.z); + tvec4<T, P> g1101(gx01.w, gy01.w, gz01.w, gw01.w); + tvec4<T, P> g0011(gx11.x, gy11.x, gz11.x, gw11.x); + tvec4<T, P> g1011(gx11.y, gy11.y, gz11.y, gw11.y); + tvec4<T, P> g0111(gx11.z, gy11.z, gz11.z, gw11.z); + tvec4<T, P> g1111(gx11.w, gy11.w, gz11.w, gw11.w); + + tvec4<T, P> norm00 = detail::taylorInvSqrt(tvec4<T, P>(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100))); + g0000 *= norm00.x; + g0100 *= norm00.y; + g1000 *= norm00.z; + g1100 *= norm00.w; + + tvec4<T, P> norm01 = detail::taylorInvSqrt(tvec4<T, P>(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101))); + g0001 *= norm01.x; + g0101 *= norm01.y; + g1001 *= norm01.z; + g1101 *= norm01.w; + + tvec4<T, P> norm10 = detail::taylorInvSqrt(tvec4<T, P>(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110))); + g0010 *= norm10.x; + g0110 *= norm10.y; + g1010 *= norm10.z; + g1110 *= norm10.w; + + tvec4<T, P> norm11 = detail::taylorInvSqrt(tvec4<T, P>(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111))); + g0011 *= norm11.x; + g0111 *= norm11.y; + g1011 *= norm11.z; + g1111 *= norm11.w; + + T n0000 = dot(g0000, Pf0); + T n1000 = dot(g1000, tvec4<T, P>(Pf1.x, Pf0.y, Pf0.z, Pf0.w)); + T n0100 = dot(g0100, tvec4<T, P>(Pf0.x, Pf1.y, Pf0.z, Pf0.w)); + T n1100 = dot(g1100, tvec4<T, P>(Pf1.x, Pf1.y, Pf0.z, Pf0.w)); + T n0010 = dot(g0010, tvec4<T, P>(Pf0.x, Pf0.y, Pf1.z, Pf0.w)); + T n1010 = dot(g1010, tvec4<T, P>(Pf1.x, Pf0.y, Pf1.z, Pf0.w)); + T n0110 = dot(g0110, tvec4<T, P>(Pf0.x, Pf1.y, Pf1.z, Pf0.w)); + T n1110 = dot(g1110, tvec4<T, P>(Pf1.x, Pf1.y, Pf1.z, Pf0.w)); + T n0001 = dot(g0001, tvec4<T, P>(Pf0.x, Pf0.y, Pf0.z, Pf1.w)); + T n1001 = dot(g1001, tvec4<T, P>(Pf1.x, Pf0.y, Pf0.z, Pf1.w)); + T n0101 = dot(g0101, tvec4<T, P>(Pf0.x, Pf1.y, Pf0.z, Pf1.w)); + T n1101 = dot(g1101, tvec4<T, P>(Pf1.x, Pf1.y, Pf0.z, Pf1.w)); + T n0011 = dot(g0011, tvec4<T, P>(Pf0.x, Pf0.y, Pf1.z, Pf1.w)); + T n1011 = dot(g1011, tvec4<T, P>(Pf1.x, Pf0.y, Pf1.z, Pf1.w)); + T n0111 = dot(g0111, tvec4<T, P>(Pf0.x, Pf1.y, Pf1.z, Pf1.w)); + T n1111 = dot(g1111, Pf1); + + tvec4<T, P> fade_xyzw = detail::fade(Pf0); + tvec4<T, P> n_0w = mix(tvec4<T, P>(n0000, n1000, n0100, n1100), tvec4<T, P>(n0001, n1001, n0101, n1101), fade_xyzw.w); + tvec4<T, P> n_1w = mix(tvec4<T, P>(n0010, n1010, n0110, n1110), tvec4<T, P>(n0011, n1011, n0111, n1111), fade_xyzw.w); + tvec4<T, P> n_zw = mix(n_0w, n_1w, fade_xyzw.z); + tvec2<T, P> n_yzw = mix(tvec2<T, P>(n_zw.x, n_zw.y), tvec2<T, P>(n_zw.z, n_zw.w), fade_xyzw.y); + T n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x); + return T(2.2) * n_xyzw; + } + + // Classic Perlin noise, periodic variant + template <typename T, precision P> + GLM_FUNC_QUALIFIER T perlin(tvec2<T, P> const & Position, tvec2<T, P> const & rep) + { + tvec4<T, P> Pi = floor(tvec4<T, P>(Position.x, Position.y, Position.x, Position.y)) + tvec4<T, P>(0.0, 0.0, 1.0, 1.0); + tvec4<T, P> Pf = fract(tvec4<T, P>(Position.x, Position.y, Position.x, Position.y)) - tvec4<T, P>(0.0, 0.0, 1.0, 1.0); + Pi = mod(Pi, tvec4<T, P>(rep.x, rep.y, rep.x, rep.y)); // To create noise with explicit period + Pi = mod(Pi, tvec4<T, P>(289)); // To avoid truncation effects in permutation + tvec4<T, P> ix(Pi.x, Pi.z, Pi.x, Pi.z); + tvec4<T, P> iy(Pi.y, Pi.y, Pi.w, Pi.w); + tvec4<T, P> fx(Pf.x, Pf.z, Pf.x, Pf.z); + tvec4<T, P> fy(Pf.y, Pf.y, Pf.w, Pf.w); + + tvec4<T, P> i = detail::permute(detail::permute(ix) + iy); + + tvec4<T, P> gx = static_cast<T>(2) * fract(i / T(41)) - T(1); + tvec4<T, P> gy = abs(gx) - T(0.5); + tvec4<T, P> tx = floor(gx + T(0.5)); + gx = gx - tx; + + tvec2<T, P> g00(gx.x, gy.x); + tvec2<T, P> g10(gx.y, gy.y); + tvec2<T, P> g01(gx.z, gy.z); + tvec2<T, P> g11(gx.w, gy.w); + + tvec4<T, P> norm = detail::taylorInvSqrt(tvec4<T, P>(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11))); + g00 *= norm.x; + g01 *= norm.y; + g10 *= norm.z; + g11 *= norm.w; + + T n00 = dot(g00, tvec2<T, P>(fx.x, fy.x)); + T n10 = dot(g10, tvec2<T, P>(fx.y, fy.y)); + T n01 = dot(g01, tvec2<T, P>(fx.z, fy.z)); + T n11 = dot(g11, tvec2<T, P>(fx.w, fy.w)); + + tvec2<T, P> fade_xy = detail::fade(tvec2<T, P>(Pf.x, Pf.y)); + tvec2<T, P> n_x = mix(tvec2<T, P>(n00, n01), tvec2<T, P>(n10, n11), fade_xy.x); + T n_xy = mix(n_x.x, n_x.y, fade_xy.y); + return T(2.3) * n_xy; + } + + // Classic Perlin noise, periodic variant + template <typename T, precision P> + GLM_FUNC_QUALIFIER T perlin(tvec3<T, P> const & Position, tvec3<T, P> const & rep) + { + tvec3<T, P> Pi0 = mod(floor(Position), rep); // Integer part, modulo period + tvec3<T, P> Pi1 = mod(Pi0 + tvec3<T, P>(T(1)), rep); // Integer part + 1, mod period + Pi0 = mod(Pi0, tvec3<T, P>(289)); + Pi1 = mod(Pi1, tvec3<T, P>(289)); + tvec3<T, P> Pf0 = fract(Position); // Fractional part for interpolation + tvec3<T, P> Pf1 = Pf0 - tvec3<T, P>(T(1)); // Fractional part - 1.0 + tvec4<T, P> ix = tvec4<T, P>(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + tvec4<T, P> iy = tvec4<T, P>(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + tvec4<T, P> iz0(Pi0.z); + tvec4<T, P> iz1(Pi1.z); + + tvec4<T, P> ixy = detail::permute(detail::permute(ix) + iy); + tvec4<T, P> ixy0 = detail::permute(ixy + iz0); + tvec4<T, P> ixy1 = detail::permute(ixy + iz1); + + tvec4<T, P> gx0 = ixy0 / T(7); + tvec4<T, P> gy0 = fract(floor(gx0) / T(7)) - T(0.5); + gx0 = fract(gx0); + tvec4<T, P> gz0 = tvec4<T, P>(0.5) - abs(gx0) - abs(gy0); + tvec4<T, P> sz0 = step(gz0, tvec4<T, P>(0)); + gx0 -= sz0 * (step(T(0), gx0) - T(0.5)); + gy0 -= sz0 * (step(T(0), gy0) - T(0.5)); + + tvec4<T, P> gx1 = ixy1 / T(7); + tvec4<T, P> gy1 = fract(floor(gx1) / T(7)) - T(0.5); + gx1 = fract(gx1); + tvec4<T, P> gz1 = tvec4<T, P>(0.5) - abs(gx1) - abs(gy1); + tvec4<T, P> sz1 = step(gz1, tvec4<T, P>(T(0))); + gx1 -= sz1 * (step(T(0), gx1) - T(0.5)); + gy1 -= sz1 * (step(T(0), gy1) - T(0.5)); + + tvec3<T, P> g000 = tvec3<T, P>(gx0.x, gy0.x, gz0.x); + tvec3<T, P> g100 = tvec3<T, P>(gx0.y, gy0.y, gz0.y); + tvec3<T, P> g010 = tvec3<T, P>(gx0.z, gy0.z, gz0.z); + tvec3<T, P> g110 = tvec3<T, P>(gx0.w, gy0.w, gz0.w); + tvec3<T, P> g001 = tvec3<T, P>(gx1.x, gy1.x, gz1.x); + tvec3<T, P> g101 = tvec3<T, P>(gx1.y, gy1.y, gz1.y); + tvec3<T, P> g011 = tvec3<T, P>(gx1.z, gy1.z, gz1.z); + tvec3<T, P> g111 = tvec3<T, P>(gx1.w, gy1.w, gz1.w); + + tvec4<T, P> norm0 = detail::taylorInvSqrt(tvec4<T, P>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); + g000 *= norm0.x; + g010 *= norm0.y; + g100 *= norm0.z; + g110 *= norm0.w; + tvec4<T, P> norm1 = detail::taylorInvSqrt(tvec4<T, P>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); + g001 *= norm1.x; + g011 *= norm1.y; + g101 *= norm1.z; + g111 *= norm1.w; + + T n000 = dot(g000, Pf0); + T n100 = dot(g100, tvec3<T, P>(Pf1.x, Pf0.y, Pf0.z)); + T n010 = dot(g010, tvec3<T, P>(Pf0.x, Pf1.y, Pf0.z)); + T n110 = dot(g110, tvec3<T, P>(Pf1.x, Pf1.y, Pf0.z)); + T n001 = dot(g001, tvec3<T, P>(Pf0.x, Pf0.y, Pf1.z)); + T n101 = dot(g101, tvec3<T, P>(Pf1.x, Pf0.y, Pf1.z)); + T n011 = dot(g011, tvec3<T, P>(Pf0.x, Pf1.y, Pf1.z)); + T n111 = dot(g111, Pf1); + + tvec3<T, P> fade_xyz = detail::fade(Pf0); + tvec4<T, P> n_z = mix(tvec4<T, P>(n000, n100, n010, n110), tvec4<T, P>(n001, n101, n011, n111), fade_xyz.z); + tvec2<T, P> n_yz = mix(tvec2<T, P>(n_z.x, n_z.y), tvec2<T, P>(n_z.z, n_z.w), fade_xyz.y); + T n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); + return T(2.2) * n_xyz; + } + + // Classic Perlin noise, periodic version + template <typename T, precision P> + GLM_FUNC_QUALIFIER T perlin(tvec4<T, P> const & Position, tvec4<T, P> const & rep) + { + tvec4<T, P> Pi0 = mod(floor(Position), rep); // Integer part modulo rep + tvec4<T, P> Pi1 = mod(Pi0 + T(1), rep); // Integer part + 1 mod rep + tvec4<T, P> Pf0 = fract(Position); // Fractional part for interpolation + tvec4<T, P> Pf1 = Pf0 - T(1); // Fractional part - 1.0 + tvec4<T, P> ix = tvec4<T, P>(Pi0.x, Pi1.x, Pi0.x, Pi1.x); + tvec4<T, P> iy = tvec4<T, P>(Pi0.y, Pi0.y, Pi1.y, Pi1.y); + tvec4<T, P> iz0(Pi0.z); + tvec4<T, P> iz1(Pi1.z); + tvec4<T, P> iw0(Pi0.w); + tvec4<T, P> iw1(Pi1.w); + + tvec4<T, P> ixy = detail::permute(detail::permute(ix) + iy); + tvec4<T, P> ixy0 = detail::permute(ixy + iz0); + tvec4<T, P> ixy1 = detail::permute(ixy + iz1); + tvec4<T, P> ixy00 = detail::permute(ixy0 + iw0); + tvec4<T, P> ixy01 = detail::permute(ixy0 + iw1); + tvec4<T, P> ixy10 = detail::permute(ixy1 + iw0); + tvec4<T, P> ixy11 = detail::permute(ixy1 + iw1); + + tvec4<T, P> gx00 = ixy00 / T(7); + tvec4<T, P> gy00 = floor(gx00) / T(7); + tvec4<T, P> gz00 = floor(gy00) / T(6); + gx00 = fract(gx00) - T(0.5); + gy00 = fract(gy00) - T(0.5); + gz00 = fract(gz00) - T(0.5); + tvec4<T, P> gw00 = tvec4<T, P>(0.75) - abs(gx00) - abs(gy00) - abs(gz00); + tvec4<T, P> sw00 = step(gw00, tvec4<T, P>(0)); + gx00 -= sw00 * (step(T(0), gx00) - T(0.5)); + gy00 -= sw00 * (step(T(0), gy00) - T(0.5)); + + tvec4<T, P> gx01 = ixy01 / T(7); + tvec4<T, P> gy01 = floor(gx01) / T(7); + tvec4<T, P> gz01 = floor(gy01) / T(6); + gx01 = fract(gx01) - T(0.5); + gy01 = fract(gy01) - T(0.5); + gz01 = fract(gz01) - T(0.5); + tvec4<T, P> gw01 = tvec4<T, P>(0.75) - abs(gx01) - abs(gy01) - abs(gz01); + tvec4<T, P> sw01 = step(gw01, tvec4<T, P>(0.0)); + gx01 -= sw01 * (step(T(0), gx01) - T(0.5)); + gy01 -= sw01 * (step(T(0), gy01) - T(0.5)); + + tvec4<T, P> gx10 = ixy10 / T(7); + tvec4<T, P> gy10 = floor(gx10) / T(7); + tvec4<T, P> gz10 = floor(gy10) / T(6); + gx10 = fract(gx10) - T(0.5); + gy10 = fract(gy10) - T(0.5); + gz10 = fract(gz10) - T(0.5); + tvec4<T, P> gw10 = tvec4<T, P>(0.75) - abs(gx10) - abs(gy10) - abs(gz10); + tvec4<T, P> sw10 = step(gw10, tvec4<T, P>(0.0)); + gx10 -= sw10 * (step(T(0), gx10) - T(0.5)); + gy10 -= sw10 * (step(T(0), gy10) - T(0.5)); + + tvec4<T, P> gx11 = ixy11 / T(7); + tvec4<T, P> gy11 = floor(gx11) / T(7); + tvec4<T, P> gz11 = floor(gy11) / T(6); + gx11 = fract(gx11) - T(0.5); + gy11 = fract(gy11) - T(0.5); + gz11 = fract(gz11) - T(0.5); + tvec4<T, P> gw11 = tvec4<T, P>(0.75) - abs(gx11) - abs(gy11) - abs(gz11); + tvec4<T, P> sw11 = step(gw11, tvec4<T, P>(T(0))); + gx11 -= sw11 * (step(T(0), gx11) - T(0.5)); + gy11 -= sw11 * (step(T(0), gy11) - T(0.5)); + + tvec4<T, P> g0000(gx00.x, gy00.x, gz00.x, gw00.x); + tvec4<T, P> g1000(gx00.y, gy00.y, gz00.y, gw00.y); + tvec4<T, P> g0100(gx00.z, gy00.z, gz00.z, gw00.z); + tvec4<T, P> g1100(gx00.w, gy00.w, gz00.w, gw00.w); + tvec4<T, P> g0010(gx10.x, gy10.x, gz10.x, gw10.x); + tvec4<T, P> g1010(gx10.y, gy10.y, gz10.y, gw10.y); + tvec4<T, P> g0110(gx10.z, gy10.z, gz10.z, gw10.z); + tvec4<T, P> g1110(gx10.w, gy10.w, gz10.w, gw10.w); + tvec4<T, P> g0001(gx01.x, gy01.x, gz01.x, gw01.x); + tvec4<T, P> g1001(gx01.y, gy01.y, gz01.y, gw01.y); + tvec4<T, P> g0101(gx01.z, gy01.z, gz01.z, gw01.z); + tvec4<T, P> g1101(gx01.w, gy01.w, gz01.w, gw01.w); + tvec4<T, P> g0011(gx11.x, gy11.x, gz11.x, gw11.x); + tvec4<T, P> g1011(gx11.y, gy11.y, gz11.y, gw11.y); + tvec4<T, P> g0111(gx11.z, gy11.z, gz11.z, gw11.z); + tvec4<T, P> g1111(gx11.w, gy11.w, gz11.w, gw11.w); + + tvec4<T, P> norm00 = detail::taylorInvSqrt(tvec4<T, P>(dot(g0000, g0000), dot(g0100, g0100), dot(g1000, g1000), dot(g1100, g1100))); + g0000 *= norm00.x; + g0100 *= norm00.y; + g1000 *= norm00.z; + g1100 *= norm00.w; + + tvec4<T, P> norm01 = detail::taylorInvSqrt(tvec4<T, P>(dot(g0001, g0001), dot(g0101, g0101), dot(g1001, g1001), dot(g1101, g1101))); + g0001 *= norm01.x; + g0101 *= norm01.y; + g1001 *= norm01.z; + g1101 *= norm01.w; + + tvec4<T, P> norm10 = detail::taylorInvSqrt(tvec4<T, P>(dot(g0010, g0010), dot(g0110, g0110), dot(g1010, g1010), dot(g1110, g1110))); + g0010 *= norm10.x; + g0110 *= norm10.y; + g1010 *= norm10.z; + g1110 *= norm10.w; + + tvec4<T, P> norm11 = detail::taylorInvSqrt(tvec4<T, P>(dot(g0011, g0011), dot(g0111, g0111), dot(g1011, g1011), dot(g1111, g1111))); + g0011 *= norm11.x; + g0111 *= norm11.y; + g1011 *= norm11.z; + g1111 *= norm11.w; + + T n0000 = dot(g0000, Pf0); + T n1000 = dot(g1000, tvec4<T, P>(Pf1.x, Pf0.y, Pf0.z, Pf0.w)); + T n0100 = dot(g0100, tvec4<T, P>(Pf0.x, Pf1.y, Pf0.z, Pf0.w)); + T n1100 = dot(g1100, tvec4<T, P>(Pf1.x, Pf1.y, Pf0.z, Pf0.w)); + T n0010 = dot(g0010, tvec4<T, P>(Pf0.x, Pf0.y, Pf1.z, Pf0.w)); + T n1010 = dot(g1010, tvec4<T, P>(Pf1.x, Pf0.y, Pf1.z, Pf0.w)); + T n0110 = dot(g0110, tvec4<T, P>(Pf0.x, Pf1.y, Pf1.z, Pf0.w)); + T n1110 = dot(g1110, tvec4<T, P>(Pf1.x, Pf1.y, Pf1.z, Pf0.w)); + T n0001 = dot(g0001, tvec4<T, P>(Pf0.x, Pf0.y, Pf0.z, Pf1.w)); + T n1001 = dot(g1001, tvec4<T, P>(Pf1.x, Pf0.y, Pf0.z, Pf1.w)); + T n0101 = dot(g0101, tvec4<T, P>(Pf0.x, Pf1.y, Pf0.z, Pf1.w)); + T n1101 = dot(g1101, tvec4<T, P>(Pf1.x, Pf1.y, Pf0.z, Pf1.w)); + T n0011 = dot(g0011, tvec4<T, P>(Pf0.x, Pf0.y, Pf1.z, Pf1.w)); + T n1011 = dot(g1011, tvec4<T, P>(Pf1.x, Pf0.y, Pf1.z, Pf1.w)); + T n0111 = dot(g0111, tvec4<T, P>(Pf0.x, Pf1.y, Pf1.z, Pf1.w)); + T n1111 = dot(g1111, Pf1); + + tvec4<T, P> fade_xyzw = detail::fade(Pf0); + tvec4<T, P> n_0w = mix(tvec4<T, P>(n0000, n1000, n0100, n1100), tvec4<T, P>(n0001, n1001, n0101, n1101), fade_xyzw.w); + tvec4<T, P> n_1w = mix(tvec4<T, P>(n0010, n1010, n0110, n1110), tvec4<T, P>(n0011, n1011, n0111, n1111), fade_xyzw.w); + tvec4<T, P> n_zw = mix(n_0w, n_1w, fade_xyzw.z); + tvec2<T, P> n_yzw = mix(tvec2<T, P>(n_zw.x, n_zw.y), tvec2<T, P>(n_zw.z, n_zw.w), fade_xyzw.y); + T n_xyzw = mix(n_yzw.x, n_yzw.y, fade_xyzw.x); + return T(2.2) * n_xyzw; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T simplex(glm::tvec2<T, P> const & v) + { + tvec4<T, P> const C = tvec4<T, P>( + T( 0.211324865405187), // (3.0 - sqrt(3.0)) / 6.0 + T( 0.366025403784439), // 0.5 * (sqrt(3.0) - 1.0) + T(-0.577350269189626), // -1.0 + 2.0 * C.x + T( 0.024390243902439)); // 1.0 / 41.0 + + // First corner + tvec2<T, P> i = floor(v + dot(v, tvec2<T, P>(C[1]))); + tvec2<T, P> x0 = v - i + dot(i, tvec2<T, P>(C[0])); + + // Other corners + //i1.x = step( x0.y, x0.x ); // x0.x > x0.y ? 1.0 : 0.0 + //i1.y = 1.0 - i1.x; + tvec2<T, P> i1 = (x0.x > x0.y) ? tvec2<T, P>(1, 0) : tvec2<T, P>(0, 1); + // x0 = x0 - 0.0 + 0.0 * C.xx ; + // x1 = x0 - i1 + 1.0 * C.xx ; + // x2 = x0 - 1.0 + 2.0 * C.xx ; + tvec4<T, P> x12 = tvec4<T, P>(x0.x, x0.y, x0.x, x0.y) + tvec4<T, P>(C.x, C.x, C.z, C.z); + x12 = tvec4<T, P>(tvec2<T, P>(x12) - i1, x12.z, x12.w); + + // Permutations + i = mod(i, tvec2<T, P>(289)); // Avoid truncation effects in permutation + tvec3<T, P> p = detail::permute( + detail::permute(i.y + tvec3<T, P>(T(0), i1.y, T(1))) + + i.x + tvec3<T, P>(T(0), i1.x, T(1))); + + tvec3<T, P> m = max(tvec3<T, P>(0.5) - tvec3<T, P>( + dot(x0, x0), + dot(tvec2<T, P>(x12.x, x12.y), tvec2<T, P>(x12.x, x12.y)), + dot(tvec2<T, P>(x12.z, x12.w), tvec2<T, P>(x12.z, x12.w))), tvec3<T, P>(0)); + m = m * m ; + m = m * m ; + + // Gradients: 41 points uniformly over a line, mapped onto a diamond. + // The ring size 17*17 = 289 is close to a multiple of 41 (41*7 = 287) + + tvec3<T, P> x = static_cast<T>(2) * fract(p * C.w) - T(1); + tvec3<T, P> h = abs(x) - T(0.5); + tvec3<T, P> ox = floor(x + T(0.5)); + tvec3<T, P> a0 = x - ox; + + // Normalise gradients implicitly by scaling m + // Inlined for speed: m *= taylorInvSqrt( a0*a0 + h*h ); + m *= static_cast<T>(1.79284291400159) - T(0.85373472095314) * (a0 * a0 + h * h); + + // Compute final noise value at P + tvec3<T, P> g; + g.x = a0.x * x0.x + h.x * x0.y; + //g.yz = a0.yz * x12.xz + h.yz * x12.yw; + g.y = a0.y * x12.x + h.y * x12.y; + g.z = a0.z * x12.z + h.z * x12.w; + return T(130) * dot(m, g); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T simplex(tvec3<T, P> const & v) + { + tvec2<T, P> const C(1.0 / 6.0, 1.0 / 3.0); + tvec4<T, P> const D(0.0, 0.5, 1.0, 2.0); + + // First corner + tvec3<T, P> i(floor(v + dot(v, tvec3<T, P>(C.y)))); + tvec3<T, P> x0(v - i + dot(i, tvec3<T, P>(C.x))); + + // Other corners + tvec3<T, P> g(step(tvec3<T, P>(x0.y, x0.z, x0.x), x0)); + tvec3<T, P> l(T(1) - g); + tvec3<T, P> i1(min(g, tvec3<T, P>(l.z, l.x, l.y))); + tvec3<T, P> i2(max(g, tvec3<T, P>(l.z, l.x, l.y))); + + // x0 = x0 - 0.0 + 0.0 * C.xxx; + // x1 = x0 - i1 + 1.0 * C.xxx; + // x2 = x0 - i2 + 2.0 * C.xxx; + // x3 = x0 - 1.0 + 3.0 * C.xxx; + tvec3<T, P> x1(x0 - i1 + C.x); + tvec3<T, P> x2(x0 - i2 + C.y); // 2.0*C.x = 1/3 = C.y + tvec3<T, P> x3(x0 - D.y); // -1.0+3.0*C.x = -0.5 = -D.y + + // Permutations + i = detail::mod289(i); + tvec4<T, P> p(detail::permute(detail::permute(detail::permute( + i.z + tvec4<T, P>(T(0), i1.z, i2.z, T(1))) + + i.y + tvec4<T, P>(T(0), i1.y, i2.y, T(1))) + + i.x + tvec4<T, P>(T(0), i1.x, i2.x, T(1)))); + + // Gradients: 7x7 points over a square, mapped onto an octahedron. + // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294) + T n_ = static_cast<T>(0.142857142857); // 1.0/7.0 + tvec3<T, P> ns(n_ * tvec3<T, P>(D.w, D.y, D.z) - tvec3<T, P>(D.x, D.z, D.x)); + + tvec4<T, P> j(p - T(49) * floor(p * ns.z * ns.z)); // mod(p,7*7) + + tvec4<T, P> x_(floor(j * ns.z)); + tvec4<T, P> y_(floor(j - T(7) * x_)); // mod(j,N) + + tvec4<T, P> x(x_ * ns.x + ns.y); + tvec4<T, P> y(y_ * ns.x + ns.y); + tvec4<T, P> h(T(1) - abs(x) - abs(y)); + + tvec4<T, P> b0(x.x, x.y, y.x, y.y); + tvec4<T, P> b1(x.z, x.w, y.z, y.w); + + // vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0; + // vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0; + tvec4<T, P> s0(floor(b0) * T(2) + T(1)); + tvec4<T, P> s1(floor(b1) * T(2) + T(1)); + tvec4<T, P> sh(-step(h, tvec4<T, P>(0.0))); + + tvec4<T, P> a0 = tvec4<T, P>(b0.x, b0.z, b0.y, b0.w) + tvec4<T, P>(s0.x, s0.z, s0.y, s0.w) * tvec4<T, P>(sh.x, sh.x, sh.y, sh.y); + tvec4<T, P> a1 = tvec4<T, P>(b1.x, b1.z, b1.y, b1.w) + tvec4<T, P>(s1.x, s1.z, s1.y, s1.w) * tvec4<T, P>(sh.z, sh.z, sh.w, sh.w); + + tvec3<T, P> p0(a0.x, a0.y, h.x); + tvec3<T, P> p1(a0.z, a0.w, h.y); + tvec3<T, P> p2(a1.x, a1.y, h.z); + tvec3<T, P> p3(a1.z, a1.w, h.w); + + // Normalise gradients + tvec4<T, P> norm = detail::taylorInvSqrt(tvec4<T, P>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + + // Mix final noise value + tvec4<T, P> m = max(T(0.6) - tvec4<T, P>(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), tvec4<T, P>(0)); + m = m * m; + return T(42) * dot(m * m, tvec4<T, P>(dot(p0, x0), dot(p1, x1), dot(p2, x2), dot(p3, x3))); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T simplex(tvec4<T, P> const & v) + { + tvec4<T, P> const C( + 0.138196601125011, // (5 - sqrt(5))/20 G4 + 0.276393202250021, // 2 * G4 + 0.414589803375032, // 3 * G4 + -0.447213595499958); // -1 + 4 * G4 + + // (sqrt(5) - 1)/4 = F4, used once below + T const F4 = static_cast<T>(0.309016994374947451); + + // First corner + tvec4<T, P> i = floor(v + dot(v, vec4(F4))); + tvec4<T, P> x0 = v - i + dot(i, vec4(C.x)); + + // Other corners + + // Rank sorting originally contributed by Bill Licea-Kane, AMD (formerly ATI) + tvec4<T, P> i0; + tvec3<T, P> isX = step(tvec3<T, P>(x0.y, x0.z, x0.w), tvec3<T, P>(x0.x)); + tvec3<T, P> isYZ = step(tvec3<T, P>(x0.z, x0.w, x0.w), tvec3<T, P>(x0.y, x0.y, x0.z)); + // i0.x = dot(isX, vec3(1.0)); + //i0.x = isX.x + isX.y + isX.z; + //i0.yzw = static_cast<T>(1) - isX; + i0 = tvec4<T, P>(isX.x + isX.y + isX.z, T(1) - isX); + // i0.y += dot(isYZ.xy, vec2(1.0)); + i0.y += isYZ.x + isYZ.y; + //i0.zw += 1.0 - tvec2<T, P>(isYZ.x, isYZ.y); + i0.z += static_cast<T>(1) - isYZ.x; + i0.w += static_cast<T>(1) - isYZ.y; + i0.z += isYZ.z; + i0.w += static_cast<T>(1) - isYZ.z; + + // i0 now contains the unique values 0,1,2,3 in each channel + tvec4<T, P> i3 = clamp(i0, T(0), T(1)); + tvec4<T, P> i2 = clamp(i0 - T(1), T(0), T(1)); + tvec4<T, P> i1 = clamp(i0 - T(2), T(0), T(1)); + + // x0 = x0 - 0.0 + 0.0 * C.xxxx + // x1 = x0 - i1 + 0.0 * C.xxxx + // x2 = x0 - i2 + 0.0 * C.xxxx + // x3 = x0 - i3 + 0.0 * C.xxxx + // x4 = x0 - 1.0 + 4.0 * C.xxxx + tvec4<T, P> x1 = x0 - i1 + C.x; + tvec4<T, P> x2 = x0 - i2 + C.y; + tvec4<T, P> x3 = x0 - i3 + C.z; + tvec4<T, P> x4 = x0 + C.w; + + // Permutations + i = mod(i, tvec4<T, P>(289)); + T j0 = detail::permute(detail::permute(detail::permute(detail::permute(i.w) + i.z) + i.y) + i.x); + tvec4<T, P> j1 = detail::permute(detail::permute(detail::permute(detail::permute( + i.w + tvec4<T, P>(i1.w, i2.w, i3.w, T(1))) + + i.z + tvec4<T, P>(i1.z, i2.z, i3.z, T(1))) + + i.y + tvec4<T, P>(i1.y, i2.y, i3.y, T(1))) + + i.x + tvec4<T, P>(i1.x, i2.x, i3.x, T(1))); + + // Gradients: 7x7x6 points over a cube, mapped onto a 4-cross polytope + // 7*7*6 = 294, which is close to the ring size 17*17 = 289. + tvec4<T, P> ip = tvec4<T, P>(T(1) / T(294), T(1) / T(49), T(1) / T(7), T(0)); + + tvec4<T, P> p0 = gtc::grad4(j0, ip); + tvec4<T, P> p1 = gtc::grad4(j1.x, ip); + tvec4<T, P> p2 = gtc::grad4(j1.y, ip); + tvec4<T, P> p3 = gtc::grad4(j1.z, ip); + tvec4<T, P> p4 = gtc::grad4(j1.w, ip); + + // Normalise gradients + tvec4<T, P> norm = detail::taylorInvSqrt(tvec4<T, P>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3))); + p0 *= norm.x; + p1 *= norm.y; + p2 *= norm.z; + p3 *= norm.w; + p4 *= detail::taylorInvSqrt(dot(p4, p4)); + + // Mix contributions from the five corners + tvec3<T, P> m0 = max(T(0.6) - tvec3<T, P>(dot(x0, x0), dot(x1, x1), dot(x2, x2)), tvec3<T, P>(0)); + tvec2<T, P> m1 = max(T(0.6) - tvec2<T, P>(dot(x3, x3), dot(x4, x4) ), tvec2<T, P>(0)); + m0 = m0 * m0; + m1 = m1 * m1; + return T(49) * + (dot(m0 * m0, tvec3<T, P>(dot(p0, x0), dot(p1, x1), dot(p2, x2))) + + dot(m1 * m1, tvec2<T, P>(dot(p3, x3), dot(p4, x4)))); + } +}//namespace glm diff --git a/extensions/common/glm/gtc/packing.hpp b/extensions/common/glm/gtc/packing.hpp new file mode 100644 index 0000000000..e82d29b06d --- /dev/null +++ b/extensions/common/glm/gtc/packing.hpp @@ -0,0 +1,478 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_packing +/// @file glm/gtc/packing.hpp +/// @date 2013-08-08 / 2013-08-08 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtc_packing GLM_GTC_packing +/// @ingroup gtc +/// +/// @brief This extension provides a set of function to convert vertors to packed +/// formats. +/// +/// <glm/gtc/packing.hpp> need to be included to use these features. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "type_precision.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_packing extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_packing + /// @{ + + /// First, converts the normalized floating-point value v into a 8-bit integer value. + /// Then, the results are packed into the returned 8-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm1x8: round(clamp(c, 0, +1) * 255.0) + /// + /// @see gtc_packing + /// @see uint16 packUnorm2x8(vec2 const & v) + /// @see uint32 packUnorm4x8(vec4 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm4x8.xml">GLSL packUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint8 packUnorm1x8(float v); + + /// Convert a single 8-bit integer to a normalized floating-point value. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm4x8: f / 255.0 + /// + /// @see gtc_packing + /// @see vec2 unpackUnorm2x8(uint16 p) + /// @see vec4 unpackUnorm4x8(uint32 p) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm4x8.xml">GLSL unpackUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL float unpackUnorm1x8(uint8 p); + + /// First, converts each component of the normalized floating-point value v into 8-bit integer values. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm2x8: round(clamp(c, 0, +1) * 255.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint8 packUnorm1x8(float const & v) + /// @see uint32 packUnorm4x8(vec4 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm4x8.xml">GLSL packUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint16 packUnorm2x8(vec2 const & v); + + /// First, unpacks a single 16-bit unsigned integer p into a pair of 8-bit unsigned integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm4x8: f / 255.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackUnorm1x8(uint8 v) + /// @see vec4 unpackUnorm4x8(uint32 p) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm4x8.xml">GLSL unpackUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL vec2 unpackUnorm2x8(uint16 p); + + /// First, converts the normalized floating-point value v into 8-bit integer value. + /// Then, the results are packed into the returned 8-bit unsigned integer. + /// + /// The conversion to fixed point is done as follows: + /// packSnorm1x8: round(clamp(s, -1, +1) * 127.0) + /// + /// @see gtc_packing + /// @see uint16 packSnorm2x8(vec2 const & v) + /// @see uint32 packSnorm4x8(vec4 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm4x8.xml">GLSL packSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint8 packSnorm1x8(float s); + + /// First, unpacks a single 8-bit unsigned integer p into a single 8-bit signed integers. + /// Then, the value is converted to a normalized floating-point value to generate the returned scalar. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm1x8: clamp(f / 127.0, -1, +1) + /// + /// @see gtc_packing + /// @see vec2 unpackSnorm2x8(uint16 p) + /// @see vec4 unpackSnorm4x8(uint32 p) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm4x8.xml">GLSL unpackSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL float unpackSnorm1x8(uint8 p); + + /// First, converts each component of the normalized floating-point value v into 8-bit integer values. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm2x8: round(clamp(c, -1, +1) * 127.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint8 packSnorm1x8(float const & v) + /// @see uint32 packSnorm4x8(vec4 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm4x8.xml">GLSL packSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint16 packSnorm2x8(vec2 const & v); + + /// First, unpacks a single 16-bit unsigned integer p into a pair of 8-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned two-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm2x8: clamp(f / 127.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackSnorm1x8(uint8 p) + /// @see vec4 unpackSnorm4x8(uint32 p) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm4x8.xml">GLSL unpackSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL vec2 unpackSnorm2x8(uint16 p); + + /// First, converts the normalized floating-point value v into a 16-bit integer value. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm1x16: round(clamp(c, 0, +1) * 65535.0) + /// + /// @see gtc_packing + /// @see uint16 packSnorm1x16(float const & v) + /// @see uint64 packSnorm4x16(vec4 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm4x8.xml">GLSL packUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint16 packUnorm1x16(float v); + + /// First, unpacks a single 16-bit unsigned integer p into a of 16-bit unsigned integers. + /// Then, the value is converted to a normalized floating-point value to generate the returned scalar. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnorm1x16: f / 65535.0 + /// + /// @see gtc_packing + /// @see vec2 unpackUnorm2x16(uint32 p) + /// @see vec4 unpackUnorm4x16(uint64 p) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm2x16.xml">GLSL unpackUnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL float unpackUnorm1x16(uint16 p); + + /// First, converts each component of the normalized floating-point value v into 16-bit integer values. + /// Then, the results are packed into the returned 64-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm4x16: round(clamp(c, 0, +1) * 65535.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint16 packUnorm1x16(float const & v) + /// @see uint32 packUnorm2x16(vec2 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packUnorm4x8.xml">GLSL packUnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint64 packUnorm4x16(vec4 const & v); + + /// First, unpacks a single 64-bit unsigned integer p into four 16-bit unsigned integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackUnormx4x16: f / 65535.0 + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackUnorm1x16(uint16 p) + /// @see vec2 unpackUnorm2x16(uint32 p) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackUnorm2x16.xml">GLSL unpackUnorm2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL vec4 unpackUnorm4x16(uint64 p); + + /// First, converts the normalized floating-point value v into 16-bit integer value. + /// Then, the results are packed into the returned 16-bit unsigned integer. + /// + /// The conversion to fixed point is done as follows: + /// packSnorm1x8: round(clamp(s, -1, +1) * 32767.0) + /// + /// @see gtc_packing + /// @see uint32 packSnorm2x16(vec2 const & v) + /// @see uint64 packSnorm4x16(vec4 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm4x8.xml">GLSL packSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint16 packSnorm1x16(float v); + + /// First, unpacks a single 16-bit unsigned integer p into a single 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned scalar. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm1x16: clamp(f / 32767.0, -1, +1) + /// + /// @see gtc_packing + /// @see vec2 unpackSnorm2x16(uint32 p) + /// @see vec4 unpackSnorm4x16(uint64 p) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm1x16.xml">GLSL unpackSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL float unpackSnorm1x16(uint16 p); + + /// First, converts each component of the normalized floating-point value v into 16-bit integer values. + /// Then, the results are packed into the returned 64-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm2x8: round(clamp(c, -1, +1) * 32767.0) + /// + /// The first component of the vector will be written to the least significant bits of the output; + /// the last component will be written to the most significant bits. + /// + /// @see gtc_packing + /// @see uint16 packSnorm1x16(float const & v) + /// @see uint32 packSnorm2x16(vec2 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packSnorm4x8.xml">GLSL packSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint64 packSnorm4x16(vec4 const & v); + + /// First, unpacks a single 64-bit unsigned integer p into four 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm4x16: clamp(f / 32767.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see float unpackSnorm1x16(uint16 p) + /// @see vec2 unpackSnorm2x16(uint32 p) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackSnorm2x16.xml">GLSL unpackSnorm4x8 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL vec4 unpackSnorm4x16(uint64 p); + + /// Returns an unsigned integer obtained by converting the components of a floating-point scalar + /// to the 16-bit floating-point representation found in the OpenGL Specification, + /// and then packing this 16-bit value into a 16-bit unsigned integer. + /// + /// @see gtc_packing + /// @see uint32 packHalf2x16(vec2 const & v) + /// @see uint64 packHalf4x16(vec4 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packHalf2x16.xml">GLSL packHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint16 packHalf1x16(float v); + + /// Returns a floating-point scalar with components obtained by unpacking a 16-bit unsigned integer into a 16-bit value, + /// interpreted as a 16-bit floating-point number according to the OpenGL Specification, + /// and converting it to 32-bit floating-point values. + /// + /// @see gtc_packing + /// @see vec2 unpackHalf2x16(uint32 const & v) + /// @see vec4 unpackHalf4x16(uint64 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackHalf2x16.xml">GLSL unpackHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL float unpackHalf1x16(uint16 v); + + /// Returns an unsigned integer obtained by converting the components of a four-component floating-point vector + /// to the 16-bit floating-point representation found in the OpenGL Specification, + /// and then packing these four 16-bit values into a 64-bit unsigned integer. + /// The first vector component specifies the 16 least-significant bits of the result; + /// the forth component specifies the 16 most-significant bits. + /// + /// @see gtc_packing + /// @see uint16 packHalf1x16(float const & v) + /// @see uint32 packHalf2x16(vec2 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/packHalf2x16.xml">GLSL packHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL uint64 packHalf4x16(vec4 const & v); + + /// Returns a four-component floating-point vector with components obtained by unpacking a 64-bit unsigned integer into four 16-bit values, + /// interpreting those values as 16-bit floating-point numbers according to the OpenGL Specification, + /// and converting them to 32-bit floating-point values. + /// The first component of the vector is obtained from the 16 least-significant bits of v; + /// the forth component is obtained from the 16 most-significant bits of v. + /// + /// @see gtc_packing + /// @see float unpackHalf1x16(uint16 const & v) + /// @see vec2 unpackHalf2x16(uint32 const & v) + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/unpackHalf2x16.xml">GLSL unpackHalf2x16 man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.4 Floating-Point Pack and Unpack Functions</a> + GLM_FUNC_DECL vec4 unpackHalf4x16(uint64 p); + + /// Returns an unsigned integer obtained by converting the components of a four-component signed integer vector + /// to the 10-10-10-2-bit signed integer representation found in the OpenGL Specification, + /// and then packing these four values into a 32-bit unsigned integer. + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see uint32 packI3x10_1x2(uvec4 const & v) + /// @see uint32 packSnorm3x10_1x2(vec4 const & v) + /// @see uint32 packUnorm3x10_1x2(vec4 const & v) + /// @see ivec4 unpackI3x10_1x2(uint32 const & p) + GLM_FUNC_DECL uint32 packI3x10_1x2(ivec4 const & v); + + /// Unpacks a single 32-bit unsigned integer p into three 10-bit and one 2-bit signed integers. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packU3x10_1x2(uvec4 const & v) + /// @see vec4 unpackSnorm3x10_1x2(uint32 const & p); + /// @see uvec4 unpackI3x10_1x2(uint32 const & p); + GLM_FUNC_DECL ivec4 unpackI3x10_1x2(uint32 p); + + /// Returns an unsigned integer obtained by converting the components of a four-component unsigned integer vector + /// to the 10-10-10-2-bit unsigned integer representation found in the OpenGL Specification, + /// and then packing these four values into a 32-bit unsigned integer. + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see uint32 packI3x10_1x2(ivec4 const & v) + /// @see uint32 packSnorm3x10_1x2(vec4 const & v) + /// @see uint32 packUnorm3x10_1x2(vec4 const & v) + /// @see ivec4 unpackU3x10_1x2(uint32 const & p) + GLM_FUNC_DECL uint32 packU3x10_1x2(uvec4 const & v); + + /// Unpacks a single 32-bit unsigned integer p into three 10-bit and one 2-bit unsigned integers. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packU3x10_1x2(uvec4 const & v) + /// @see vec4 unpackSnorm3x10_1x2(uint32 const & p); + /// @see uvec4 unpackI3x10_1x2(uint32 const & p); + GLM_FUNC_DECL uvec4 unpackU3x10_1x2(uint32 p); + + /// First, converts the first three components of the normalized floating-point value v into 10-bit signed integer values. + /// Then, converts the forth component of the normalized floating-point value v into 2-bit signed integer values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packSnorm3x10_1x2(xyz): round(clamp(c, -1, +1) * 511.0) + /// packSnorm3x10_1x2(w): round(clamp(c, -1, +1) * 1.0) + /// + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see vec4 unpackSnorm3x10_1x2(uint32 const & p) + /// @see uint32 packUnorm3x10_1x2(vec4 const & v) + /// @see uint32 packU3x10_1x2(uvec4 const & v) + /// @see uint32 packI3x10_1x2(ivec4 const & v) + GLM_FUNC_DECL uint32 packSnorm3x10_1x2(vec4 const & v); + + /// First, unpacks a single 32-bit unsigned integer p into four 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm3x10_1x2(xyz): clamp(f / 511.0, -1, +1) + /// unpackSnorm3x10_1x2(w): clamp(f / 511.0, -1, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packSnorm3x10_1x2(vec4 const & v) + /// @see vec4 unpackUnorm3x10_1x2(uint32 const & p)) + /// @see uvec4 unpackI3x10_1x2(uint32 const & p) + /// @see uvec4 unpackU3x10_1x2(uint32 const & p) + GLM_FUNC_DECL vec4 unpackSnorm3x10_1x2(uint32 p); + + /// First, converts the first three components of the normalized floating-point value v into 10-bit unsigned integer values. + /// Then, converts the forth component of the normalized floating-point value v into 2-bit signed uninteger values. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The conversion for component c of v to fixed point is done as follows: + /// packUnorm3x10_1x2(xyz): round(clamp(c, 0, +1) * 1023.0) + /// packUnorm3x10_1x2(w): round(clamp(c, 0, +1) * 3.0) + /// + /// The first vector component specifies the 10 least-significant bits of the result; + /// the forth component specifies the 2 most-significant bits. + /// + /// @see gtc_packing + /// @see vec4 unpackUnorm3x10_1x2(uint32 const & p) + /// @see uint32 packUnorm3x10_1x2(vec4 const & v) + /// @see uint32 packU3x10_1x2(uvec4 const & v) + /// @see uint32 packI3x10_1x2(ivec4 const & v) + GLM_FUNC_DECL uint32 packUnorm3x10_1x2(vec4 const & v); + + /// First, unpacks a single 32-bit unsigned integer p into four 16-bit signed integers. + /// Then, each component is converted to a normalized floating-point value to generate the returned four-component vector. + /// + /// The conversion for unpacked fixed-point value f to floating point is done as follows: + /// unpackSnorm3x10_1x2(xyz): clamp(f / 1023.0, 0, +1) + /// unpackSnorm3x10_1x2(w): clamp(f / 3.0, 0, +1) + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packSnorm3x10_1x2(vec4 const & v) + /// @see vec4 unpackInorm3x10_1x2(uint32 const & p)) + /// @see uvec4 unpackI3x10_1x2(uint32 const & p) + /// @see uvec4 unpackU3x10_1x2(uint32 const & p) + GLM_FUNC_DECL vec4 unpackUnorm3x10_1x2(uint32 p); + + /// First, converts the first two components of the normalized floating-point value v into 11-bit signless floating-point values. + /// Then, converts the third component of the normalized floating-point value v into a 10-bit signless floating-point value. + /// Then, the results are packed into the returned 32-bit unsigned integer. + /// + /// The first vector component specifies the 11 least-significant bits of the result; + /// the last component specifies the 10 most-significant bits. + /// + /// @see gtc_packing + /// @see vec3 unpackF2x11_1x10(uint32 const & p) + GLM_FUNC_DECL uint32 packF2x11_1x10(vec3 const & v); + + /// First, unpacks a single 32-bit unsigned integer p into two 11-bit signless floating-point values and one 10-bit signless floating-point value . + /// Then, each component is converted to a normalized floating-point value to generate the returned three-component vector. + /// + /// The first component of the returned vector will be extracted from the least significant bits of the input; + /// the last component will be extracted from the most significant bits. + /// + /// @see gtc_packing + /// @see uint32 packF2x11_1x10(vec3 const & v) + GLM_FUNC_DECL vec3 unpackF2x11_1x10(uint32 p); + + /// @} +}// namespace glm + +#include "packing.inl" diff --git a/extensions/common/glm/gtc/packing.inl b/extensions/common/glm/gtc/packing.inl new file mode 100644 index 0000000000..fa417dd23d --- /dev/null +++ b/extensions/common/glm/gtc/packing.inl @@ -0,0 +1,490 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_packing +/// @file glm/gtc/packing.inl +/// @date 2013-08-08 / 2013-08-08 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "../common.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../detail/type_half.hpp" +#include <cstring> + +namespace glm{ +namespace detail +{ + GLM_FUNC_QUALIFIER glm::uint16 float2half(glm::uint32 f) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x00007c00 => 00000000 00000000 01111100 00000000 + // 0x000003ff => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((f >> 16) & 0x8000) | // sign + ((((f & 0x7f800000) - 0x38000000) >> 13) & 0x7c00) | // exponential + ((f >> 13) & 0x03ff); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 float2packed11(glm::uint32 f) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x000007c0 => 00000000 00000000 00000111 11000000 + // 0x00007c00 => 00000000 00000000 01111100 00000000 + // 0x000003ff => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((f & 0x7f800000) - 0x38000000) >> 17) & 0x07c0) | // exponential + ((f >> 17) & 0x003f); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 packed11ToFloat(glm::uint32 p) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x000007c0 => 00000000 00000000 00000111 11000000 + // 0x00007c00 => 00000000 00000000 01111100 00000000 + // 0x000003ff => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((p & 0x07c0) << 17) + 0x38000000) & 0x7f800000) | // exponential + ((p & 0x003f) << 17); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 float2packed10(glm::uint32 f) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x0000001F => 00000000 00000000 00000000 00011111 + // 0x0000003F => 00000000 00000000 00000000 00111111 + // 0x000003E0 => 00000000 00000000 00000011 11100000 + // 0x000007C0 => 00000000 00000000 00000111 11000000 + // 0x00007C00 => 00000000 00000000 01111100 00000000 + // 0x000003FF => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((f & 0x7f800000) - 0x38000000) >> 18) & 0x03E0) | // exponential + ((f >> 18) & 0x001f); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint32 packed10ToFloat(glm::uint32 p) + { + // 10 bits => EE EEEFFFFF + // 11 bits => EEE EEFFFFFF + // Half bits => SEEEEEFF FFFFFFFF + // Float bits => SEEEEEEE EFFFFFFF FFFFFFFF FFFFFFFF + + // 0x0000001F => 00000000 00000000 00000000 00011111 + // 0x0000003F => 00000000 00000000 00000000 00111111 + // 0x000003E0 => 00000000 00000000 00000011 11100000 + // 0x000007C0 => 00000000 00000000 00000111 11000000 + // 0x00007C00 => 00000000 00000000 01111100 00000000 + // 0x000003FF => 00000000 00000000 00000011 11111111 + // 0x38000000 => 00111000 00000000 00000000 00000000 + // 0x7f800000 => 01111111 10000000 00000000 00000000 + // 0x00008000 => 00000000 00000000 10000000 00000000 + return + ((((p & 0x03E0) << 18) + 0x38000000) & 0x7f800000) | // exponential + ((p & 0x001f) << 18); // Mantissa + } + + GLM_FUNC_QUALIFIER glm::uint half2float(glm::uint h) + { + return ((h & 0x8000) << 16) | ((( h & 0x7c00) + 0x1C000) << 13) | ((h & 0x03FF) << 13); + } + + GLM_FUNC_QUALIFIER glm::uint floatTo11bit(float x) + { + if(x == 0.0f) + return 0u; + else if(glm::isnan(x)) + return ~0u; + else if(glm::isinf(x)) + return 0x1Fu << 6u; + +# if(GLM_COMPILER & GLM_COMPILER_GCC || GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) + uint Pack = 0u; + memcpy(&Pack, &x, sizeof(Pack)); +# else + uint Pack = reinterpret_cast<uint&>(x); +# endif + + return float2packed11(Pack); + } + + GLM_FUNC_QUALIFIER float packed11bitToFloat(glm::uint x) + { + if(x == 0) + return 0.0f; + else if(x == ((1 << 11) - 1)) + return ~0;//NaN + else if(x == (0x1f << 6)) + return ~0;//Inf + + uint Result = packed11ToFloat(x); + +# if(GLM_COMPILER & GLM_COMPILER_GCC || GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) + float Temp = 0; + memcpy(&Temp, &Result, sizeof(Temp)); + return Temp; +# else + return reinterpret_cast<float&>(Result); +# endif + } + + GLM_FUNC_QUALIFIER glm::uint floatTo10bit(float x) + { + if(x == 0.0f) + return 0u; + else if(glm::isnan(x)) + return ~0u; + else if(glm::isinf(x)) + return 0x1Fu << 5u; + +# if(GLM_COMPILER & GLM_COMPILER_GCC || GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) + uint Pack = 0; + memcpy(&Pack, &x, sizeof(Pack)); +# else + uint Pack = reinterpret_cast<uint&>(x); +# endif + + return float2packed10(Pack); + } + + GLM_FUNC_QUALIFIER float packed10bitToFloat(glm::uint x) + { + if(x == 0) + return 0.0f; + else if(x == ((1 << 10) - 1)) + return ~0;//NaN + else if(x == (0x1f << 5)) + return ~0;//Inf + + uint Result = packed10ToFloat(x); + +# if(GLM_COMPILER & GLM_COMPILER_GCC || GLM_COMPILER & (GLM_COMPILER_APPLE_CLANG | GLM_COMPILER_LLVM)) + float Temp = 0; + memcpy(&Temp, &Result, sizeof(Temp)); + return Temp; +# else + return reinterpret_cast<float&>(Result); +# endif + } + +// GLM_FUNC_QUALIFIER glm::uint f11_f11_f10(float x, float y, float z) +// { +// return ((floatTo11bit(x) & ((1 << 11) - 1)) << 0) | ((floatTo11bit(y) & ((1 << 11) - 1)) << 11) | ((floatTo10bit(z) & ((1 << 10) - 1)) << 22); +// } + + union u10u10u10u2 + { + struct + { + uint x : 10; + uint y : 10; + uint z : 10; + uint w : 2; + } data; + uint32 pack; + }; + + union i10i10i10i2 + { + struct + { + int x : 10; + int y : 10; + int z : 10; + int w : 2; + } data; + uint32 pack; + }; + +}//namespace detail + + GLM_FUNC_QUALIFIER uint8 packUnorm1x8(float v) + { + return static_cast<uint8>(round(clamp(v, 0.0f, 1.0f) * 255.0f)); + } + + GLM_FUNC_QUALIFIER float unpackUnorm1x8(uint8 p) + { + float const Unpack(p); + return Unpack * static_cast<float>(0.0039215686274509803921568627451); // 1 / 255 + } + + GLM_FUNC_QUALIFIER uint16 packUnorm2x8(vec2 const & v) + { + u8vec2 const Topack(round(clamp(v, 0.0f, 1.0f) * 255.0f)); + return reinterpret_cast<uint16 const &>(Topack); + } + + GLM_FUNC_QUALIFIER vec2 unpackUnorm2x8(uint16 p) + { + vec2 const Unpack(reinterpret_cast<u8vec2 const &>(p)); + return Unpack * float(0.0039215686274509803921568627451); // 1 / 255 + } + + GLM_FUNC_QUALIFIER uint8 packSnorm1x8(float v) + { + int8 const Topack(static_cast<int8>(round(clamp(v ,-1.0f, 1.0f) * 127.0f))); + return reinterpret_cast<uint8 const &>(Topack); + } + + GLM_FUNC_QUALIFIER float unpackSnorm1x8(uint8 p) + { + float const Unpack(reinterpret_cast<int8 const &>(p)); + return clamp( + Unpack * 0.00787401574803149606299212598425f, // 1.0f / 127.0f + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint16 packSnorm2x8(vec2 const & v) + { + i8vec2 const Topack(round(clamp(v, -1.0f, 1.0f) * 127.0f)); + return reinterpret_cast<uint16 const &>(Topack); + } + + GLM_FUNC_QUALIFIER vec2 unpackSnorm2x8(uint16 p) + { + vec2 const Unpack(reinterpret_cast<i8vec2 const &>(p)); + return clamp( + Unpack * 0.00787401574803149606299212598425f, // 1.0f / 127.0f + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint16 packUnorm1x16(float s) + { + return static_cast<uint16>(round(clamp(s, 0.0f, 1.0f) * 65535.0f)); + } + + GLM_FUNC_QUALIFIER float unpackUnorm1x16(uint16 p) + { + float const Unpack(p); + return Unpack * 1.5259021896696421759365224689097e-5f; // 1.0 / 65535.0 + } + + GLM_FUNC_QUALIFIER uint64 packUnorm4x16(vec4 const & v) + { + u16vec4 const Topack(round(clamp(v , 0.0f, 1.0f) * 65535.0f)); + return reinterpret_cast<uint64 const &>(Topack); + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm4x16(uint64 p) + { + vec4 const Unpack(reinterpret_cast<u16vec4 const &>(p)); + return Unpack * 1.5259021896696421759365224689097e-5f; // 1.0 / 65535.0 + } + + GLM_FUNC_QUALIFIER uint16 packSnorm1x16(float v) + { + int16 const Topack = static_cast<int16>(round(clamp(v ,-1.0f, 1.0f) * 32767.0f)); + return reinterpret_cast<uint16 const &>(Topack); + } + + GLM_FUNC_QUALIFIER float unpackSnorm1x16(uint16 p) + { + float const Unpack(reinterpret_cast<int16 const &>(p)); + return clamp( + Unpack * 3.0518509475997192297128208258309e-5f, //1.0f / 32767.0f, + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint64 packSnorm4x16(vec4 const & v) + { + i16vec4 const Topack(round(clamp(v ,-1.0f, 1.0f) * 32767.0f)); + return reinterpret_cast<uint64 const &>(Topack); + } + + GLM_FUNC_QUALIFIER vec4 unpackSnorm4x16(uint64 p) + { + vec4 const Unpack(reinterpret_cast<i16vec4 const &>(p)); + return clamp( + Unpack * 3.0518509475997192297128208258309e-5f, //1.0f / 32767.0f, + -1.0f, 1.0f); + } + + GLM_FUNC_QUALIFIER uint16 packHalf1x16(float v) + { + int16 const Topack(detail::toFloat16(v)); + return reinterpret_cast<uint16 const &>(Topack); + } + + GLM_FUNC_QUALIFIER float unpackHalf1x16(uint16 v) + { + return detail::toFloat32(reinterpret_cast<int16 const &>(v)); + } + + GLM_FUNC_QUALIFIER uint64 packHalf4x16(glm::vec4 const & v) + { + i16vec4 Unpack( + detail::toFloat16(v.x), + detail::toFloat16(v.y), + detail::toFloat16(v.z), + detail::toFloat16(v.w)); + + return reinterpret_cast<uint64 const &>(Unpack); + } + + GLM_FUNC_QUALIFIER glm::vec4 unpackHalf4x16(uint64 v) + { + i16vec4 Unpack(reinterpret_cast<i16vec4 const &>(v)); + + return vec4( + detail::toFloat32(Unpack.x), + detail::toFloat32(Unpack.y), + detail::toFloat32(Unpack.z), + detail::toFloat32(Unpack.w)); + } + + GLM_FUNC_QUALIFIER uint32 packI3x10_1x2(ivec4 const & v) + { + detail::i10i10i10i2 Result; + Result.data.x = v.x; + Result.data.y = v.y; + Result.data.z = v.z; + Result.data.w = v.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER ivec4 unpackI3x10_1x2(uint32 v) + { + detail::i10i10i10i2 Unpack; + Unpack.pack = v; + return ivec4( + Unpack.data.x, + Unpack.data.y, + Unpack.data.z, + Unpack.data.w); + } + + GLM_FUNC_QUALIFIER uint32 packU3x10_1x2(uvec4 const & v) + { + detail::u10u10u10u2 Result; + Result.data.x = v.x; + Result.data.y = v.y; + Result.data.z = v.z; + Result.data.w = v.w; + return Result.pack; + } + + GLM_FUNC_QUALIFIER uvec4 unpackU3x10_1x2(uint32 v) + { + detail::u10u10u10u2 Unpack; + Unpack.pack = v; + return uvec4( + Unpack.data.x, + Unpack.data.y, + Unpack.data.z, + Unpack.data.w); + } + + GLM_FUNC_QUALIFIER uint32 packSnorm3x10_1x2(vec4 const & v) + { + detail::i10i10i10i2 Result; + Result.data.x = int(round(clamp(v.x,-1.0f, 1.0f) * 511.f)); + Result.data.y = int(round(clamp(v.y,-1.0f, 1.0f) * 511.f)); + Result.data.z = int(round(clamp(v.z,-1.0f, 1.0f) * 511.f)); + Result.data.w = int(round(clamp(v.w,-1.0f, 1.0f) * 1.f)); + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec4 unpackSnorm3x10_1x2(uint32 v) + { + detail::i10i10i10i2 Unpack; + Unpack.pack = v; + vec4 Result; + Result.x = clamp(float(Unpack.data.x) / 511.f, -1.0f, 1.0f); + Result.y = clamp(float(Unpack.data.y) / 511.f, -1.0f, 1.0f); + Result.z = clamp(float(Unpack.data.z) / 511.f, -1.0f, 1.0f); + Result.w = clamp(float(Unpack.data.w) / 1.f, -1.0f, 1.0f); + return Result; + } + + GLM_FUNC_QUALIFIER uint32 packUnorm3x10_1x2(vec4 const & v) + { + detail::i10i10i10i2 Result; + Result.data.x = int(round(clamp(v.x, 0.0f, 1.0f) * 1023.f)); + Result.data.y = int(round(clamp(v.y, 0.0f, 1.0f) * 1023.f)); + Result.data.z = int(round(clamp(v.z, 0.0f, 1.0f) * 1023.f)); + Result.data.w = int(round(clamp(v.w, 0.0f, 1.0f) * 3.f)); + return Result.pack; + } + + GLM_FUNC_QUALIFIER vec4 unpackUnorm3x10_1x2(uint32 v) + { + detail::i10i10i10i2 Unpack; + Unpack.pack = v; + vec4 Result; + Result.x = float(Unpack.data.x) / 1023.f; + Result.y = float(Unpack.data.y) / 1023.f; + Result.z = float(Unpack.data.z) / 1023.f; + Result.w = float(Unpack.data.w) / 3.f; + return Result; + } + + GLM_FUNC_QUALIFIER uint32 packF2x11_1x10(vec3 const & v) + { + return + ((detail::floatTo11bit(v.x) & ((1 << 11) - 1)) << 0) | + ((detail::floatTo11bit(v.y) & ((1 << 11) - 1)) << 11) | + ((detail::floatTo10bit(v.z) & ((1 << 10) - 1)) << 22); + } + + GLM_FUNC_QUALIFIER vec3 unpackF2x11_1x10(uint32 v) + { + return vec3( + detail::packed11bitToFloat(v >> 0), + detail::packed11bitToFloat(v >> 11), + detail::packed10bitToFloat(v >> 22)); + } + +}//namespace glm diff --git a/extensions/common/glm/gtc/quaternion.hpp b/extensions/common/glm/gtc/quaternion.hpp new file mode 100644 index 0000000000..30bdc3ce36 --- /dev/null +++ b/extensions/common/glm/gtc/quaternion.hpp @@ -0,0 +1,377 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_quaternion +/// @file glm/gtc/quaternion.hpp +/// @date 2009-05-21 / 2012-12-20 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// @see gtc_constants (dependence) +/// +/// @defgroup gtc_quaternion GLM_GTC_quaternion +/// @ingroup gtc +/// +/// @brief Defines a templated quaternion type and several quaternion operations. +/// +/// <glm/gtc/quaternion.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" +#include "../mat4x4.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../gtc/constants.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_quaternion extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_quaternion + /// @{ + + template <typename T, precision P> + struct tquat + { + typedef tquat<T, P> type; + typedef T value_type; + + public: + T x, y, z, w; + + ////////////////////////////////////// + // Component accesses + +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t size_type; + /// Return the count of components of a quaternion + GLM_FUNC_DECL GLM_CONSTEXPR size_type size() const; + + GLM_FUNC_DECL T & operator[](size_type i); + GLM_FUNC_DECL T const & operator[](size_type i) const; +# else + typedef length_t length_type; + /// Return the count of components of a quaternion + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL T & operator[](length_type i); + GLM_FUNC_DECL T const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Implicit basic constructors + + GLM_FUNC_DECL tquat(); + GLM_FUNC_DECL tquat(tquat<T, P> const & q); + template <precision Q> + GLM_FUNC_DECL tquat(tquat<T, Q> const & q); + + ////////////////////////////////////// + // Explicit basic constructors + + GLM_FUNC_DECL explicit tquat(ctor); + GLM_FUNC_DECL explicit tquat(T const & s, tvec3<T, P> const & v); + GLM_FUNC_DECL tquat(T const & w, T const & x, T const & y, T const & z); + + ////////////////////////////////////// + // Convertions + +# ifdef GLM_FORCE_EXPLICIT_CTOR + template <typename U, precision Q> + GLM_FUNC_DECL explicit tquat(tquat<U, Q> const & q); +# else + template <typename U, precision Q> + GLM_FUNC_DECL tquat(tquat<U, Q> const & q); +# endif + + // explicit conversion operators +# if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS + GLM_FUNC_DECL explicit operator tmat3x3<T, P>(); + GLM_FUNC_DECL explicit operator tmat4x4<T, P>(); +# endif + + /// Create a quaternion from two normalized axis + /// + /// @param u A first normalized axis + /// @param v A second normalized axis + /// @see gtc_quaternion + /// @see http://lolengine.net/blog/2013/09/18/beautiful-maths-quaternion-from-vectors + GLM_FUNC_DECL explicit tquat(tvec3<T, P> const & u, tvec3<T, P> const & v); + + /// Build a quaternion from euler angles (pitch, yaw, roll), in radians. + GLM_FUNC_DECL explicit tquat(tvec3<T, P> const & eulerAngles); + GLM_FUNC_DECL explicit tquat(tmat3x3<T, P> const & m); + GLM_FUNC_DECL explicit tquat(tmat4x4<T, P> const & m); + + ////////////////////////////////////// + // Operators + + GLM_FUNC_DECL tquat<T, P> & operator=(tquat<T, P> const & m); + + template <typename U> + GLM_FUNC_DECL tquat<T, P> & operator=(tquat<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tquat<T, P> & operator+=(tquat<U, P> const & q); + template <typename U> + GLM_FUNC_DECL tquat<T, P> & operator*=(tquat<U, P> const & q); + template <typename U> + GLM_FUNC_DECL tquat<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tquat<T, P> & operator/=(U s); + }; + + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> operator-(tquat<T, P> const & q); + + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> operator+(tquat<T, P> const & q, tquat<T, P> const & p); + + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> operator*(tquat<T, P> const & q, tquat<T, P> const & p); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator*(tquat<T, P> const & q, tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator*(tvec3<T, P> const & v, tquat<T, P> const & q); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator*(tquat<T, P> const & q, tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator*(tvec4<T, P> const & v, tquat<T, P> const & q); + + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> operator*(tquat<T, P> const & q, T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> operator*(T const & s, tquat<T, P> const & q); + + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> operator/(tquat<T, P> const & q, T const & s); + + /// Returns the length of the quaternion. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL T length(tquat<T, P> const & q); + + /// Returns the normalized quaternion. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> normalize(tquat<T, P> const & q); + + /// Returns dot product of q1 and q2, i.e., q1[0] * q2[0] + q1[1] * q2[1] + ... + /// + /// @see gtc_quaternion + template <typename T, precision P, template <typename, precision> class quatType> + GLM_FUNC_DECL T dot(quatType<T, P> const & x, quatType<T, P> const & y); + + /// Spherical linear interpolation of two quaternions. + /// The interpolation is oriented and the rotation is performed at constant speed. + /// For short path spherical linear interpolation, use the slerp function. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// @tparam T Value type used to build the quaternion. Supported: half, float or double. + /// @see gtc_quaternion + /// @see - slerp(tquat<T, P> const & x, tquat<T, P> const & y, T const & a) + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> mix(tquat<T, P> const & x, tquat<T, P> const & y, T a); + + /// Linear interpolation of two quaternions. + /// The interpolation is oriented. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined in the range [0, 1]. + /// @tparam T Value type used to build the quaternion. Supported: half, float or double. + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> lerp(tquat<T, P> const & x, tquat<T, P> const & y, T a); + + /// Spherical linear interpolation of two quaternions. + /// The interpolation always take the short path and the rotation is performed at constant speed. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// @tparam T Value type used to build the quaternion. Supported: half, float or double. + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> slerp(tquat<T, P> const & x, tquat<T, P> const & y, T a); + + /// Returns the q conjugate. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> conjugate(tquat<T, P> const & q); + + /// Returns the q inverse. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> inverse(tquat<T, P> const & q); + + /// Rotates a quaternion from a vector of 3 components axis and an angle. + /// + /// @param q Source orientation + /// @param angle Angle expressed in radians. + /// @param axis Axis of the rotation + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> rotate(tquat<T, P> const & q, T const & angle, tvec3<T, P> const & axis); + + /// Returns euler angles, yitch as x, yaw as y, roll as z. + /// The result is expressed in radians if GLM_FORCE_RADIANS is defined or degrees otherwise. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> eulerAngles(tquat<T, P> const & x); + + /// Returns roll value of euler angles expressed in radians. + /// + /// @see gtx_quaternion + template <typename T, precision P> + GLM_FUNC_DECL T roll(tquat<T, P> const & x); + + /// Returns pitch value of euler angles expressed in radians. + /// + /// @see gtx_quaternion + template <typename T, precision P> + GLM_FUNC_DECL T pitch(tquat<T, P> const & x); + + /// Returns yaw value of euler angles expressed in radians. + /// + /// @see gtx_quaternion + template <typename T, precision P> + GLM_FUNC_DECL T yaw(tquat<T, P> const & x); + + /// Converts a quaternion to a 3 * 3 matrix. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> mat3_cast(tquat<T, P> const & x); + + /// Converts a quaternion to a 4 * 4 matrix. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> mat4_cast(tquat<T, P> const & x); + + /// Converts a 3 * 3 matrix to a quaternion. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> quat_cast(tmat3x3<T, P> const & x); + + /// Converts a 4 * 4 matrix to a quaternion. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> quat_cast(tmat4x4<T, P> const & x); + + /// Returns the quaternion rotation angle. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL T angle(tquat<T, P> const & x); + + /// Returns the q rotation axis. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> axis(tquat<T, P> const & x); + + /// Build a quaternion from an angle and a normalized axis. + /// + /// @param angle Angle expressed in radians. + /// @param axis Axis of the quaternion, must be normalized. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> angleAxis(T const & angle, tvec3<T, P> const & axis); + + /// Returns the component-wise comparison result of x < y. + /// + /// @tparam quatType Floating-point quaternion types. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tvec4<bool, P> lessThan(tquat<T, P> const & x, tquat<T, P> const & y); + + /// Returns the component-wise comparison of result x <= y. + /// + /// @tparam quatType Floating-point quaternion types. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tvec4<bool, P> lessThanEqual(tquat<T, P> const & x, tquat<T, P> const & y); + + /// Returns the component-wise comparison of result x > y. + /// + /// @tparam quatType Floating-point quaternion types. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tvec4<bool, P> greaterThan(tquat<T, P> const & x, tquat<T, P> const & y); + + /// Returns the component-wise comparison of result x >= y. + /// + /// @tparam quatType Floating-point quaternion types. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tvec4<bool, P> greaterThanEqual(tquat<T, P> const & x, tquat<T, P> const & y); + + /// Returns the component-wise comparison of result x == y. + /// + /// @tparam quatType Floating-point quaternion types. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tvec4<bool, P> equal(tquat<T, P> const & x, tquat<T, P> const & y); + + /// Returns the component-wise comparison of result x != y. + /// + /// @tparam quatType Floating-point quaternion types. + /// + /// @see gtc_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tvec4<bool, P> notEqual(tquat<T, P> const & x, tquat<T, P> const & y); + /// @} +} //namespace glm + +#include "quaternion.inl" diff --git a/extensions/common/glm/gtc/quaternion.inl b/extensions/common/glm/gtc/quaternion.inl new file mode 100644 index 0000000000..25f41f11d3 --- /dev/null +++ b/extensions/common/glm/gtc/quaternion.inl @@ -0,0 +1,784 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_quaternion +/// @file glm/gtc/quaternion.inl +/// @date 2009-05-21 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "../trigonometric.hpp" +#include "../geometric.hpp" +#include "../exponential.hpp" +#include <limits> + +namespace glm{ +namespace detail +{ + template <typename T, precision P> + struct compute_dot<tquat, T, P> + { + static GLM_FUNC_QUALIFIER T call(tquat<T, P> const & x, tquat<T, P> const & y) + { + tvec4<T, P> tmp(x.x * y.x, x.y * y.y, x.z * y.z, x.w * y.w); + return (tmp.x + tmp.y) + (tmp.z + tmp.w); + } + }; +}//namespace detail + + ////////////////////////////////////// + // Component accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tquat<T, P>::size_type tquat<T, P>::size() const + { + return 4; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T & tquat<T, P>::operator[](typename tquat<T, P>::size_type i) + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T const & tquat<T, P>::operator[](typename tquat<T, P>::size_type i) const + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tquat<T, P>::length_type tquat<T, P>::length() const + { + return 4; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T & tquat<T, P>::operator[](typename tquat<T, P>::length_type i) + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T const & tquat<T, P>::operator[](typename tquat<T, P>::length_type i) const + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&x)[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Implicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P>::tquat() +# ifndef GLM_FORCE_NO_CTOR_INIT + : x(0), y(0), z(0), w(1) +# endif + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P>::tquat(tquat<T, P> const & q) + : x(q.x), y(q.y), z(q.z), w(q.w) + {} + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tquat<T, P>::tquat(tquat<T, Q> const & q) + : x(q.x), y(q.y), z(q.z), w(q.w) + {} + + ////////////////////////////////////// + // Explicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P>::tquat(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P>::tquat(T const & s, tvec3<T, P> const & v) + : x(v.x), y(v.y), z(v.z), w(s) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P>::tquat(T const & w, T const & x, T const & y, T const & z) + : x(x), y(y), z(z), w(w) + {} + + ////////////////////////////////////////////////////////////// + // Conversions + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tquat<T, P>::tquat(tquat<U, Q> const & q) + : x(static_cast<T>(q.x)) + , y(static_cast<T>(q.y)) + , z(static_cast<T>(q.z)) + , w(static_cast<T>(q.w)) + {} + + //template <typename valType> + //GLM_FUNC_QUALIFIER tquat<valType>::tquat + //( + // valType const & pitch, + // valType const & yaw, + // valType const & roll + //) + //{ + // tvec3<valType> eulerAngle(pitch * valType(0.5), yaw * valType(0.5), roll * valType(0.5)); + // tvec3<valType> c = glm::cos(eulerAngle * valType(0.5)); + // tvec3<valType> s = glm::sin(eulerAngle * valType(0.5)); + // + // this->w = c.x * c.y * c.z + s.x * s.y * s.z; + // this->x = s.x * c.y * c.z - c.x * s.y * s.z; + // this->y = c.x * s.y * c.z + s.x * c.y * s.z; + // this->z = c.x * c.y * s.z - s.x * s.y * c.z; + //} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P>::tquat(tvec3<T, P> const & u, tvec3<T, P> const & v) + { + tvec3<T, P> const LocalW(cross(u, v)); + T Dot = detail::compute_dot<tvec3, T, P>::call(u, v); + tquat<T, P> q(T(1) + Dot, LocalW.x, LocalW.y, LocalW.z); + + *this = normalize(q); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P>::tquat(tvec3<T, P> const & eulerAngle) + { + tvec3<T, P> c = glm::cos(eulerAngle * T(0.5)); + tvec3<T, P> s = glm::sin(eulerAngle * T(0.5)); + + this->w = c.x * c.y * c.z + s.x * s.y * s.z; + this->x = s.x * c.y * c.z - c.x * s.y * s.z; + this->y = c.x * s.y * c.z + s.x * c.y * s.z; + this->z = c.x * c.y * s.z - s.x * s.y * c.z; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P>::tquat(tmat3x3<T, P> const & m) + { + *this = quat_cast(m); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P>::tquat(tmat4x4<T, P> const & m) + { + *this = quat_cast(m); + } + +# if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P>::operator tmat3x3<T, P>() + { + return mat3_cast(*this); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P>::operator tmat4x4<T, P>() + { + return mat4_cast(*this); + } +# endif//GLM_HAS_EXPLICIT_CONVERSION_OPERATORS + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> conjugate(tquat<T, P> const & q) + { + return tquat<T, P>(q.w, -q.x, -q.y, -q.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> inverse(tquat<T, P> const & q) + { + return conjugate(q) / dot(q, q); + } + + ////////////////////////////////////////////////////////////// + // tquat<valType> operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> & tquat<T, P>::operator=(tquat<T, P> const & q) + { + this->w = q.w; + this->x = q.x; + this->y = q.y; + this->z = q.z; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tquat<T, P> & tquat<T, P>::operator=(tquat<U, P> const & q) + { + this->w = static_cast<T>(q.w); + this->x = static_cast<T>(q.x); + this->y = static_cast<T>(q.y); + this->z = static_cast<T>(q.z); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tquat<T, P> & tquat<T, P>::operator+=(tquat<U, P> const & q) + { + this->w += static_cast<T>(q.w); + this->x += static_cast<T>(q.x); + this->y += static_cast<T>(q.y); + this->z += static_cast<T>(q.z); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tquat<T, P> & tquat<T, P>::operator*=(tquat<U, P> const & r) + { + tquat<T, P> const p(*this); + tquat<T, P> const q(r); + + this->w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z; + this->x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y; + this->y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z; + this->z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tquat<T, P> & tquat<T, P>::operator*=(U s) + { + this->w *= static_cast<U>(s); + this->x *= static_cast<U>(s); + this->y *= static_cast<U>(s); + this->z *= static_cast<U>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tquat<T, P> & tquat<T, P>::operator/=(U s) + { + this->w /= static_cast<U>(s); + this->x /= static_cast<U>(s); + this->y /= static_cast<U>(s); + this->z /= static_cast<U>(s); + return *this; + } + + ////////////////////////////////////////////////////////////// + // tquat<T, P> external operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> operator-(tquat<T, P> const & q) + { + return tquat<T, P>(-q.w, -q.x, -q.y, -q.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> operator+(tquat<T, P> const & q, tquat<T, P> const & p) + { + return tquat<T, P>(q) += p; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> operator*(tquat<T, P> const & q, tquat<T, P> const & p) + { + return tquat<T, P>(q) *= p; + } + + // Transformation + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator*(tquat<T, P> const & q, tvec3<T, P> const & v) + { + tvec3<T, P> const QuatVector(q.x, q.y, q.z); + tvec3<T, P> const uv(glm::cross(QuatVector, v)); + tvec3<T, P> const uuv(glm::cross(QuatVector, uv)); + + return v + ((uv * q.w) + uuv) * static_cast<T>(2); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator*(tvec3<T, P> const & v, tquat<T, P> const & q) + { + return glm::inverse(q) * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator*(tquat<T, P> const & q, tvec4<T, P> const & v) + { + return tvec4<T, P>(q * tvec3<T, P>(v), v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator*(tvec4<T, P> const & v, tquat<T, P> const & q) + { + return glm::inverse(q) * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> operator*(tquat<T, P> const & q, T const & s) + { + return tquat<T, P>( + q.w * s, q.x * s, q.y * s, q.z * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> operator*(T const & s, tquat<T, P> const & q) + { + return q * s; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> operator/(tquat<T, P> const & q, T const & s) + { + return tquat<T, P>( + q.w / s, q.x / s, q.y / s, q.z / s); + } + + ////////////////////////////////////// + // Boolean operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tquat<T, P> const & q1, tquat<T, P> const & q2) + { + return (q1.x == q2.x) && (q1.y == q2.y) && (q1.z == q2.z) && (q1.w == q2.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tquat<T, P> const & q1, tquat<T, P> const & q2) + { + return (q1.x != q2.x) || (q1.y != q2.y) || (q1.z != q2.z) || (q1.w != q2.w); + } + + //////////////////////////////////////////////////////// + template <typename T, precision P> + GLM_FUNC_QUALIFIER T length(tquat<T, P> const & q) + { + return glm::sqrt(dot(q, q)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> normalize(tquat<T, P> const & q) + { + T len = length(q); + if(len <= T(0)) // Problem + return tquat<T, P>(1, 0, 0, 0); + T oneOverLen = T(1) / len; + return tquat<T, P>(q.w * oneOverLen, q.x * oneOverLen, q.y * oneOverLen, q.z * oneOverLen); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> cross(tquat<T, P> const & q1, tquat<T, P> const & q2) + { + return tquat<T, P>( + q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z, + q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y, + q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z, + q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x); + } +/* + // (x * sin(1 - a) * angle / sin(angle)) + (y * sin(a) * angle / sin(angle)) + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> mix(tquat<T, P> const & x, tquat<T, P> const & y, T const & a) + { + if(a <= T(0)) return x; + if(a >= T(1)) return y; + + float fCos = dot(x, y); + tquat<T, P> y2(y); //BUG!!! tquat<T, P> y2; + if(fCos < T(0)) + { + y2 = -y; + fCos = -fCos; + } + + //if(fCos > 1.0f) // problem + float k0, k1; + if(fCos > T(0.9999)) + { + k0 = T(1) - a; + k1 = T(0) + a; //BUG!!! 1.0f + a; + } + else + { + T fSin = sqrt(T(1) - fCos * fCos); + T fAngle = atan(fSin, fCos); + T fOneOverSin = static_cast<T>(1) / fSin; + k0 = sin((T(1) - a) * fAngle) * fOneOverSin; + k1 = sin((T(0) + a) * fAngle) * fOneOverSin; + } + + return tquat<T, P>( + k0 * x.w + k1 * y2.w, + k0 * x.x + k1 * y2.x, + k0 * x.y + k1 * y2.y, + k0 * x.z + k1 * y2.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> mix2 + ( + tquat<T, P> const & x, + tquat<T, P> const & y, + T const & a + ) + { + bool flip = false; + if(a <= static_cast<T>(0)) return x; + if(a >= static_cast<T>(1)) return y; + + T cos_t = dot(x, y); + if(cos_t < T(0)) + { + cos_t = -cos_t; + flip = true; + } + + T alpha(0), beta(0); + + if(T(1) - cos_t < 1e-7) + beta = static_cast<T>(1) - alpha; + else + { + T theta = acos(cos_t); + T sin_t = sin(theta); + beta = sin(theta * (T(1) - alpha)) / sin_t; + alpha = sin(alpha * theta) / sin_t; + } + + if(flip) + alpha = -alpha; + + return normalize(beta * x + alpha * y); + } +*/ + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> mix(tquat<T, P> const & x, tquat<T, P> const & y, T a) + { + T cosTheta = dot(x, y); + + // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator + if(cosTheta > T(1) - epsilon<T>()) + { + // Linear interpolation + return tquat<T, P>( + mix(x.w, y.w, a), + mix(x.x, y.x, a), + mix(x.y, y.y, a), + mix(x.z, y.z, a)); + } + else + { + // Essential Mathematics, page 467 + T angle = acos(cosTheta); + return (sin((T(1) - a) * angle) * x + sin(a * angle) * y) / sin(angle); + } + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> lerp(tquat<T, P> const & x, tquat<T, P> const & y, T a) + { + // Lerp is only defined in [0, 1] + assert(a >= static_cast<T>(0)); + assert(a <= static_cast<T>(1)); + + return x * (T(1) - a) + (y * a); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> slerp(tquat<T, P> const & x, tquat<T, P> const & y, T a) + { + tquat<T, P> z = y; + + T cosTheta = dot(x, y); + + // If cosTheta < 0, the interpolation will take the long way around the sphere. + // To fix this, one quat must be negated. + if (cosTheta < T(0)) + { + z = -y; + cosTheta = -cosTheta; + } + + // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator + if(cosTheta > T(1) - epsilon<T>()) + { + // Linear interpolation + return tquat<T, P>( + mix(x.w, z.w, a), + mix(x.x, z.x, a), + mix(x.y, z.y, a), + mix(x.z, z.z, a)); + } + else + { + // Essential Mathematics, page 467 + T angle = acos(cosTheta); + return (sin((T(1) - a) * angle) * x + sin(a * angle) * z) / sin(angle); + } + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> rotate(tquat<T, P> const & q, T const & angle, tvec3<T, P> const & v) + { + tvec3<T, P> Tmp = v; + + // Axis of rotation must be normalised + T len = glm::length(Tmp); + if(abs(len - T(1)) > T(0.001)) + { + T oneOverLen = static_cast<T>(1) / len; + Tmp.x *= oneOverLen; + Tmp.y *= oneOverLen; + Tmp.z *= oneOverLen; + } + + T const AngleRad(angle); + T const Sin = sin(AngleRad * T(0.5)); + + return q * tquat<T, P>(cos(AngleRad * T(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); + //return gtc::quaternion::cross(q, tquat<T, P>(cos(AngleRad * T(0.5)), Tmp.x * fSin, Tmp.y * fSin, Tmp.z * fSin)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> eulerAngles(tquat<T, P> const & x) + { + return tvec3<T, P>(pitch(x), yaw(x), roll(x)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T roll(tquat<T, P> const & q) + { + return T(atan(T(2) * (q.x * q.y + q.w * q.z), q.w * q.w + q.x * q.x - q.y * q.y - q.z * q.z)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T pitch(tquat<T, P> const & q) + { + return T(atan(T(2) * (q.y * q.z + q.w * q.x), q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T yaw(tquat<T, P> const & q) + { + return asin(T(-2) * (q.x * q.z - q.w * q.y)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> mat3_cast(tquat<T, P> const & q) + { + tmat3x3<T, P> Result(T(1)); + T qxx(q.x * q.x); + T qyy(q.y * q.y); + T qzz(q.z * q.z); + T qxz(q.x * q.z); + T qxy(q.x * q.y); + T qyz(q.y * q.z); + T qwx(q.w * q.x); + T qwy(q.w * q.y); + T qwz(q.w * q.z); + + Result[0][0] = 1 - 2 * (qyy + qzz); + Result[0][1] = 2 * (qxy + qwz); + Result[0][2] = 2 * (qxz - qwy); + + Result[1][0] = 2 * (qxy - qwz); + Result[1][1] = 1 - 2 * (qxx + qzz); + Result[1][2] = 2 * (qyz + qwx); + + Result[2][0] = 2 * (qxz + qwy); + Result[2][1] = 2 * (qyz - qwx); + Result[2][2] = 1 - 2 * (qxx + qyy); + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> mat4_cast(tquat<T, P> const & q) + { + return tmat4x4<T, P>(mat3_cast(q)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> quat_cast(tmat3x3<T, P> const & m) + { + T fourXSquaredMinus1 = m[0][0] - m[1][1] - m[2][2]; + T fourYSquaredMinus1 = m[1][1] - m[0][0] - m[2][2]; + T fourZSquaredMinus1 = m[2][2] - m[0][0] - m[1][1]; + T fourWSquaredMinus1 = m[0][0] + m[1][1] + m[2][2]; + + int biggestIndex = 0; + T fourBiggestSquaredMinus1 = fourWSquaredMinus1; + if(fourXSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourXSquaredMinus1; + biggestIndex = 1; + } + if(fourYSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourYSquaredMinus1; + biggestIndex = 2; + } + if(fourZSquaredMinus1 > fourBiggestSquaredMinus1) + { + fourBiggestSquaredMinus1 = fourZSquaredMinus1; + biggestIndex = 3; + } + + T biggestVal = sqrt(fourBiggestSquaredMinus1 + T(1)) * T(0.5); + T mult = static_cast<T>(0.25) / biggestVal; + + tquat<T, P> Result(uninitialize); + switch(biggestIndex) + { + case 0: + Result.w = biggestVal; + Result.x = (m[1][2] - m[2][1]) * mult; + Result.y = (m[2][0] - m[0][2]) * mult; + Result.z = (m[0][1] - m[1][0]) * mult; + break; + case 1: + Result.w = (m[1][2] - m[2][1]) * mult; + Result.x = biggestVal; + Result.y = (m[0][1] + m[1][0]) * mult; + Result.z = (m[2][0] + m[0][2]) * mult; + break; + case 2: + Result.w = (m[2][0] - m[0][2]) * mult; + Result.x = (m[0][1] + m[1][0]) * mult; + Result.y = biggestVal; + Result.z = (m[1][2] + m[2][1]) * mult; + break; + case 3: + Result.w = (m[0][1] - m[1][0]) * mult; + Result.x = (m[2][0] + m[0][2]) * mult; + Result.y = (m[1][2] + m[2][1]) * mult; + Result.z = biggestVal; + break; + + default: // Silence a -Wswitch-default warning in GCC. Should never actually get here. Assert is just for sanity. + assert(false); + break; + } + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> quat_cast(tmat4x4<T, P> const & m4) + { + return quat_cast(tmat3x3<T, P>(m4)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T angle(tquat<T, P> const & x) + { + return acos(x.w) * T(2); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> axis(tquat<T, P> const & x) + { + T tmp1 = static_cast<T>(1) - x.w * x.w; + if(tmp1 <= static_cast<T>(0)) + return tvec3<T, P>(0, 0, 1); + T tmp2 = static_cast<T>(1) / sqrt(tmp1); + return tvec3<T, P>(x.x * tmp2, x.y * tmp2, x.z * tmp2); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> angleAxis(T const & angle, tvec3<T, P> const & v) + { + tquat<T, P> Result(uninitialize); + + T const a(angle); + T const s = glm::sin(a * static_cast<T>(0.5)); + + Result.w = glm::cos(a * static_cast<T>(0.5)); + Result.x = v.x * s; + Result.y = v.y * s; + Result.z = v.z * s; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<bool, P> lessThan(tquat<T, P> const & x, tquat<T, P> const & y) + { + tvec4<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] < y[i]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<bool, P> lessThanEqual(tquat<T, P> const & x, tquat<T, P> const & y) + { + tvec4<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] <= y[i]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<bool, P> greaterThan(tquat<T, P> const & x, tquat<T, P> const & y) + { + tvec4<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] > y[i]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<bool, P> greaterThanEqual(tquat<T, P> const & x, tquat<T, P> const & y) + { + tvec4<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] >= y[i]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<bool, P> equal(tquat<T, P> const & x, tquat<T, P> const & y) + { + tvec4<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] == y[i]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<bool, P> notEqual(tquat<T, P> const & x, tquat<T, P> const & y) + { + tvec4<bool, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = x[i] != y[i]; + return Result; + } +}//namespace glm diff --git a/extensions/common/glm/gtc/random.hpp b/extensions/common/glm/gtc/random.hpp new file mode 100644 index 0000000000..e8df8a1a40 --- /dev/null +++ b/extensions/common/glm/gtc/random.hpp @@ -0,0 +1,120 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_random +/// @file glm/gtc/random.hpp +/// @date 2011-09-18 / 2011-09-18 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// @see gtx_random (extended) +/// +/// @defgroup gtc_random GLM_GTC_random +/// @ingroup gtc +/// +/// @brief Generate random number from various distribution methods. +/// +/// <glm/gtc/random.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../vec2.hpp" +#include "../vec3.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_random extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_random + /// @{ + + /// Generate random numbers in the interval [Min, Max], according a linear distribution + /// + /// @param Min + /// @param Max + /// @tparam genType Value type. Currently supported: half (not recommanded), float or double scalars and vectors. + /// @see gtc_random + template <typename genTYpe> + GLM_FUNC_DECL genTYpe linearRand( + genTYpe Min, + genTYpe Max); + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> linearRand( + vecType<T, P> const & Min, + vecType<T, P> const & Max); + + /// Generate random numbers in the interval [Min, Max], according a gaussian distribution + /// + /// @param Mean + /// @param Deviation + /// @see gtc_random + template <typename genType> + GLM_FUNC_DECL genType gaussRand( + genType Mean, + genType Deviation); + + /// Generate a random 2D vector which coordinates are regulary distributed on a circle of a given radius + /// + /// @param Radius + /// @see gtc_random + template <typename T> + GLM_FUNC_DECL tvec2<T, defaultp> circularRand( + T Radius); + + /// Generate a random 3D vector which coordinates are regulary distributed on a sphere of a given radius + /// + /// @param Radius + /// @see gtc_random + template <typename T> + GLM_FUNC_DECL tvec3<T, defaultp> sphericalRand( + T Radius); + + /// Generate a random 2D vector which coordinates are regulary distributed within the area of a disk of a given radius + /// + /// @param Radius + /// @see gtc_random + template <typename T> + GLM_FUNC_DECL tvec2<T, defaultp> diskRand( + T Radius); + + /// Generate a random 3D vector which coordinates are regulary distributed within the volume of a ball of a given radius + /// + /// @param Radius + /// @see gtc_random + template <typename T> + GLM_FUNC_DECL tvec3<T, defaultp> ballRand( + T Radius); + + /// @} +}//namespace glm + +#include "random.inl" diff --git a/extensions/common/glm/gtc/random.inl b/extensions/common/glm/gtc/random.inl new file mode 100644 index 0000000000..c6b4ee1c66 --- /dev/null +++ b/extensions/common/glm/gtc/random.inl @@ -0,0 +1,379 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_random +/// @file glm/gtc/random.inl +/// @date 2011-09-19 / 2012-04-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "../geometric.hpp" +#include "../exponential.hpp" +#include <cstdlib> +#include <ctime> +#include <cassert> + +namespace glm{ +namespace detail +{ + template <typename T, precision P, template <class, precision> class vecType> + struct compute_rand + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(); + }; + + template <precision P> + struct compute_rand<uint8, P, tvec1> + { + GLM_FUNC_QUALIFIER static tvec1<uint8, P> call() + { + return tvec1<uint8, P>( + std::rand()) % std::numeric_limits<uint8>::max(); + } + }; + + template <precision P> + struct compute_rand<uint8, P, tvec2> + { + GLM_FUNC_QUALIFIER static tvec2<uint8, P> call() + { + return tvec2<uint8, P>( + std::rand(), + std::rand()) % std::numeric_limits<uint8>::max(); + } + }; + + template <precision P> + struct compute_rand<uint8, P, tvec3> + { + GLM_FUNC_QUALIFIER static tvec3<uint8, P> call() + { + return tvec3<uint8, P>( + std::rand(), + std::rand(), + std::rand()) % std::numeric_limits<uint8>::max(); + } + }; + + template <precision P> + struct compute_rand<uint8, P, tvec4> + { + GLM_FUNC_QUALIFIER static tvec4<uint8, P> call() + { + return tvec4<uint8, P>( + std::rand(), + std::rand(), + std::rand(), + std::rand()) % std::numeric_limits<uint8>::max(); + } + }; + + template <precision P, template <class, precision> class vecType> + struct compute_rand<uint16, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<uint16, P> call() + { + return + (vecType<uint16, P>(compute_rand<uint8, P, vecType>::call()) << static_cast<uint16>(8)) | + (vecType<uint16, P>(compute_rand<uint8, P, vecType>::call()) << static_cast<uint16>(0)); + } + }; + + template <precision P, template <class, precision> class vecType> + struct compute_rand<uint32, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<uint32, P> call() + { + return + (vecType<uint32, P>(compute_rand<uint16, P, vecType>::call()) << static_cast<uint32>(16)) | + (vecType<uint32, P>(compute_rand<uint16, P, vecType>::call()) << static_cast<uint32>(0)); + } + }; + + template <precision P, template <class, precision> class vecType> + struct compute_rand<uint64, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<uint64, P> call() + { + return + (vecType<uint64, P>(compute_rand<uint32, P, vecType>::call()) << static_cast<uint64>(32)) | + (vecType<uint64, P>(compute_rand<uint32, P, vecType>::call()) << static_cast<uint64>(0)); + } + }; + + template <typename T, precision P, template <class, precision> class vecType> + struct compute_linearRand + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & Min, vecType<T, P> const & Max); + }; + + template <precision P, template <class, precision> class vecType> + struct compute_linearRand<int8, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<int8, P> call(vecType<int8, P> const & Min, vecType<int8, P> const & Max) + { + return (vecType<int8, P>(compute_rand<uint8, P, vecType>::call() % vecType<uint8, P>(Max + static_cast<int8>(1) - Min))) + Min; + } + }; + + template <precision P, template <class, precision> class vecType> + struct compute_linearRand<uint8, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<uint8, P> call(vecType<uint8, P> const & Min, vecType<uint8, P> const & Max) + { + return (compute_rand<uint8, P, vecType>::call() % (Max + static_cast<uint8>(1) - Min)) + Min; + } + }; + + template <precision P, template <class, precision> class vecType> + struct compute_linearRand<int16, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<int16, P> call(vecType<int16, P> const & Min, vecType<int16, P> const & Max) + { + return (vecType<int16, P>(compute_rand<uint16, P, vecType>::call() % vecType<uint16, P>(Max + static_cast<int16>(1) - Min))) + Min; + } + }; + + template <precision P, template <class, precision> class vecType> + struct compute_linearRand<uint16, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<uint16, P> call(vecType<uint16, P> const & Min, vecType<uint16, P> const & Max) + { + return (compute_rand<uint16, P, vecType>::call() % (Max + static_cast<uint16>(1) - Min)) + Min; + } + }; + + template <precision P, template <class, precision> class vecType> + struct compute_linearRand<int32, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<int32, P> call(vecType<int32, P> const & Min, vecType<int32, P> const & Max) + { + return (vecType<int32, P>(compute_rand<uint32, P, vecType>::call() % vecType<uint32, P>(Max + static_cast<int32>(1) - Min))) + Min; + } + }; + + template <precision P, template <class, precision> class vecType> + struct compute_linearRand<uint32, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<uint32, P> call(vecType<uint32, P> const & Min, vecType<uint32, P> const & Max) + { + return (compute_rand<uint32, P, vecType>::call() % (Max + static_cast<uint32>(1) - Min)) + Min; + } + }; + + template <precision P, template <class, precision> class vecType> + struct compute_linearRand<int64, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<int64, P> call(vecType<int64, P> const & Min, vecType<int64, P> const & Max) + { + return (vecType<int64, P>(compute_rand<uint64, P, vecType>::call() % vecType<uint64, P>(Max + static_cast<int64>(1) - Min))) + Min; + } + }; + + template <precision P, template <class, precision> class vecType> + struct compute_linearRand<uint64, P, vecType> + { + GLM_FUNC_QUALIFIER static vecType<uint64, P> call(vecType<uint64, P> const & Min, vecType<uint64, P> const & Max) + { + return (compute_rand<uint64, P, vecType>::call() % (Max + static_cast<uint64>(1) - Min)) + Min; + } + }; + + template <template <class, precision> class vecType> + struct compute_linearRand<float, lowp, vecType> + { + GLM_FUNC_QUALIFIER static vecType<float, lowp> call(vecType<float, lowp> const & Min, vecType<float, lowp> const & Max) + { + return vecType<float, lowp>(compute_rand<uint8, lowp, vecType>::call()) / static_cast<float>(std::numeric_limits<uint8>::max()) * (Max - Min) + Min; + } + }; + + template <template <class, precision> class vecType> + struct compute_linearRand<float, mediump, vecType> + { + GLM_FUNC_QUALIFIER static vecType<float, mediump> call(vecType<float, mediump> const & Min, vecType<float, mediump> const & Max) + { + return vecType<float, mediump>(compute_rand<uint16, mediump, vecType>::call()) / static_cast<float>(std::numeric_limits<uint16>::max()) * (Max - Min) + Min; + } + }; + + template <template <class, precision> class vecType> + struct compute_linearRand<float, highp, vecType> + { + GLM_FUNC_QUALIFIER static vecType<float, highp> call(vecType<float, highp> const & Min, vecType<float, highp> const & Max) + { + return vecType<float, highp>(compute_rand<uint32, highp, vecType>::call()) / static_cast<float>(std::numeric_limits<uint32>::max()) * (Max - Min) + Min; + } + }; + + template <template <class, precision> class vecType> + struct compute_linearRand<double, lowp, vecType> + { + GLM_FUNC_QUALIFIER static vecType<double, lowp> call(vecType<double, lowp> const & Min, vecType<double, lowp> const & Max) + { + return vecType<double, lowp>(compute_rand<uint16, lowp, vecType>::call()) / static_cast<double>(std::numeric_limits<uint16>::max()) * (Max - Min) + Min; + } + }; + + template <template <class, precision> class vecType> + struct compute_linearRand<double, mediump, vecType> + { + GLM_FUNC_QUALIFIER static vecType<double, mediump> call(vecType<double, mediump> const & Min, vecType<double, mediump> const & Max) + { + return vecType<double, mediump>(compute_rand<uint32, mediump, vecType>::call()) / static_cast<double>(std::numeric_limits<uint32>::max()) * (Max - Min) + Min; + } + }; + + template <template <class, precision> class vecType> + struct compute_linearRand<double, highp, vecType> + { + GLM_FUNC_QUALIFIER static vecType<double, highp> call(vecType<double, highp> const & Min, vecType<double, highp> const & Max) + { + return vecType<double, highp>(compute_rand<uint64, highp, vecType>::call()) / static_cast<double>(std::numeric_limits<uint64>::max()) * (Max - Min) + Min; + } + }; + + template <template <class, precision> class vecType> + struct compute_linearRand<long double, lowp, vecType> + { + GLM_FUNC_QUALIFIER static vecType<long double, lowp> call(vecType<long double, lowp> const & Min, vecType<long double, lowp> const & Max) + { + return vecType<long double, lowp>(compute_rand<uint32, lowp, vecType>::call()) / static_cast<long double>(std::numeric_limits<uint32>::max()) * (Max - Min) + Min; + } + }; + + template <template <class, precision> class vecType> + struct compute_linearRand<long double, mediump, vecType> + { + GLM_FUNC_QUALIFIER static vecType<long double, mediump> call(vecType<long double, mediump> const & Min, vecType<long double, mediump> const & Max) + { + return vecType<long double, mediump>(compute_rand<uint64, mediump, vecType>::call()) / static_cast<long double>(std::numeric_limits<uint64>::max()) * (Max - Min) + Min; + } + }; + + template <template <class, precision> class vecType> + struct compute_linearRand<long double, highp, vecType> + { + GLM_FUNC_QUALIFIER static vecType<long double, highp> call(vecType<long double, highp> const & Min, vecType<long double, highp> const & Max) + { + return vecType<long double, highp>(compute_rand<uint64, highp, vecType>::call()) / static_cast<long double>(std::numeric_limits<uint64>::max()) * (Max - Min) + Min; + } + }; +}//namespace detail + + template <typename genType> + GLM_FUNC_QUALIFIER genType linearRand(genType Min, genType Max) + { + return detail::compute_linearRand<genType, highp, tvec1>::call( + tvec1<genType, highp>(Min), + tvec1<genType, highp>(Max)).x; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> linearRand(vecType<T, P> const & Min, vecType<T, P> const & Max) + { + return detail::compute_linearRand<T, P, vecType>::call(Min, Max); + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType gaussRand(genType Mean, genType Deviation) + { + genType w, x1, x2; + + do + { + x1 = linearRand(genType(-1), genType(1)); + x2 = linearRand(genType(-1), genType(1)); + + w = x1 * x1 + x2 * x2; + } while(w > genType(1)); + + return x2 * Deviation * Deviation * sqrt((genType(-2) * log(w)) / w) + Mean; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> gaussRand(vecType<T, P> const & Mean, vecType<T, P> const & Deviation) + { + return detail::functor2<T, P, vecType>::call(gaussRand, Mean, Deviation); + } + + template <typename T> + GLM_FUNC_QUALIFIER tvec2<T, defaultp> diskRand(T Radius) + { + tvec2<T, defaultp> Result(T(0)); + T LenRadius(T(0)); + + do + { + Result = linearRand( + tvec2<T, defaultp>(-Radius), + tvec2<T, defaultp>(Radius)); + LenRadius = length(Result); + } + while(LenRadius > Radius); + + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tvec3<T, defaultp> ballRand(T Radius) + { + tvec3<T, defaultp> Result(T(0)); + T LenRadius(T(0)); + + do + { + Result = linearRand( + tvec3<T, defaultp>(-Radius), + tvec3<T, defaultp>(Radius)); + LenRadius = length(Result); + } + while(LenRadius > Radius); + + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tvec2<T, defaultp> circularRand(T Radius) + { + T a = linearRand(T(0), T(6.283185307179586476925286766559f)); + return tvec2<T, defaultp>(cos(a), sin(a)) * Radius; + } + + template <typename T> + GLM_FUNC_QUALIFIER tvec3<T, defaultp> sphericalRand(T Radius) + { + T z = linearRand(T(-1), T(1)); + T a = linearRand(T(0), T(6.283185307179586476925286766559f)); + + T r = sqrt(T(1) - z * z); + + T x = r * cos(a); + T y = r * sin(a); + + return tvec3<T, defaultp>(x, y, z) * Radius; + } +}//namespace glm diff --git a/extensions/common/glm/gtc/reciprocal.hpp b/extensions/common/glm/gtc/reciprocal.hpp new file mode 100644 index 0000000000..53989337e6 --- /dev/null +++ b/extensions/common/glm/gtc/reciprocal.hpp @@ -0,0 +1,134 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_reciprocal +/// @file glm/gtc/reciprocal.hpp +/// @date 2008-10-09 / 2012-01-25 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtc_reciprocal GLM_GTC_reciprocal +/// @ingroup gtc +/// +/// @brief Define secant, cosecant and cotangent functions. +/// +/// <glm/gtc/reciprocal.hpp> need to be included to use these features. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_reciprocal extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_reciprocal + /// @{ + + /// Secant function. + /// hypotenuse / adjacent or 1 / cos(x) + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType sec(genType const & angle); + + /// Cosecant function. + /// hypotenuse / opposite or 1 / sin(x) + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType csc(genType const & angle); + + /// Cotangent function. + /// adjacent / opposite or 1 / tan(x) + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType cot(genType const & angle); + + /// Inverse secant function. + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType asec(genType const & x); + + /// Inverse cosecant function. + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType acsc(genType const & x); + + /// Inverse cotangent function. + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType acot(genType const & x); + + /// Secant hyperbolic function. + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType sech(genType const & angle); + + /// Cosecant hyperbolic function. + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType csch(genType const & angle); + + /// Cotangent hyperbolic function. + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType coth(genType const & angle); + + /// Inverse secant hyperbolic function. + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType asech(genType const & x); + + /// Inverse cosecant hyperbolic function. + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType acsch(genType const & x); + + /// Inverse cotangent hyperbolic function. + /// + /// @see gtc_reciprocal + template <typename genType> + GLM_FUNC_DECL genType acoth(genType const & x); + + /// @} +}//namespace glm + +#include "reciprocal.inl" diff --git a/extensions/common/glm/gtc/reciprocal.inl b/extensions/common/glm/gtc/reciprocal.inl new file mode 100644 index 0000000000..9e20c2ce5c --- /dev/null +++ b/extensions/common/glm/gtc/reciprocal.inl @@ -0,0 +1,221 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_reciprocal +/// @file glm/gtc/reciprocal.inl +/// @date 2008-10-09 / 2012-04-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include "../trigonometric.hpp" +#include <limits> + +namespace glm +{ + // sec + template <typename genType> + GLM_FUNC_QUALIFIER genType sec(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'sec' only accept floating-point values"); + return genType(1) / glm::cos(angle); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> sec(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'sec' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(sec, x); + } + + // csc + template <typename genType> + GLM_FUNC_QUALIFIER genType csc(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'csc' only accept floating-point values"); + return genType(1) / glm::sin(angle); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> csc(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'csc' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(csc, x); + } + + // cot + template <typename genType> + GLM_FUNC_QUALIFIER genType cot(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'cot' only accept floating-point values"); + + genType const pi_over_2 = genType(3.1415926535897932384626433832795 / 2.0); + return glm::tan(pi_over_2 - angle); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> cot(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'cot' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(cot, x); + } + + // asec + template <typename genType> + GLM_FUNC_QUALIFIER genType asec(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'asec' only accept floating-point values"); + return acos(genType(1) / x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> asec(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'asec' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(asec, x); + } + + // acsc + template <typename genType> + GLM_FUNC_QUALIFIER genType acsc(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acsc' only accept floating-point values"); + return asin(genType(1) / x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> acsc(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'acsc' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(acsc, x); + } + + // acot + template <typename genType> + GLM_FUNC_QUALIFIER genType acot(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acot' only accept floating-point values"); + + genType const pi_over_2 = genType(3.1415926535897932384626433832795 / 2.0); + return pi_over_2 - atan(x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> acot(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'acot' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(acot, x); + } + + // sech + template <typename genType> + GLM_FUNC_QUALIFIER genType sech(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'sech' only accept floating-point values"); + return genType(1) / glm::cosh(angle); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> sech(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'sech' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(sech, x); + } + + // csch + template <typename genType> + GLM_FUNC_QUALIFIER genType csch(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'csch' only accept floating-point values"); + return genType(1) / glm::sinh(angle); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> csch(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'csch' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(csch, x); + } + + // coth + template <typename genType> + GLM_FUNC_QUALIFIER genType coth(genType angle) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'coth' only accept floating-point values"); + return glm::cosh(angle) / glm::sinh(angle); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> coth(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'coth' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(coth, x); + } + + // asech + template <typename genType> + GLM_FUNC_QUALIFIER genType asech(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'asech' only accept floating-point values"); + return acosh(genType(1) / x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> asech(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'asech' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(asech, x); + } + + // acsch + template <typename genType> + GLM_FUNC_QUALIFIER genType acsch(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acsch' only accept floating-point values"); + return acsch(genType(1) / x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> acsch(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'acsch' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(acsch, x); + } + + // acoth + template <typename genType> + GLM_FUNC_QUALIFIER genType acoth(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'acoth' only accept floating-point values"); + return atanh(genType(1) / x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> acoth(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'acoth' only accept floating-point inputs"); + return detail::functor1<T, T, P, vecType>::call(acoth, x); + } +}//namespace glm diff --git a/extensions/common/glm/gtc/round.hpp b/extensions/common/glm/gtc/round.hpp new file mode 100644 index 0000000000..ed23959cd8 --- /dev/null +++ b/extensions/common/glm/gtc/round.hpp @@ -0,0 +1,203 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_round +/// @file glm/gtc/round.hpp +/// @date 2014-11-03 / 2014-11-03 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_round (dependence) +/// +/// @defgroup gtc_round GLM_GTC_round +/// @ingroup gtc +/// +/// @brief rounding value to specific boundings +/// +/// <glm/gtc/round.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/precision.hpp" +#include "../detail/_vectorize.hpp" +#include "../vector_relational.hpp" +#include "../common.hpp" +#include <limits> + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_round + /// @{ + + /// Return true if the value is a power of two number. + /// + /// @see gtc_round + template <typename genIUType> + GLM_FUNC_DECL bool isPowerOfTwo(genIUType Value); + + /// Return true if the value is a power of two number. + /// + /// @see gtc_round + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> isPowerOfTwo(vecType<T, P> const & value); + + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. + /// + /// @see gtc_round + template <typename genIUType> + GLM_FUNC_DECL genIUType ceilPowerOfTwo(genIUType Value); + + /// Return the power of two number which value is just higher the input value, + /// round up to a power of two. + /// + /// @see gtc_round + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> ceilPowerOfTwo(vecType<T, P> const & value); + + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. + /// + /// @see gtc_round + template <typename genIUType> + GLM_FUNC_DECL genIUType floorPowerOfTwo(genIUType Value); + + /// Return the power of two number which value is just lower the input value, + /// round down to a power of two. + /// + /// @see gtc_round + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> floorPowerOfTwo(vecType<T, P> const & value); + + /// Return the power of two number which value is the closet to the input value. + /// + /// @see gtc_round + template <typename genIUType> + GLM_FUNC_DECL genIUType roundPowerOfTwo(genIUType Value); + + /// Return the power of two number which value is the closet to the input value. + /// + /// @see gtc_round + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> roundPowerOfTwo(vecType<T, P> const & value); + + /// Return true if the 'Value' is a multiple of 'Multiple'. + /// + /// @see gtc_round + template <typename genIUType> + GLM_FUNC_DECL bool isMultiple(genIUType Value, genIUType Multiple); + + /// Return true if the 'Value' is a multiple of 'Multiple'. + /// + /// @see gtc_round + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> isMultiple(vecType<T, P> const & Value, T Multiple); + + /// Return true if the 'Value' is a multiple of 'Multiple'. + /// + /// @see gtc_round + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> isMultiple(vecType<T, P> const & Value, vecType<T, P> const & Multiple); + + /// Higher multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// @param Source + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template <typename genType> + GLM_FUNC_DECL genType ceilMultiple(genType Source, genType Multiple); + + /// Higher multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// @param Source + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> ceilMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// @param Source + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template <typename genType> + GLM_FUNC_DECL genType floorMultiple( + genType Source, + genType Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// @param Source + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> floorMultiple( + vecType<T, P> const & Source, + vecType<T, P> const & Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// @param Source + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template <typename genType> + GLM_FUNC_DECL genType roundMultiple( + genType Source, + genType Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// @param Source + /// @param Multiple Must be a null or positive value + /// + /// @see gtc_round + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> roundMultiple( + vecType<T, P> const & Source, + vecType<T, P> const & Multiple); + + /// @} +} //namespace glm + +#include "round.inl" diff --git a/extensions/common/glm/gtc/round.inl b/extensions/common/glm/gtc/round.inl new file mode 100644 index 0000000000..4dc91b14c6 --- /dev/null +++ b/extensions/common/glm/gtc/round.inl @@ -0,0 +1,378 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_round +/// @file glm/gtc/round.inl +/// @date 2014-11-03 / 2014-11-03 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ +namespace detail +{ + template <typename T, precision P, template <typename, precision> class vecType, bool compute = false> + struct compute_ceilShift + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T) + { + return v; + } + }; + + template <typename T, precision P, template <typename, precision> class vecType> + struct compute_ceilShift<T, P, vecType, true> + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & v, T Shift) + { + return v | (v >> Shift); + } + }; + + template <typename T, precision P, template <typename, precision> class vecType, bool isSigned = true> + struct compute_ceilPowerOfTwo + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vecType<T, P> const Sign(sign(x)); + + vecType<T, P> v(abs(x)); + + v = v - static_cast<T>(1); + v = v | (v >> static_cast<T>(1)); + v = v | (v >> static_cast<T>(2)); + v = v | (v >> static_cast<T>(4)); + v = compute_ceilShift<T, P, vecType, sizeof(T) >= 2>::call(v, 8); + v = compute_ceilShift<T, P, vecType, sizeof(T) >= 4>::call(v, 16); + v = compute_ceilShift<T, P, vecType, sizeof(T) >= 8>::call(v, 32); + return (v + static_cast<T>(1)) * Sign; + } + }; + + template <typename T, precision P, template <typename, precision> class vecType> + struct compute_ceilPowerOfTwo<T, P, vecType, false> + { + GLM_FUNC_QUALIFIER static vecType<T, P> call(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs"); + + vecType<T, P> v(x); + + v = v - static_cast<T>(1); + v = v | (v >> static_cast<T>(1)); + v = v | (v >> static_cast<T>(2)); + v = v | (v >> static_cast<T>(4)); + v = compute_ceilShift<T, P, vecType, sizeof(T) >= 2>::call(v, 8); + v = compute_ceilShift<T, P, vecType, sizeof(T) >= 4>::call(v, 16); + v = compute_ceilShift<T, P, vecType, sizeof(T) >= 8>::call(v, 32); + return v + static_cast<T>(1); + } + }; + + template <bool is_float, bool is_signed> + struct compute_ceilMultiple{}; + + template <> + struct compute_ceilMultiple<true, true> + { + template <typename genType> + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source > genType(0)) + { + genType Tmp = Source - genType(1); + return Tmp + (Multiple - std::fmod(Tmp, Multiple)); + } + else + return Source + std::fmod(-Source, Multiple); + } + }; + + template <> + struct compute_ceilMultiple<false, false> + { + template <typename genType> + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + genType Tmp = Source - genType(1); + return Tmp + (Multiple - (Tmp % Multiple)); + } + }; + + template <> + struct compute_ceilMultiple<false, true> + { + template <typename genType> + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source > genType(0)) + { + genType Tmp = Source - genType(1); + return Tmp + (Multiple - (Tmp % Multiple)); + } + else + return Source + (-Source % Multiple); + } + }; + + template <bool is_float, bool is_signed> + struct compute_floorMultiple{}; + + template <> + struct compute_floorMultiple<true, true> + { + template <typename genType> + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - std::fmod(Source, Multiple); + else + { + genType Tmp = Source + genType(1); + return Tmp - std::fmod(Tmp, Multiple) - Multiple; + } + } + }; + + template <> + struct compute_floorMultiple<false, false> + { + template <typename genType> + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; + + template <> + struct compute_floorMultiple<false, true> + { + template <typename genType> + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; + + template <bool is_float, bool is_signed> + struct compute_roundMultiple{}; + + template <> + struct compute_roundMultiple<true, true> + { + template <typename genType> + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - std::fmod(Source, Multiple); + else + { + genType Tmp = Source + genType(1); + return Tmp - std::fmod(Tmp, Multiple) - Multiple; + } + } + }; + + template <> + struct compute_roundMultiple<false, false> + { + template <typename genType> + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; + + template <> + struct compute_roundMultiple<false, true> + { + template <typename genType> + GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple) + { + if(Source >= genType(0)) + return Source - Source % Multiple; + else + { + genType Tmp = Source + genType(1); + return Tmp - Tmp % Multiple - Multiple; + } + } + }; +}//namespace detail + + //////////////// + // isPowerOfTwo + + template <typename genType> + GLM_FUNC_QUALIFIER bool isPowerOfTwo(genType Value) + { + genType const Result = glm::abs(Value); + return !(Result & (Result - 1)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> isPowerOfTwo(vecType<T, P> const & Value) + { + vecType<T, P> const Result(abs(Value)); + return equal(Result & (Result - 1), vecType<T, P>(0)); + } + + ////////////////// + // ceilPowerOfTwo + + template <typename genType> + GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value) + { + return detail::compute_ceilPowerOfTwo<genType, defaultp, tvec1, std::numeric_limits<genType>::is_signed>::call(tvec1<genType, defaultp>(value)).x; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> ceilPowerOfTwo(vecType<T, P> const & v) + { + return detail::compute_ceilPowerOfTwo<T, P, vecType, std::numeric_limits<T>::is_signed>::call(v); + } + + /////////////////// + // floorPowerOfTwo + + template <typename genType> + GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value) + { + return isPowerOfTwo(value) ? value : highestBitValue(value); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> floorPowerOfTwo(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(floorPowerOfTwo, v); + } + + /////////////////// + // roundPowerOfTwo + + template <typename genIUType> + GLM_FUNC_QUALIFIER genIUType roundPowerOfTwo(genIUType value) + { + if(isPowerOfTwo(value)) + return value; + + genIUType const prev = highestBitValue(value); + genIUType const next = prev << 1; + return (next - value) < (value - prev) ? next : prev; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> roundPowerOfTwo(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(roundPowerOfTwo, v); + } + + //////////////// + // isMultiple + + template <typename genType> + GLM_FUNC_QUALIFIER bool isMultiple(genType Value, genType Multiple) + { + return isMultiple(tvec1<genType>(Value), tvec1<genType>(Multiple)).x; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> isMultiple(vecType<T, P> const & Value, T Multiple) + { + return (Value % Multiple) == vecType<T, P>(0); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> isMultiple(vecType<T, P> const & Value, vecType<T, P> const & Multiple) + { + return (Value % Multiple) == vecType<T, P>(0); + } + + ////////////////////// + // ceilMultiple + + template <typename genType> + GLM_FUNC_QUALIFIER genType ceilMultiple(genType Source, genType Multiple) + { + return detail::compute_ceilMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> ceilMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple) + { + return detail::functor2<T, P, vecType>::call(ceilMultiple, Source, Multiple); + } + + ////////////////////// + // floorMultiple + + template <typename genType> + GLM_FUNC_QUALIFIER genType floorMultiple(genType Source, genType Multiple) + { + return detail::compute_floorMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> floorMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple) + { + return detail::functor2<T, P, vecType>::call(floorMultiple, Source, Multiple); + } + + ////////////////////// + // roundMultiple + + template <typename genType> + GLM_FUNC_QUALIFIER genType roundMultiple(genType Source, genType Multiple) + { + return detail::compute_roundMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> roundMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple) + { + return detail::functor2<T, P, vecType>::call(roundMultiple, Source, Multiple); + } +}//namespace glm diff --git a/extensions/common/glm/gtc/type_precision.hpp b/extensions/common/glm/gtc/type_precision.hpp new file mode 100644 index 0000000000..1dc9f62e72 --- /dev/null +++ b/extensions/common/glm/gtc/type_precision.hpp @@ -0,0 +1,890 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_type_precision +/// @file glm/gtc/type_precision.hpp +/// @date 2009-06-04 / 2011-12-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtc_type_precision GLM_GTC_type_precision +/// @ingroup gtc +/// +/// @brief Defines specific C++-based precision types. +/// +/// @ref core_precision defines types based on GLSL's precision qualifiers. This +/// extension defines types based on explicitly-sized C++ data types. +/// +/// <glm/gtc/type_precision.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../gtc/quaternion.hpp" +#include "../gtc/vec1.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../mat2x2.hpp" +#include "../mat2x3.hpp" +#include "../mat2x4.hpp" +#include "../mat3x2.hpp" +#include "../mat3x3.hpp" +#include "../mat3x4.hpp" +#include "../mat4x2.hpp" +#include "../mat4x3.hpp" +#include "../mat4x4.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_type_precision extension included") +#endif + +namespace glm +{ + /////////////////////////// + // Signed int vector types + + /// @addtogroup gtc_type_precision + /// @{ + + /// Low precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_int8; + + /// Low precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_int16; + + /// Low precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_int32; + + /// Low precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_int64; + + /// Low precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_int8_t; + + /// Low precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_int16_t; + + /// Low precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_int32_t; + + /// Low precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_int64_t; + + /// Low precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 lowp_i8; + + /// Low precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 lowp_i16; + + /// Low precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 lowp_i32; + + /// Low precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 lowp_i64; + + /// Medium precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_int8; + + /// Medium precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_int16; + + /// Medium precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_int32; + + /// Medium precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_int64; + + /// Medium precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_int8_t; + + /// Medium precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_int16_t; + + /// Medium precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_int32_t; + + /// Medium precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_int64_t; + + /// Medium precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 mediump_i8; + + /// Medium precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 mediump_i16; + + /// Medium precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 mediump_i32; + + /// Medium precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 mediump_i64; + + /// High precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_int8; + + /// High precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_int16; + + /// High precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_int32; + + /// High precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_int64; + + /// High precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_int8_t; + + /// High precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_int16_t; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_int32_t; + + /// High precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_int64_t; + + /// High precision 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 highp_i8; + + /// High precision 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 highp_i16; + + /// High precision 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 highp_i32; + + /// High precision 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 highp_i64; + + + /// 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 int8; + + /// 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 int16; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 int32; + + /// 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 int64; + +#if GLM_HAS_EXTENDED_INTEGER_TYPE + using std::int8_t; + using std::int16_t; + using std::int32_t; + using std::int64_t; +#else + /// 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 int8_t; + + /// 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 int16_t; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 int32_t; + + /// 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 int64_t; +#endif + + /// 8 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int8 i8; + + /// 16 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int16 i16; + + /// 32 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int32 i32; + + /// 64 bit signed integer type. + /// @see gtc_type_precision + typedef detail::int64 i64; + + + /// 8 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i8, defaultp> i8vec1; + + /// 8 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i8, defaultp> i8vec2; + + /// 8 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i8, defaultp> i8vec3; + + /// 8 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i8, defaultp> i8vec4; + + + /// 16 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i16, defaultp> i16vec1; + + /// 16 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i16, defaultp> i16vec2; + + /// 16 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i16, defaultp> i16vec3; + + /// 16 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i16, defaultp> i16vec4; + + + /// 32 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i32, defaultp> i32vec1; + + /// 32 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i32, defaultp> i32vec2; + + /// 32 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i32, defaultp> i32vec3; + + /// 32 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i32, defaultp> i32vec4; + + + /// 64 bit signed integer scalar type. + /// @see gtc_type_precision + typedef tvec1<i64, defaultp> i64vec1; + + /// 64 bit signed integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<i64, defaultp> i64vec2; + + /// 64 bit signed integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<i64, defaultp> i64vec3; + + /// 64 bit signed integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<i64, defaultp> i64vec4; + + + ///////////////////////////// + // Unsigned int vector types + + /// Low precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_uint8; + + /// Low precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_uint16; + + /// Low precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_uint32; + + /// Low precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_uint64; + + /// Low precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_uint8_t; + + /// Low precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_uint16_t; + + /// Low precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_uint32_t; + + /// Low precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_uint64_t; + + /// Low precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 lowp_u8; + + /// Low precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 lowp_u16; + + /// Low precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 lowp_u32; + + /// Low precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 lowp_u64; + + /// Medium precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_uint8; + + /// Medium precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_uint16; + + /// Medium precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_uint32; + + /// Medium precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_uint64; + + /// Medium precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_uint8_t; + + /// Medium precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_uint16_t; + + /// Medium precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_uint32_t; + + /// Medium precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_uint64_t; + + /// Medium precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 mediump_u8; + + /// Medium precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 mediump_u16; + + /// Medium precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 mediump_u32; + + /// Medium precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 mediump_u64; + + /// High precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_uint8; + + /// High precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_uint16; + + /// High precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_uint32; + + /// High precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_uint64; + + /// High precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_uint8_t; + + /// High precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_uint16_t; + + /// High precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_uint32_t; + + /// High precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_uint64_t; + + /// High precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 highp_u8; + + /// High precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 highp_u16; + + /// High precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 highp_u32; + + /// High precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 highp_u64; + + /// Default precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 uint8; + + /// Default precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 uint16; + + /// Default precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 uint32; + + /// Default precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 uint64; + +#if GLM_HAS_EXTENDED_INTEGER_TYPE + using std::uint8_t; + using std::uint16_t; + using std::uint32_t; + using std::uint64_t; +#else + /// Default precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 uint8_t; + + /// Default precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 uint16_t; + + /// Default precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 uint32_t; + + /// Default precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 uint64_t; +#endif + + /// Default precision 8 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint8 u8; + + /// Default precision 16 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint16 u16; + + /// Default precision 32 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint32 u32; + + /// Default precision 64 bit unsigned integer type. + /// @see gtc_type_precision + typedef detail::uint64 u64; + + + + /// Default precision 8 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u8, defaultp> u8vec1; + + /// Default precision 8 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u8, defaultp> u8vec2; + + /// Default precision 8 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u8, defaultp> u8vec3; + + /// Default precision 8 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u8, defaultp> u8vec4; + + + /// Default precision 16 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u16, defaultp> u16vec1; + + /// Default precision 16 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u16, defaultp> u16vec2; + + /// Default precision 16 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u16, defaultp> u16vec3; + + /// Default precision 16 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u16, defaultp> u16vec4; + + + /// Default precision 32 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u32, defaultp> u32vec1; + + /// Default precision 32 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u32, defaultp> u32vec2; + + /// Default precision 32 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u32, defaultp> u32vec3; + + /// Default precision 32 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u32, defaultp> u32vec4; + + + /// Default precision 64 bit unsigned integer scalar type. + /// @see gtc_type_precision + typedef tvec1<u64, defaultp> u64vec1; + + /// Default precision 64 bit unsigned integer vector of 2 components type. + /// @see gtc_type_precision + typedef tvec2<u64, defaultp> u64vec2; + + /// Default precision 64 bit unsigned integer vector of 3 components type. + /// @see gtc_type_precision + typedef tvec3<u64, defaultp> u64vec3; + + /// Default precision 64 bit unsigned integer vector of 4 components type. + /// @see gtc_type_precision + typedef tvec4<u64, defaultp> u64vec4; + + + ////////////////////// + // Float vector types + + /// 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 float32; + + /// 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 float64; + + + /// 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float32 float32_t; + + /// 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef detail::float64 float64_t; + + + /// 32 bit single-precision floating-point scalar. + /// @see gtc_type_precision + typedef float32 f32; + + /// 64 bit double-precision floating-point scalar. + /// @see gtc_type_precision + typedef float64 f64; + + + /// Single-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<float, defaultp> fvec1; + + /// Single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<float, defaultp> fvec2; + + /// Single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<float, defaultp> fvec3; + + /// Single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<float, defaultp> fvec4; + + + /// Single-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<f32, defaultp> f32vec1; + + /// Single-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<f32, defaultp> f32vec2; + + /// Single-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<f32, defaultp> f32vec3; + + /// Single-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<f32, defaultp> f32vec4; + + + /// Double-precision floating-point vector of 1 component. + /// @see gtc_type_precision + typedef tvec1<f64, defaultp> f64vec1; + + /// Double-precision floating-point vector of 2 components. + /// @see gtc_type_precision + typedef tvec2<f64, defaultp> f64vec2; + + /// Double-precision floating-point vector of 3 components. + /// @see gtc_type_precision + typedef tvec3<f64, defaultp> f64vec3; + + /// Double-precision floating-point vector of 4 components. + /// @see gtc_type_precision + typedef tvec4<f64, defaultp> f64vec4; + + + ////////////////////// + // Float matrix types + + /// Single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1<f32> fmat1; + + /// Single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f32, defaultp> fmat2; + + /// Single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f32, defaultp> fmat3; + + /// Single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f32, defaultp> fmat4; + + + /// Single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 fmat1x1; + + /// Single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f32, defaultp> fmat2x2; + + /// Single-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f32, defaultp> fmat2x3; + + /// Single-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f32, defaultp> fmat2x4; + + /// Single-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f32, defaultp> fmat3x2; + + /// Single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f32, defaultp> fmat3x3; + + /// Single-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f32, defaultp> fmat3x4; + + /// Single-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f32, defaultp> fmat4x2; + + /// Single-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f32, defaultp> fmat4x3; + + /// Single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f32, defaultp> fmat4x4; + + + /// Single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1<f32, defaultp> f32mat1; + + /// Single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f32, defaultp> f32mat2; + + /// Single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f32, defaultp> f32mat3; + + /// Single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f32, defaultp> f32mat4; + + + /// Single-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f32 f32mat1x1; + + /// Single-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f32, defaultp> f32mat2x2; + + /// Single-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f32, defaultp> f32mat2x3; + + /// Single-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f32, defaultp> f32mat2x4; + + /// Single-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f32, defaultp> f32mat3x2; + + /// Single-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f32, defaultp> f32mat3x3; + + /// Single-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f32, defaultp> f32mat3x4; + + /// Single-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f32, defaultp> f32mat4x2; + + /// Single-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f32, defaultp> f32mat4x3; + + /// Single-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f32, defaultp> f32mat4x4; + + + /// Double-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef detail::tmat1x1<f64, defaultp> f64mat1; + + /// Double-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f64, defaultp> f64mat2; + + /// Double-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f64, defaultp> f64mat3; + + /// Double-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f64, defaultp> f64mat4; + + + /// Double-precision floating-point 1x1 matrix. + /// @see gtc_type_precision + //typedef f64 f64mat1x1; + + /// Double-precision floating-point 2x2 matrix. + /// @see gtc_type_precision + typedef tmat2x2<f64, defaultp> f64mat2x2; + + /// Double-precision floating-point 2x3 matrix. + /// @see gtc_type_precision + typedef tmat2x3<f64, defaultp> f64mat2x3; + + /// Double-precision floating-point 2x4 matrix. + /// @see gtc_type_precision + typedef tmat2x4<f64, defaultp> f64mat2x4; + + /// Double-precision floating-point 3x2 matrix. + /// @see gtc_type_precision + typedef tmat3x2<f64, defaultp> f64mat3x2; + + /// Double-precision floating-point 3x3 matrix. + /// @see gtc_type_precision + typedef tmat3x3<f64, defaultp> f64mat3x3; + + /// Double-precision floating-point 3x4 matrix. + /// @see gtc_type_precision + typedef tmat3x4<f64, defaultp> f64mat3x4; + + /// Double-precision floating-point 4x2 matrix. + /// @see gtc_type_precision + typedef tmat4x2<f64, defaultp> f64mat4x2; + + /// Double-precision floating-point 4x3 matrix. + /// @see gtc_type_precision + typedef tmat4x3<f64, defaultp> f64mat4x3; + + /// Double-precision floating-point 4x4 matrix. + /// @see gtc_type_precision + typedef tmat4x4<f64, defaultp> f64mat4x4; + + + ////////////////////////// + // Quaternion types + + /// Single-precision floating-point quaternion. + /// @see gtc_type_precision + typedef tquat<f32, defaultp> f32quat; + + /// Double-precision floating-point quaternion. + /// @see gtc_type_precision + typedef tquat<f64, defaultp> f64quat; + + /// @} +}//namespace glm + +#include "type_precision.inl" diff --git a/extensions/common/glm/gtc/type_precision.inl b/extensions/common/glm/gtc/type_precision.inl new file mode 100644 index 0000000000..8a8178228f --- /dev/null +++ b/extensions/common/glm/gtc/type_precision.inl @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_swizzle +/// @file glm/gtc/swizzle.inl +/// @date 2009-06-14 / 2011-06-15 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + +} diff --git a/extensions/common/glm/gtc/type_ptr.hpp b/extensions/common/glm/gtc/type_ptr.hpp new file mode 100644 index 0000000000..ad3a928324 --- /dev/null +++ b/extensions/common/glm/gtc/type_ptr.hpp @@ -0,0 +1,178 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_type_ptr +/// @file glm/gtc/type_ptr.hpp +/// @date 2009-05-06 / 2011-06-05 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtc_type_ptr GLM_GTC_type_ptr +/// @ingroup gtc +/// +/// @brief Handles the interaction between pointers and vector, matrix types. +/// +/// This extension defines an overloaded function, glm::value_ptr, which +/// takes any of the \ref core_template "core template types". It returns +/// a pointer to the memory layout of the object. Matrix types store their values +/// in column-major order. +/// +/// This is useful for uploading data to matrices or copying data to buffer objects. +/// +/// Example: +/// @code +/// #include <glm/glm.hpp> +/// #include <glm/gtc/type_ptr.hpp> +/// +/// glm::vec3 aVector(3); +/// glm::mat4 someMatrix(1.0); +/// +/// glUniform3fv(uniformLoc, 1, glm::value_ptr(aVector)); +/// glUniformMatrix4fv(uniformMatrixLoc, 1, GL_FALSE, glm::value_ptr(someMatrix)); +/// @endcode +/// +/// <glm/gtc/type_ptr.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../gtc/quaternion.hpp" +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../mat2x2.hpp" +#include "../mat2x3.hpp" +#include "../mat2x4.hpp" +#include "../mat3x2.hpp" +#include "../mat3x3.hpp" +#include "../mat3x4.hpp" +#include "../mat4x2.hpp" +#include "../mat4x3.hpp" +#include "../mat4x4.hpp" +#include <cstring> + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_type_ptr extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_type_ptr + /// @{ + + /// Return the constant address to the data of the input parameter. + /// @see gtc_type_ptr + template<typename genType> + GLM_FUNC_DECL typename genType::value_type const * value_ptr(genType const & vec); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tvec2<T, defaultp> make_vec2(T const * const ptr); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tvec3<T, defaultp> make_vec3(T const * const ptr); + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tvec4<T, defaultp> make_vec4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat2x2<T, defaultp> make_mat2x2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat2x3<T, defaultp> make_mat2x3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat2x4<T, defaultp> make_mat2x4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat3x2<T, defaultp> make_mat3x2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat3x3<T, defaultp> make_mat3x3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat3x4<T, defaultp> make_mat3x4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat4x2<T, defaultp> make_mat4x2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat4x3<T, defaultp> make_mat4x3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> make_mat4x4(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat2x2<T, defaultp> make_mat2(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat3x3<T, defaultp> make_mat3(T const * const ptr); + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> make_mat4(T const * const ptr); + + /// Build a quaternion from a pointer. + /// @see gtc_type_ptr + template<typename T> + GLM_FUNC_DECL tquat<T, defaultp> make_quat(T const * const ptr); + + /// @} +}//namespace glm + +#include "type_ptr.inl" diff --git a/extensions/common/glm/gtc/type_ptr.inl b/extensions/common/glm/gtc/type_ptr.inl new file mode 100644 index 0000000000..a08ec5439f --- /dev/null +++ b/extensions/common/glm/gtc/type_ptr.inl @@ -0,0 +1,479 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_type_ptr +/// @file glm/gtc/type_ptr.inl +/// @date 2011-06-15 / 2011-12-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include <cstring> + +namespace glm +{ + /// @addtogroup gtc_type_ptr + /// @{ + + /// Return the constant address to the data of the vector input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tvec2<T, P> const & vec + ) + { + return &(vec.x); + } + + //! Return the address to the data of the vector input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tvec2<T, P> & vec + ) + { + return &(vec.x); + } + + /// Return the constant address to the data of the vector input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tvec3<T, P> const & vec + ) + { + return &(vec.x); + } + + //! Return the address to the data of the vector input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tvec3<T, P> & vec + ) + { + return &(vec.x); + } + + /// Return the constant address to the data of the vector input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tvec4<T, P> const & vec + ) + { + return &(vec.x); + } + + //! Return the address to the data of the vector input. + //! From GLM_GTC_type_ptr extension. + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tvec4<T, P> & vec + ) + { + return &(vec.x); + } + + /// Return the constant address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tmat2x2<T, P> const & mat + ) + { + return &(mat[0].x); + } + + //! Return the address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tmat2x2<T, P> & mat + ) + { + return &(mat[0].x); + } + + /// Return the constant address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tmat3x3<T, P> const & mat + ) + { + return &(mat[0].x); + } + + //! Return the address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tmat3x3<T, P> & mat + ) + { + return &(mat[0].x); + } + + /// Return the constant address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tmat4x4<T, P> const & mat + ) + { + return &(mat[0].x); + } + + //! Return the address to the data of the matrix input. + //! From GLM_GTC_type_ptr extension. + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tmat4x4<T, P> & mat + ) + { + return &(mat[0].x); + } + + /// Return the constant address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tmat2x3<T, P> const & mat + ) + { + return &(mat[0].x); + } + + //! Return the address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tmat2x3<T, P> & mat + ) + { + return &(mat[0].x); + } + + /// Return the constant address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tmat3x2<T, P> const & mat + ) + { + return &(mat[0].x); + } + + //! Return the address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tmat3x2<T, P> & mat + ) + { + return &(mat[0].x); + } + + /// Return the constant address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tmat2x4<T, P> const & mat + ) + { + return &(mat[0].x); + } + + //! Return the address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tmat2x4<T, P> & mat + ) + { + return &(mat[0].x); + } + + /// Return the constant address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tmat4x2<T, P> const & mat + ) + { + return &(mat[0].x); + } + + //! Return the address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tmat4x2<T, P> & mat + ) + { + return &(mat[0].x); + } + + /// Return the constant address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tmat3x4<T, P> const & mat + ) + { + return &(mat[0].x); + } + + //! Return the address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tmat3x4<T, P> & mat + ) + { + return &(mat[0].x); + } + + /// Return the constant address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tmat4x3<T, P> const & mat + ) + { + return &(mat[0].x); + } + + /// Return the address to the data of the matrix input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr(tmat4x3<T, P> & mat) + { + return &(mat[0].x); + } + + /// Return the constant address to the data of the input parameter. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T const * value_ptr + ( + tquat<T, P> const & q + ) + { + return &(q[0]); + } + + /// Return the address to the data of the quaternion input. + /// @see gtc_type_ptr + template<typename T, precision P> + GLM_FUNC_QUALIFIER T * value_ptr + ( + tquat<T, P> & q + ) + { + return &(q[0]); + } + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tvec2<T, defaultp> make_vec2(T const * const ptr) + { + tvec2<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tvec2<T, defaultp>)); + return Result; + } + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tvec3<T, defaultp> make_vec3(T const * const ptr) + { + tvec3<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tvec3<T, defaultp>)); + return Result; + } + + /// Build a vector from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tvec4<T, defaultp> make_vec4(T const * const ptr) + { + tvec4<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tvec4<T, defaultp>)); + return Result; + } + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat2x2<T, defaultp> make_mat2x2(T const * const ptr) + { + tmat2x2<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tmat2x2<T, defaultp>)); + return Result; + } + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat2x3<T, defaultp> make_mat2x3(T const * const ptr) + { + tmat2x3<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tmat2x3<T, defaultp>)); + return Result; + } + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat2x4<T, defaultp> make_mat2x4(T const * const ptr) + { + tmat2x4<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tmat2x4<T, defaultp>)); + return Result; + } + + /// Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat3x2<T, defaultp> make_mat3x2(T const * const ptr) + { + tmat3x2<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tmat3x2<T, defaultp>)); + return Result; + } + + //! Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat3x3<T, defaultp> make_mat3x3(T const * const ptr) + { + tmat3x3<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tmat3x3<T, defaultp>)); + return Result; + } + + //! Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat3x4<T, defaultp> make_mat3x4(T const * const ptr) + { + tmat3x4<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tmat3x4<T, defaultp>)); + return Result; + } + + //! Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat4x2<T, defaultp> make_mat4x2(T const * const ptr) + { + tmat4x2<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tmat4x2<T, defaultp>)); + return Result; + } + + //! Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat4x3<T, defaultp> make_mat4x3(T const * const ptr) + { + tmat4x3<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tmat4x3<T, defaultp>)); + return Result; + } + + //! Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> make_mat4x4(T const * const ptr) + { + tmat4x4<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tmat4x4<T, defaultp>)); + return Result; + } + + //! Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat2x2<T, defaultp> make_mat2(T const * const ptr) + { + return make_mat2x2(ptr); + } + + //! Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat3x3<T, defaultp> make_mat3(T const * const ptr) + { + return make_mat3x3(ptr); + } + + //! Build a matrix from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> make_mat4(T const * const ptr) + { + return make_mat4x4(ptr); + } + + //! Build a quaternion from a pointer. + /// @see gtc_type_ptr + template <typename T> + GLM_FUNC_QUALIFIER tquat<T, defaultp> make_quat(T const * const ptr) + { + tquat<T, defaultp> Result; + memcpy(value_ptr(Result), ptr, sizeof(tquat<T, defaultp>)); + return Result; + } + + /// @} +}//namespace glm + diff --git a/extensions/common/glm/gtc/ulp.hpp b/extensions/common/glm/gtc/ulp.hpp new file mode 100644 index 0000000000..a0233e0062 --- /dev/null +++ b/extensions/common/glm/gtc/ulp.hpp @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_ulp +/// @file glm/gtc/ulp.hpp +/// @date 2011-02-21 / 2011-12-12 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtc_ulp GLM_GTC_ulp +/// @ingroup gtc +/// +/// @brief Allow the measurement of the accuracy of a function against a reference +/// implementation. This extension works on floating-point data and provide results +/// in ULP. +/// <glm/gtc/ulp.hpp> need to be included to use these features. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/precision.hpp" +#include "../detail/type_int.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_ulp extension included") +#endif + +namespace glm +{ + /// @addtogroup gtc_ulp + /// @{ + + /// Return the next ULP value(s) after the input value(s). + /// @see gtc_ulp + template <typename genType> + GLM_FUNC_DECL genType next_float(genType const & x); + + /// Return the previous ULP value(s) before the input value(s). + /// @see gtc_ulp + template <typename genType> + GLM_FUNC_DECL genType prev_float(genType const & x); + + /// Return the value(s) ULP distance after the input value(s). + /// @see gtc_ulp + template <typename genType> + GLM_FUNC_DECL genType next_float(genType const & x, uint const & Distance); + + /// Return the value(s) ULP distance before the input value(s). + /// @see gtc_ulp + template <typename genType> + GLM_FUNC_DECL genType prev_float(genType const & x, uint const & Distance); + + /// Return the distance in the number of ULP between 2 scalars. + /// @see gtc_ulp + template <typename T> + GLM_FUNC_DECL uint float_distance(T const & x, T const & y); + + /// Return the distance in the number of ULP between 2 vectors. + /// @see gtc_ulp + template<typename T, template<typename> class vecType> + GLM_FUNC_DECL vecType<uint> float_distance(vecType<T> const & x, vecType<T> const & y); + + /// @} +}// namespace glm + +#include "ulp.inl" diff --git a/extensions/common/glm/gtc/ulp.inl b/extensions/common/glm/gtc/ulp.inl new file mode 100644 index 0000000000..e91fee68ee --- /dev/null +++ b/extensions/common/glm/gtc/ulp.inl @@ -0,0 +1,350 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_ulp +/// @file glm/gtc/ulp.inl +/// @date 2011-03-07 / 2012-04-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// +/// Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. +/// +/// Developed at SunPro, a Sun Microsystems, Inc. business. +/// Permission to use, copy, modify, and distribute this +/// software is freely granted, provided that this notice +/// is preserved. +/////////////////////////////////////////////////////////////////////////////////// + +#include "../detail/type_int.hpp" +#include <cmath> +#include <cfloat> +#include <limits> + +#if(GLM_COMPILER & GLM_COMPILER_VC) +# pragma warning(push) +# pragma warning(disable : 4127) +#endif + +typedef union +{ + float value; + /* FIXME: Assumes 32 bit int. */ + unsigned int word; +} ieee_float_shape_type; + +typedef union +{ + double value; + struct + { + glm::detail::int32 lsw; + glm::detail::int32 msw; + } parts; +} ieee_double_shape_type; + +#define GLM_EXTRACT_WORDS(ix0,ix1,d) \ + do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ + } while (0) + +#define GLM_GET_FLOAT_WORD(i,d) \ + do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ + } while (0) + +#define GLM_SET_FLOAT_WORD(d,i) \ + do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ + } while (0) + +#define GLM_INSERT_WORDS(d,ix0,ix1) \ + do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ + } while (0) + +namespace glm{ +namespace detail +{ + GLM_FUNC_QUALIFIER float nextafterf(float x, float y) + { + volatile float t; + glm::detail::int32 hx, hy, ix, iy; + + GLM_GET_FLOAT_WORD(hx, x); + GLM_GET_FLOAT_WORD(hy, y); + ix = hx&0x7fffffff; // |x| + iy = hy&0x7fffffff; // |y| + + if((ix>0x7f800000) || // x is nan + (iy>0x7f800000)) // y is nan + return x+y; + if(x==y) return y; // x=y, return y + if(ix==0) { // x == 0 + GLM_SET_FLOAT_WORD(x,(hy&0x80000000)|1);// return +-minsubnormal + t = x*x; + if(t==x) return t; else return x; // raise underflow flag + } + if(hx>=0) { // x > 0 + if(hx>hy) { // x > y, x -= ulp + hx -= 1; + } else { // x < y, x += ulp + hx += 1; + } + } else { // x < 0 + if(hy>=0||hx>hy){ // x < y, x -= ulp + hx -= 1; + } else { // x > y, x += ulp + hx += 1; + } + } + hy = hx&0x7f800000; + if(hy>=0x7f800000) return x+x; // overflow + if(hy<0x00800000) { // underflow + t = x*x; + if(t!=x) { // raise underflow flag + GLM_SET_FLOAT_WORD(y,hx); + return y; + } + } + GLM_SET_FLOAT_WORD(x,hx); + return x; + } + + GLM_FUNC_QUALIFIER double nextafter(double x, double y) + { + volatile double t; + glm::detail::int32 hx, hy, ix, iy; + glm::detail::uint32 lx, ly; + + GLM_EXTRACT_WORDS(hx, lx, x); + GLM_EXTRACT_WORDS(hy, ly, y); + ix = hx & 0x7fffffff; // |x| + iy = hy & 0x7fffffff; // |y| + + if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) || // x is nan + ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0)) // y is nan + return x+y; + if(x==y) return y; // x=y, return y + if((ix|lx)==0) { // x == 0 + GLM_INSERT_WORDS(x, hy & 0x80000000, 1); // return +-minsubnormal + t = x*x; + if(t==x) return t; else return x; // raise underflow flag + } + if(hx>=0) { // x > 0 + if(hx>hy||((hx==hy)&&(lx>ly))) { // x > y, x -= ulp + if(lx==0) hx -= 1; + lx -= 1; + } else { // x < y, x += ulp + lx += 1; + if(lx==0) hx += 1; + } + } else { // x < 0 + if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){// x < y, x -= ulp + if(lx==0) hx -= 1; + lx -= 1; + } else { // x > y, x += ulp + lx += 1; + if(lx==0) hx += 1; + } + } + hy = hx&0x7ff00000; + if(hy>=0x7ff00000) return x+x; // overflow + if(hy<0x00100000) { // underflow + t = x*x; + if(t!=x) { // raise underflow flag + GLM_INSERT_WORDS(y,hx,lx); + return y; + } + } + GLM_INSERT_WORDS(x,hx,lx); + return x; + } +}//namespace detail +}//namespace glm + +#if(GLM_COMPILER & GLM_COMPILER_VC) +# pragma warning(pop) +#endif + +namespace glm +{ + template <> + GLM_FUNC_QUALIFIER float next_float(float const & x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits<float>::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafterf(x, FLT_MAX); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafterf(x, FLT_MAX); +# else + return nextafterf(x, FLT_MAX); +# endif + } + + template <> + GLM_FUNC_QUALIFIER double next_float(double const & x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits<double>::max()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafter(x, std::numeric_limits<double>::max()); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, FLT_MAX); +# else + return nextafter(x, DBL_MAX); +# endif + } + + template<typename T, precision P, template<typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> next_float(vecType<T, P> const & x) + { + vecType<T, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = next_float(x[i]); + return Result; + } + + GLM_FUNC_QUALIFIER float prev_float(float const & x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits<float>::min()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return detail::nextafterf(x, FLT_MIN); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafterf(x, FLT_MIN); +# else + return nextafterf(x, FLT_MIN); +# endif + } + + GLM_FUNC_QUALIFIER double prev_float(double const & x) + { +# if GLM_HAS_CXX11_STL + return std::nextafter(x, std::numeric_limits<double>::min()); +# elif((GLM_COMPILER & GLM_COMPILER_VC) || ((GLM_COMPILER & GLM_COMPILER_INTEL) && (GLM_PLATFORM & GLM_PLATFORM_WINDOWS))) + return _nextafter(x, DBL_MIN); +# elif(GLM_PLATFORM & GLM_PLATFORM_ANDROID) + return __builtin_nextafter(x, DBL_MIN); +# else + return nextafter(x, DBL_MIN); +# endif + } + + template<typename T, precision P, template<typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> prev_float(vecType<T, P> const & x) + { + vecType<T, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = prev_float(x[i]); + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER T next_float(T const & x, uint const & ulps) + { + T temp = x; + for(uint i = 0; i < ulps; ++i) + temp = next_float(temp); + return temp; + } + + template<typename T, precision P, template<typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> next_float(vecType<T, P> const & x, vecType<uint, P> const & ulps) + { + vecType<T, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = next_float(x[i], ulps[i]); + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER T prev_float(T const & x, uint const & ulps) + { + T temp = x; + for(uint i = 0; i < ulps; ++i) + temp = prev_float(temp); + return temp; + } + + template<typename T, precision P, template<typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> prev_float(vecType<T, P> const & x, vecType<uint, P> const & ulps) + { + vecType<T, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = prev_float(x[i], ulps[i]); + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER uint float_distance(T const & x, T const & y) + { + uint ulp = 0; + + if(x < y) + { + T temp = x; + while(temp != y)// && ulp < std::numeric_limits<std::size_t>::max()) + { + ++ulp; + temp = next_float(temp); + } + } + else if(y < x) + { + T temp = y; + while(temp != x)// && ulp < std::numeric_limits<std::size_t>::max()) + { + ++ulp; + temp = next_float(temp); + } + } + else // == + { + + } + + return ulp; + } + + template<typename T, precision P, template<typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<uint, P> float_distance(vecType<T, P> const & x, vecType<T, P> const & y) + { + vecType<uint, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = float_distance(x[i], y[i]); + return Result; + } +}//namespace glm diff --git a/extensions/common/glm/gtc/vec1.hpp b/extensions/common/glm/gtc/vec1.hpp new file mode 100644 index 0000000000..0846755356 --- /dev/null +++ b/extensions/common/glm/gtc/vec1.hpp @@ -0,0 +1,193 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_vec1 +/// @file glm/gtc/vec1.hpp +/// @date 2010-02-08 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtc_vec1 GLM_GTC_vec1 +/// @ingroup gtc +/// +/// @brief Add vec1, ivec1, uvec1 and bvec1 types. +/// <glm/gtc/vec1.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../detail/type_vec1.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTC_vec1 extension included") +#endif + +namespace glm +{ + /// 1 component vector of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef highp_vec1_t highp_vec1; + + /// 1 component vector of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef mediump_vec1_t mediump_vec1; + + /// 1 component vector of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef lowp_vec1_t lowp_vec1; + + /// 1 component vector of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef highp_dvec1_t highp_dvec1; + + /// 1 component vector of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef mediump_dvec1_t mediump_dvec1; + + /// 1 component vector of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef lowp_dvec1_t lowp_dvec1; + + /// 1 component vector of high precision signed integer numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef highp_ivec1_t highp_ivec1; + + /// 1 component vector of medium precision signed integer numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef mediump_ivec1_t mediump_ivec1; + + /// 1 component vector of low precision signed integer numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef lowp_ivec1_t lowp_ivec1; + + /// 1 component vector of high precision unsigned integer numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef highp_uvec1_t highp_uvec1; + + /// 1 component vector of medium precision unsigned integer numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef mediump_uvec1_t mediump_uvec1; + + /// 1 component vector of low precision unsigned integer numbers. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef lowp_uvec1_t lowp_uvec1; + + /// 1 component vector of high precision boolean. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef highp_bvec1_t highp_bvec1; + + /// 1 component vector of medium precision boolean. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef mediump_bvec1_t mediump_bvec1; + + /// 1 component vector of low precision boolean. + /// There is no guarantee on the actual precision. + /// @see gtc_vec1 extension. + typedef lowp_bvec1_t lowp_bvec1; + + ////////////////////////// + // vec1 definition + +#if(defined(GLM_PRECISION_HIGHP_BOOL)) + typedef highp_bvec1 bvec1; +#elif(defined(GLM_PRECISION_MEDIUMP_BOOL)) + typedef mediump_bvec1 bvec1; +#elif(defined(GLM_PRECISION_LOWP_BOOL)) + typedef lowp_bvec1 bvec1; +#else + /// 1 component vector of boolean. + /// @see gtc_vec1 extension. + typedef highp_bvec1 bvec1; +#endif//GLM_PRECISION + +#if(defined(GLM_PRECISION_HIGHP_FLOAT)) + typedef highp_vec1 vec1; +#elif(defined(GLM_PRECISION_MEDIUMP_FLOAT)) + typedef mediump_vec1 vec1; +#elif(defined(GLM_PRECISION_LOWP_FLOAT)) + typedef lowp_vec1 vec1; +#else + /// 1 component vector of floating-point numbers. + /// @see gtc_vec1 extension. + typedef highp_vec1 vec1; +#endif//GLM_PRECISION + +#if(defined(GLM_PRECISION_HIGHP_DOUBLE)) + typedef highp_dvec1 dvec1; +#elif(defined(GLM_PRECISION_MEDIUMP_DOUBLE)) + typedef mediump_dvec1 dvec1; +#elif(defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef lowp_dvec1 dvec1; +#else + /// 1 component vector of floating-point numbers. + /// @see gtc_vec1 extension. + typedef highp_dvec1 dvec1; +#endif//GLM_PRECISION + +#if(defined(GLM_PRECISION_HIGHP_INT)) + typedef highp_ivec1 ivec1; +#elif(defined(GLM_PRECISION_MEDIUMP_INT)) + typedef mediump_ivec1 ivec1; +#elif(defined(GLM_PRECISION_LOWP_INT)) + typedef lowp_ivec1 ivec1; +#else + /// 1 component vector of signed integer numbers. + /// @see gtc_vec1 extension. + typedef highp_ivec1 ivec1; +#endif//GLM_PRECISION + +#if(defined(GLM_PRECISION_HIGHP_UINT)) + typedef highp_uvec1 uvec1; +#elif(defined(GLM_PRECISION_MEDIUMP_UINT)) + typedef mediump_uvec1 uvec1; +#elif(defined(GLM_PRECISION_LOWP_UINT)) + typedef lowp_uvec1 uvec1; +#else + /// 1 component vector of unsigned integer numbers. + /// @see gtc_vec1 extension. + typedef highp_uvec1 uvec1; +#endif//GLM_PRECISION + +}// namespace glm + +#include "vec1.inl" diff --git a/extensions/common/glm/gtc/vec1.inl b/extensions/common/glm/gtc/vec1.inl new file mode 100644 index 0000000000..06b614a5df --- /dev/null +++ b/extensions/common/glm/gtc/vec1.inl @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_vec1 +/// @file glm/gtc/vec1.inl +/// @date 2013-03-16 / 2013-03-16 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// diff --git a/extensions/common/glm/gtx/associated_min_max.hpp b/extensions/common/glm/gtx/associated_min_max.hpp new file mode 100644 index 0000000000..88ea687ecb --- /dev/null +++ b/extensions/common/glm/gtx/associated_min_max.hpp @@ -0,0 +1,231 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_associated_min_max +/// @file glm/gtx/associated_min_max.hpp +/// @date 2008-03-10 / 2014-10-11 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_associated_min_max GLM_GTX_associated_min_max +/// @ingroup gtx +/// +/// @brief Min and max functions that return associated values not the compared onces. +/// <glm/gtx/associated_min_max.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_associated_min_max extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_associated_min_max + /// @{ + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P> + GLM_FUNC_DECL U associatedMin(T x, U a, T y, U b); + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL tvec2<U, P> associatedMin( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b); + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMin( + T x, const vecType<U, P>& a, + T y, const vecType<U, P>& b); + + /// Minimum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMin( + vecType<T, P> const & x, U a, + vecType<T, P> const & y, U b); + + /// Minimum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U> + GLM_FUNC_DECL U associatedMin( + T x, U a, + T y, U b, + T z, U c); + + /// Minimum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMin( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b, + vecType<T, P> const & z, vecType<U, P> const & c); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U> + GLM_FUNC_DECL U associatedMin( + T x, U a, + T y, U b, + T z, U c, + T w, U d); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMin( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b, + vecType<T, P> const & z, vecType<U, P> const & c, + vecType<T, P> const & w, vecType<U, P> const & d); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMin( + T x, vecType<U, P> const & a, + T y, vecType<U, P> const & b, + T z, vecType<U, P> const & c, + T w, vecType<U, P> const & d); + + /// Minimum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMin( + vecType<T, P> const & x, U a, + vecType<T, P> const & y, U b, + vecType<T, P> const & z, U c, + vecType<T, P> const & w, U d); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U> + GLM_FUNC_DECL U associatedMax(T x, U a, T y, U b); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL tvec2<U, P> associatedMax( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> associatedMax( + T x, vecType<U, P> const & a, + T y, vecType<U, P> const & b); + + /// Maximum comparison between 2 variables and returns 2 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMax( + vecType<T, P> const & x, U a, + vecType<T, P> const & y, U b); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U> + GLM_FUNC_DECL U associatedMax( + T x, U a, + T y, U b, + T z, U c); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMax( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b, + vecType<T, P> const & z, vecType<U, P> const & c); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> associatedMax( + T x, vecType<U, P> const & a, + T y, vecType<U, P> const & b, + T z, vecType<U, P> const & c); + + /// Maximum comparison between 3 variables and returns 3 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMax( + vecType<T, P> const & x, U a, + vecType<T, P> const & y, U b, + vecType<T, P> const & z, U c); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U> + GLM_FUNC_DECL U associatedMax( + T x, U a, + T y, U b, + T z, U c, + T w, U d); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMax( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b, + vecType<T, P> const & z, vecType<U, P> const & c, + vecType<T, P> const & w, vecType<U, P> const & d); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMax( + T x, vecType<U, P> const & a, + T y, vecType<U, P> const & b, + T z, vecType<U, P> const & c, + T w, vecType<U, P> const & d); + + /// Maximum comparison between 4 variables and returns 4 associated variable values + /// @see gtx_associated_min_max + template<typename T, typename U, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<U, P> associatedMax( + vecType<T, P> const & x, U a, + vecType<T, P> const & y, U b, + vecType<T, P> const & z, U c, + vecType<T, P> const & w, U d); + + /// @} +} //namespace glm + +#include "associated_min_max.inl" diff --git a/extensions/common/glm/gtx/associated_min_max.inl b/extensions/common/glm/gtx/associated_min_max.inl new file mode 100644 index 0000000000..0773a21297 --- /dev/null +++ b/extensions/common/glm/gtx/associated_min_max.inl @@ -0,0 +1,384 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_associated_min_max +/// @file glm/gtx/associated_min_max.inl +/// @date 2008-03-10 / 2014-10-11 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ + +// Min comparison between 2 variables +template<typename T, typename U, precision P> +GLM_FUNC_QUALIFIER U associatedMin(T x, U a, T y, U b) +{ + return x < y ? a : b; +} + +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER tvec2<U, P> associatedMin +( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = x[i] < y[i] ? a[i] : b[i]; + return Result; +} + +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMin +( + T x, const vecType<U, P>& a, + T y, const vecType<U, P>& b +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = x < y ? a[i] : b[i]; + return Result; +} + +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMin +( + vecType<T, P> const & x, U a, + vecType<T, P> const & y, U b +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = x[i] < y[i] ? a : b; + return Result; +} + +// Min comparison between 3 variables +template<typename T, typename U> +GLM_FUNC_QUALIFIER U associatedMin +( + T x, U a, + T y, U b, + T z, U c +) +{ + U Result = x < y ? (x < z ? a : c) : (y < z ? b : c); + return Result; +} + +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMin +( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b, + vecType<T, P> const & z, vecType<U, P> const & c +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = x[i] < y[i] ? (x[i] < z[i] ? a[i] : c[i]) : (y[i] < z[i] ? b[i] : c[i]); + return Result; +} + +// Min comparison between 4 variables +template<typename T, typename U> +GLM_FUNC_QUALIFIER U associatedMin +( + T x, U a, + T y, U b, + T z, U c, + T w, U d +) +{ + T Test1 = min(x, y); + T Test2 = min(z, w);; + U Result1 = x < y ? a : b; + U Result2 = z < w ? c : d; + U Result = Test1 < Test2 ? Result1 : Result2; + return Result; +} + +// Min comparison between 4 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMin +( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b, + vecType<T, P> const & z, vecType<U, P> const & c, + vecType<T, P> const & w, vecType<U, P> const & d +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + { + T Test1 = min(x[i], y[i]); + T Test2 = min(z[i], w[i]); + U Result1 = x[i] < y[i] ? a[i] : b[i]; + U Result2 = z[i] < w[i] ? c[i] : d[i]; + Result[i] = Test1 < Test2 ? Result1 : Result2; + } + return Result; +} + +// Min comparison between 4 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMin +( + T x, vecType<U, P> const & a, + T y, vecType<U, P> const & b, + T z, vecType<U, P> const & c, + T w, vecType<U, P> const & d +) +{ + T Test1 = min(x, y); + T Test2 = min(z, w); + + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + { + U Result1 = x < y ? a[i] : b[i]; + U Result2 = z < w ? c[i] : d[i]; + Result[i] = Test1 < Test2 ? Result1 : Result2; + } + return Result; +} + +// Min comparison between 4 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMin +( + vecType<T, P> const & x, U a, + vecType<T, P> const & y, U b, + vecType<T, P> const & z, U c, + vecType<T, P> const & w, U d +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + { + T Test1 = min(x[i], y[i]); + T Test2 = min(z[i], w[i]);; + U Result1 = x[i] < y[i] ? a : b; + U Result2 = z[i] < w[i] ? c : d; + Result[i] = Test1 < Test2 ? Result1 : Result2; + } + return Result; +} + +// Max comparison between 2 variables +template<typename T, typename U> +GLM_FUNC_QUALIFIER U associatedMax(T x, U a, T y, U b) +{ + return x > y ? a : b; +} + +// Max comparison between 2 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER tvec2<U, P> associatedMax +( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = x[i] > y[i] ? a[i] : b[i]; + return Result; +} + +// Max comparison between 2 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<T, P> associatedMax +( + T x, vecType<U, P> const & a, + T y, vecType<U, P> const & b +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = x > y ? a[i] : b[i]; + return Result; +} + +// Max comparison between 2 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMax +( + vecType<T, P> const & x, U a, + vecType<T, P> const & y, U b +) +{ + vecType<T, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = x[i] > y[i] ? a : b; + return Result; +} + +// Max comparison between 3 variables +template<typename T, typename U> +GLM_FUNC_QUALIFIER U associatedMax +( + T x, U a, + T y, U b, + T z, U c +) +{ + U Result = x > y ? (x > z ? a : c) : (y > z ? b : c); + return Result; +} + +// Max comparison between 3 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMax +( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b, + vecType<T, P> const & z, vecType<U, P> const & c +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = x[i] > y[i] ? (x[i] > z[i] ? a[i] : c[i]) : (y[i] > z[i] ? b[i] : c[i]); + return Result; +} + +// Max comparison between 3 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<T, P> associatedMax +( + T x, vecType<U, P> const & a, + T y, vecType<U, P> const & b, + T z, vecType<U, P> const & c +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = x > y ? (x > z ? a[i] : c[i]) : (y > z ? b[i] : c[i]); + return Result; +} + +// Max comparison between 3 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMax +( + vecType<T, P> const & x, U a, + vecType<T, P> const & y, U b, + vecType<T, P> const & z, U c +) +{ + vecType<T, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + Result[i] = x[i] > y[i] ? (x[i] > z[i] ? a : c) : (y[i] > z[i] ? b : c); + return Result; +} + +// Max comparison between 4 variables +template<typename T, typename U> +GLM_FUNC_QUALIFIER U associatedMax +( + T x, U a, + T y, U b, + T z, U c, + T w, U d +) +{ + T Test1 = max(x, y); + T Test2 = max(z, w);; + U Result1 = x > y ? a : b; + U Result2 = z > w ? c : d; + U Result = Test1 > Test2 ? Result1 : Result2; + return Result; +} + +// Max comparison between 4 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMax +( + vecType<T, P> const & x, vecType<U, P> const & a, + vecType<T, P> const & y, vecType<U, P> const & b, + vecType<T, P> const & z, vecType<U, P> const & c, + vecType<T, P> const & w, vecType<U, P> const & d +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + { + T Test1 = max(x[i], y[i]); + T Test2 = max(z[i], w[i]); + U Result1 = x[i] > y[i] ? a[i] : b[i]; + U Result2 = z[i] > w[i] ? c[i] : d[i]; + Result[i] = Test1 > Test2 ? Result1 : Result2; + } + return Result; +} + +// Max comparison between 4 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMax +( + T x, vecType<U, P> const & a, + T y, vecType<U, P> const & b, + T z, vecType<U, P> const & c, + T w, vecType<U, P> const & d +) +{ + T Test1 = max(x, y); + T Test2 = max(z, w); + + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + { + U Result1 = x > y ? a[i] : b[i]; + U Result2 = z > w ? c[i] : d[i]; + Result[i] = Test1 > Test2 ? Result1 : Result2; + } + return Result; +} + +// Max comparison between 4 variables +template<typename T, typename U, precision P, template <typename, precision> class vecType> +GLM_FUNC_QUALIFIER vecType<U, P> associatedMax +( + vecType<T, P> const & x, U a, + vecType<T, P> const & y, U b, + vecType<T, P> const & z, U c, + vecType<T, P> const & w, U d +) +{ + vecType<U, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(Result); ++i) + { + T Test1 = max(x[i], y[i]); + T Test2 = max(z[i], w[i]);; + U Result1 = x[i] > y[i] ? a : b; + U Result2 = z[i] > w[i] ? c : d; + Result[i] = Test1 > Test2 ? Result1 : Result2; + } + return Result; +} +}//namespace glm diff --git a/extensions/common/glm/gtx/bit.hpp b/extensions/common/glm/gtx/bit.hpp new file mode 100644 index 0000000000..7ac226e9bd --- /dev/null +++ b/extensions/common/glm/gtx/bit.hpp @@ -0,0 +1,120 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_bit +/// @file glm/gtx/bit.hpp +/// @date 2007-03-14 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// +/// @defgroup gtx_bit GLM_GTX_bit +/// @ingroup gtx +/// +/// @brief Allow to perform bit operations on integer values +/// +/// <glm/gtx/bit.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../gtc/bitfield.hpp" + +#if(defined(GLM_MESSAGES)) +# pragma message("GLM: GLM_GTX_bit extension is deprecated, include GLM_GTC_bitfield and GLM_GTC_integer instead") +#endif + +namespace glm +{ + /// @addtogroup gtx_bit + /// @{ + + /// @see gtx_bit + template <typename genIUType> + GLM_FUNC_DECL genIUType highestBitValue(genIUType Value); + + /// Find the highest bit set to 1 in a integer variable and return its value. + /// + /// @see gtx_bit + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> highestBitValue(vecType<T, P> const & value); + + /// Return the power of two number which value is just higher the input value. + /// Deprecated, use ceilPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template <typename genIUType> + GLM_DEPRECATED GLM_FUNC_DECL genIUType powerOfTwoAbove(genIUType Value); + + /// Return the power of two number which value is just higher the input value. + /// Deprecated, use ceilPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template <typename T, precision P, template <typename, precision> class vecType> + GLM_DEPRECATED GLM_FUNC_DECL vecType<T, P> powerOfTwoAbove(vecType<T, P> const & value); + + /// Return the power of two number which value is just lower the input value. + /// Deprecated, use floorPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template <typename genIUType> + GLM_DEPRECATED GLM_FUNC_DECL genIUType powerOfTwoBelow(genIUType Value); + + /// Return the power of two number which value is just lower the input value. + /// Deprecated, use floorPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template <typename T, precision P, template <typename, precision> class vecType> + GLM_DEPRECATED GLM_FUNC_DECL vecType<T, P> powerOfTwoBelow(vecType<T, P> const & value); + + /// Return the power of two number which value is the closet to the input value. + /// Deprecated, use roundPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template <typename genIUType> + GLM_DEPRECATED GLM_FUNC_DECL genIUType powerOfTwoNearest(genIUType Value); + + /// Return the power of two number which value is the closet to the input value. + /// Deprecated, use roundPowerOfTwo from GTC_round instead + /// + /// @see gtc_round + /// @see gtx_bit + template <typename T, precision P, template <typename, precision> class vecType> + GLM_DEPRECATED GLM_FUNC_DECL vecType<T, P> powerOfTwoNearest(vecType<T, P> const & value); + + /// @} +} //namespace glm + + +#include "bit.inl" + diff --git a/extensions/common/glm/gtx/bit.inl b/extensions/common/glm/gtx/bit.inl new file mode 100644 index 0000000000..1bfc96dbde --- /dev/null +++ b/extensions/common/glm/gtx/bit.inl @@ -0,0 +1,107 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_bit +/// @file glm/gtx/bit.inl +/// @date 2014-11-25 / 2014-11-25 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + /////////////////// + // highestBitValue + + template <typename genIUType> + GLM_FUNC_QUALIFIER genIUType highestBitValue(genIUType Value) + { + genIUType tmp = Value; + genIUType result = genIUType(0); + while(tmp) + { + result = (tmp & (~tmp + 1)); // grab lowest bit + tmp &= ~result; // clear lowest bit + } + return result; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> highestBitValue(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(highestBitValue, v); + } + + /////////////////// + // powerOfTwoAbove + + template <typename genType> + GLM_FUNC_QUALIFIER genType powerOfTwoAbove(genType value) + { + return isPowerOfTwo(value) ? value : highestBitValue(value) << 1; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> powerOfTwoAbove(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(powerOfTwoAbove, v); + } + + /////////////////// + // powerOfTwoBelow + + template <typename genType> + GLM_FUNC_QUALIFIER genType powerOfTwoBelow(genType value) + { + return isPowerOfTwo(value) ? value : highestBitValue(value); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> powerOfTwoBelow(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(powerOfTwoBelow, v); + } + + ///////////////////// + // powerOfTwoNearest + + template <typename genType> + GLM_FUNC_QUALIFIER genType powerOfTwoNearest(genType value) + { + if(isPowerOfTwo(value)) + return value; + + genType const prev = highestBitValue(value); + genType const next = prev << 1; + return (next - value) < (value - prev) ? next : prev; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> powerOfTwoNearest(vecType<T, P> const & v) + { + return detail::functor1<T, T, P, vecType>::call(powerOfTwoNearest, v); + } + +}//namespace glm diff --git a/extensions/common/glm/gtx/closest_point.hpp b/extensions/common/glm/gtx/closest_point.hpp new file mode 100644 index 0000000000..2bee31fabc --- /dev/null +++ b/extensions/common/glm/gtx/closest_point.hpp @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_closest_point +/// @file glm/gtx/closest_point.hpp +/// @date 2005-12-30 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_closest_point GLM_GTX_closest_point +/// @ingroup gtx +/// +/// @brief Find the point on a straight line which is the closet of a point. +/// +/// <glm/gtx/closest_point.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_closest_point extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_closest_point + /// @{ + + /// Find the point on a straight line which is the closet of a point. + /// @see gtx_closest_point + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> closestPointOnLine( + tvec3<T, P> const & point, + tvec3<T, P> const & a, + tvec3<T, P> const & b); + + /// 2d lines work as well + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> closestPointOnLine( + tvec2<T, P> const & point, + tvec2<T, P> const & a, + tvec2<T, P> const & b); + + /// @} +}// namespace glm + +#include "closest_point.inl" diff --git a/extensions/common/glm/gtx/closest_point.inl b/extensions/common/glm/gtx/closest_point.inl new file mode 100644 index 0000000000..358b202f72 --- /dev/null +++ b/extensions/common/glm/gtx/closest_point.inl @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_closest_point +/// @file glm/gtx/closest_point.inl +/// @date 2005-12-30 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> closestPointOnLine + ( + tvec3<T, P> const & point, + tvec3<T, P> const & a, + tvec3<T, P> const & b + ) + { + T LineLength = distance(a, b); + tvec3<T, P> Vector = point - a; + tvec3<T, P> LineDirection = (b - a) / LineLength; + + // Project Vector to LineDirection to get the distance of point from a + T Distance = dot(Vector, LineDirection); + + if(Distance <= T(0)) return a; + if(Distance >= LineLength) return b; + return a + LineDirection * Distance; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> closestPointOnLine + ( + tvec2<T, P> const & point, + tvec2<T, P> const & a, + tvec2<T, P> const & b + ) + { + T LineLength = distance(a, b); + tvec2<T, P> Vector = point - a; + tvec2<T, P> LineDirection = (b - a) / LineLength; + + // Project Vector to LineDirection to get the distance of point from a + T Distance = dot(Vector, LineDirection); + + if(Distance <= T(0)) return a; + if(Distance >= LineLength) return b; + return a + LineDirection * Distance; + } + +}//namespace glm diff --git a/extensions/common/glm/gtx/color_space.hpp b/extensions/common/glm/gtx/color_space.hpp new file mode 100644 index 0000000000..7306da15cf --- /dev/null +++ b/extensions/common/glm/gtx/color_space.hpp @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_color_space +/// @file glm/gtx/color_space.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_color_space GLM_GTX_color_space +/// @ingroup gtx +/// +/// @brief Related to RGB to HSV conversions and operations. +/// +/// <glm/gtx/color_space.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_color_space extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_color_space + /// @{ + + /// Converts a color from HSV color space to its color in RGB color space. + /// @see gtx_color_space + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> rgbColor( + tvec3<T, P> const & hsvValue); + + /// Converts a color from RGB color space to its color in HSV color space. + /// @see gtx_color_space + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> hsvColor( + tvec3<T, P> const & rgbValue); + + /// Build a saturation matrix. + /// @see gtx_color_space + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> saturation( + T const s); + + /// Modify the saturation of a color. + /// @see gtx_color_space + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> saturation( + T const s, + tvec3<T, P> const & color); + + /// Modify the saturation of a color. + /// @see gtx_color_space + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> saturation( + T const s, + tvec4<T, P> const & color); + + /// Compute color luminosity associating ratios (0.33, 0.59, 0.11) to RGB canals. + /// @see gtx_color_space + template <typename T, precision P> + GLM_FUNC_DECL T luminosity( + tvec3<T, P> const & color); + + /// @} +}//namespace glm + +#include "color_space.inl" diff --git a/extensions/common/glm/gtx/color_space.inl b/extensions/common/glm/gtx/color_space.inl new file mode 100644 index 0000000000..0dd2a141d0 --- /dev/null +++ b/extensions/common/glm/gtx/color_space.inl @@ -0,0 +1,172 @@ +///////////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_color_space +/// @file glm/gtx/color_space.inl +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> rgbColor(const tvec3<T, P>& hsvColor) + { + tvec3<T, P> hsv = hsvColor; + tvec3<T, P> rgbColor; + + if(hsv.y == static_cast<T>(0)) + // achromatic (grey) + rgbColor = tvec3<T, P>(hsv.z); + else + { + T sector = floor(hsv.x / T(60)); + T frac = (hsv.x / T(60)) - sector; + // factorial part of h + T o = hsv.z * (T(1) - hsv.y); + T p = hsv.z * (T(1) - hsv.y * frac); + T q = hsv.z * (T(1) - hsv.y * (T(1) - frac)); + + switch(int(sector)) + { + default: + case 0: + rgbColor.r = hsv.z; + rgbColor.g = q; + rgbColor.b = o; + break; + case 1: + rgbColor.r = p; + rgbColor.g = hsv.z; + rgbColor.b = o; + break; + case 2: + rgbColor.r = o; + rgbColor.g = hsv.z; + rgbColor.b = q; + break; + case 3: + rgbColor.r = o; + rgbColor.g = p; + rgbColor.b = hsv.z; + break; + case 4: + rgbColor.r = q; + rgbColor.g = o; + rgbColor.b = hsv.z; + break; + case 5: + rgbColor.r = hsv.z; + rgbColor.g = o; + rgbColor.b = p; + break; + } + } + + return rgbColor; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> hsvColor(const tvec3<T, P>& rgbColor) + { + tvec3<T, P> hsv = rgbColor; + float Min = min(min(rgbColor.r, rgbColor.g), rgbColor.b); + float Max = max(max(rgbColor.r, rgbColor.g), rgbColor.b); + float Delta = Max - Min; + + hsv.z = Max; + + if(Max != static_cast<T>(0)) + { + hsv.y = Delta / hsv.z; + T h = static_cast<T>(0); + + if(rgbColor.r == Max) + // between yellow & magenta + h = static_cast<T>(0) + T(60) * (rgbColor.g - rgbColor.b) / Delta; + else if(rgbColor.g == Max) + // between cyan & yellow + h = static_cast<T>(120) + T(60) * (rgbColor.b - rgbColor.r) / Delta; + else + // between magenta & cyan + h = static_cast<T>(240) + T(60) * (rgbColor.r - rgbColor.g) / Delta; + + if(h < T(0)) + hsv.x = h + T(360); + else + hsv.x = h; + } + else + { + // If r = g = b = 0 then s = 0, h is undefined + hsv.y = static_cast<T>(0); + hsv.x = static_cast<T>(0); + } + + return hsv; + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> saturation(T const s) + { + tvec3<T, defaultp> rgbw = tvec3<T, defaultp>(T(0.2126), T(0.7152), T(0.0722)); + + T col0 = (T(1) - s) * rgbw.r; + T col1 = (T(1) - s) * rgbw.g; + T col2 = (T(1) - s) * rgbw.b; + + tmat4x4<T, defaultp> result(T(1)); + result[0][0] = col0 + s; + result[0][1] = col0; + result[0][2] = col0; + result[1][0] = col1; + result[1][1] = col1 + s; + result[1][2] = col1; + result[2][0] = col2; + result[2][1] = col2; + result[2][2] = col2 + s; + return result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> saturation(const T s, const tvec3<T, P>& color) + { + return tvec3<T, P>(saturation(s) * tvec4<T, P>(color, T(0))); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> saturation(const T s, const tvec4<T, P>& color) + { + return saturation(s) * color; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T luminosity(const tvec3<T, P>& color) + { + const tvec3<T, P> tmp = tvec3<T, P>(0.33, 0.59, 0.11); + return dot(color, tmp); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/color_space_YCoCg.hpp b/extensions/common/glm/gtx/color_space_YCoCg.hpp new file mode 100644 index 0000000000..1cef4216dc --- /dev/null +++ b/extensions/common/glm/gtx/color_space_YCoCg.hpp @@ -0,0 +1,85 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_color_space_YCoCg +/// @file glm/gtx/color_space_YCoCg.hpp +/// @date 2008-10-28 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_color_space_YCoCg GLM_GTX_color_space_YCoCg +/// @ingroup gtx +/// +/// @brief RGB to YCoCg conversions and operations +/// +/// <glm/gtx/color_space_YCoCg.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_color_space_YCoCg extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_color_space_YCoCg + /// @{ + + /// Convert a color from RGB color space to YCoCg color space. + /// @see gtx_color_space_YCoCg + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> rgb2YCoCg( + tvec3<T, P> const & rgbColor); + + /// Convert a color from YCoCg color space to RGB color space. + /// @see gtx_color_space_YCoCg + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> YCoCg2rgb( + tvec3<T, P> const & YCoCgColor); + + /// Convert a color from RGB color space to YCoCgR color space. + /// @see "YCoCg-R: A Color Space with RGB Reversibility and Low Dynamic Range" + /// @see gtx_color_space_YCoCg + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> rgb2YCoCgR( + tvec3<T, P> const & rgbColor); + + /// Convert a color from YCoCgR color space to RGB color space. + /// @see "YCoCg-R: A Color Space with RGB Reversibility and Low Dynamic Range" + /// @see gtx_color_space_YCoCg + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> YCoCgR2rgb( + tvec3<T, P> const & YCoCgColor); + + /// @} +}//namespace glm + +#include "color_space_YCoCg.inl" diff --git a/extensions/common/glm/gtx/color_space_YCoCg.inl b/extensions/common/glm/gtx/color_space_YCoCg.inl new file mode 100644 index 0000000000..3688520e95 --- /dev/null +++ b/extensions/common/glm/gtx/color_space_YCoCg.inl @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_color_space_YCoCg +/// @file glm/gtx/color_space_YCoCg.inl +/// @date 2008-10-28 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> rgb2YCoCg + ( + tvec3<T, P> const & rgbColor + ) + { + tvec3<T, P> result; + result.x/*Y */ = rgbColor.r / T(4) + rgbColor.g / T(2) + rgbColor.b / T(4); + result.y/*Co*/ = rgbColor.r / T(2) + rgbColor.g * T(0) - rgbColor.b / T(2); + result.z/*Cg*/ = - rgbColor.r / T(4) + rgbColor.g / T(2) - rgbColor.b / T(4); + return result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> rgb2YCoCgR + ( + tvec3<T, P> const & rgbColor + ) + { + tvec3<T, P> result; + result.x/*Y */ = rgbColor.g / T(2) + (rgbColor.r + rgbColor.b) / T(4); + result.y/*Co*/ = rgbColor.r - rgbColor.b; + result.z/*Cg*/ = rgbColor.g - (rgbColor.r + rgbColor.b) / T(2); + return result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> YCoCg2rgb + ( + tvec3<T, P> const & YCoCgColor + ) + { + tvec3<T, P> result; + result.r = YCoCgColor.x + YCoCgColor.y - YCoCgColor.z; + result.g = YCoCgColor.x + YCoCgColor.z; + result.b = YCoCgColor.x - YCoCgColor.y - YCoCgColor.z; + return result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> YCoCgR2rgb + ( + tvec3<T, P> const & YCoCgRColor + ) + { + tvec3<T, P> result; + T tmp = YCoCgRColor.x - (YCoCgRColor.z / T(2)); + result.g = YCoCgRColor.z + tmp; + result.b = tmp - (YCoCgRColor.y / T(2)); + result.r = result.b + YCoCgRColor.y; + return result; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/common.hpp b/extensions/common/glm/gtx/common.hpp new file mode 100644 index 0000000000..8fb2215f25 --- /dev/null +++ b/extensions/common/glm/gtx/common.hpp @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_common +/// @file glm/gtx/common.hpp +/// @date 2014-09-08 / 2014-09-08 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// +/// @defgroup gtx_common GLM_GTX_common +/// @ingroup gtx +/// +/// @brief Provide functions to increase the compatibility with Cg and HLSL languages +/// +/// <glm/gtx/common.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies: +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../gtc/vec1.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_common extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_common + /// @{ + + /// Returns true if x is a denormalized number + /// Numbers whose absolute value is too small to be represented in the normal format are represented in an alternate, denormalized format. + /// This format is less precise but can represent values closer to zero. + /// + /// @tparam genType Floating-point scalar or vector types. + /// + /// @see <a href="http://www.opengl.org/sdk/docs/manglsl/xhtml/isnan.xml">GLSL isnan man page</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 8.3 Common Functions</a> + template <typename genType> + GLM_FUNC_DECL typename genType::bool_type isdenormal(genType const & x); + + /// @} +}//namespace glm + +#include "common.inl" diff --git a/extensions/common/glm/gtx/common.inl b/extensions/common/glm/gtx/common.inl new file mode 100644 index 0000000000..61a351ca72 --- /dev/null +++ b/extensions/common/glm/gtx/common.inl @@ -0,0 +1,102 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_common +/// @file glm/gtx/common.inl +/// @date 2014-09-08 / 2014-09-08 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include <cmath> + +namespace glm +{ + template <typename T> + GLM_FUNC_QUALIFIER bool isdenormal(T const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isdenormal' only accept floating-point inputs"); + +# if GLM_HAS_CXX11_STL + return std::fpclassify(x) == FP_SUBNORMAL; +# else + return x != static_cast<T>(0) && std::fabs(x) < std::numeric_limits<T>::min(); +# endif + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tvec1<T, P>::bool_type isdenormal + ( + tvec1<T, P> const & x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isdenormal' only accept floating-point inputs"); + + return typename tvec1<T, P>::bool_type( + isdenormal(x.x)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tvec2<T, P>::bool_type isdenormal + ( + tvec2<T, P> const & x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isdenormal' only accept floating-point inputs"); + + return typename tvec2<T, P>::bool_type( + isdenormal(x.x), + isdenormal(x.y)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tvec3<T, P>::bool_type isdenormal + ( + tvec3<T, P> const & x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isdenormal' only accept floating-point inputs"); + + return typename tvec3<T, P>::bool_type( + isdenormal(x.x), + isdenormal(x.y), + isdenormal(x.z)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tvec4<T, P>::bool_type isdenormal + ( + tvec4<T, P> const & x + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isdenormal' only accept floating-point inputs"); + + return typename tvec4<T, P>::bool_type( + isdenormal(x.x), + isdenormal(x.y), + isdenormal(x.z), + isdenormal(x.w)); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/compatibility.hpp b/extensions/common/glm/gtx/compatibility.hpp new file mode 100644 index 0000000000..eff9ac6458 --- /dev/null +++ b/extensions/common/glm/gtx/compatibility.hpp @@ -0,0 +1,158 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_compatibility +/// @file glm/gtx/compatibility.hpp +/// @date 2007-01-24 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// +/// @defgroup gtx_compatibility GLM_GTX_compatibility +/// @ingroup gtx +/// +/// @brief Provide functions to increase the compatibility with Cg and HLSL languages +/// +/// <glm/gtx/compatibility.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/quaternion.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_compatibility extension included") +#endif + +#if(GLM_COMPILER & GLM_COMPILER_VC) +# include <cfloat> +#elif(GLM_COMPILER & GLM_COMPILER_GCC) +# include <cmath> +# if(GLM_PLATFORM & GLM_PLATFORM_ANDROID) +# undef isfinite +# endif +#endif//GLM_COMPILER + +namespace glm +{ + /// @addtogroup gtx_compatibility + /// @{ + + template <typename T> GLM_FUNC_QUALIFIER T lerp(T x, T y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec2<T, P> lerp(const tvec2<T, P>& x, const tvec2<T, P>& y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec3<T, P> lerp(const tvec3<T, P>& x, const tvec3<T, P>& y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec4<T, P> lerp(const tvec4<T, P>& x, const tvec4<T, P>& y, T a){return mix(x, y, a);} //!< \brief Returns x * (1.0 - a) + y * a, i.e., the linear blend of x and y using the floating-point value a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec2<T, P> lerp(const tvec2<T, P>& x, const tvec2<T, P>& y, const tvec2<T, P>& a){return mix(x, y, a);} //!< \brief Returns the component-wise result of x * (1.0 - a) + y * a, i.e., the linear blend of x and y using vector a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec3<T, P> lerp(const tvec3<T, P>& x, const tvec3<T, P>& y, const tvec3<T, P>& a){return mix(x, y, a);} //!< \brief Returns the component-wise result of x * (1.0 - a) + y * a, i.e., the linear blend of x and y using vector a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec4<T, P> lerp(const tvec4<T, P>& x, const tvec4<T, P>& y, const tvec4<T, P>& a){return mix(x, y, a);} //!< \brief Returns the component-wise result of x * (1.0 - a) + y * a, i.e., the linear blend of x and y using vector a. The value for a is not restricted to the range [0, 1]. (From GLM_GTX_compatibility) + + template <typename T, precision P> GLM_FUNC_QUALIFIER T saturate(T x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec2<T, P> saturate(const tvec2<T, P>& x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec3<T, P> saturate(const tvec3<T, P>& x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec4<T, P> saturate(const tvec4<T, P>& x){return clamp(x, T(0), T(1));} //!< \brief Returns clamp(x, 0, 1) for each component in x. (From GLM_GTX_compatibility) + + template <typename T, precision P> GLM_FUNC_QUALIFIER T atan2(T x, T y){return atan(x, y);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec2<T, P> atan2(const tvec2<T, P>& x, const tvec2<T, P>& y){return atan(x, y);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec3<T, P> atan2(const tvec3<T, P>& x, const tvec3<T, P>& y){return atan(x, y);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_QUALIFIER tvec4<T, P> atan2(const tvec4<T, P>& x, const tvec4<T, P>& y){return atan(x, y);} //!< \brief Arc tangent. Returns an angle whose tangent is y/x. The signs of x and y are used to determine what quadrant the angle is in. The range of values returned by this function is [-PI, PI]. Results are undefined if x and y are both 0. (From GLM_GTX_compatibility) + + template <typename genType> GLM_FUNC_DECL bool isfinite(genType const & x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_DECL tvec2<bool, P> isfinite(const tvec2<T, P>& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_DECL tvec3<bool, P> isfinite(const tvec3<T, P>& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + template <typename T, precision P> GLM_FUNC_DECL tvec4<bool, P> isfinite(const tvec4<T, P>& x); //!< \brief Test whether or not a scalar or each vector component is a finite value. (From GLM_GTX_compatibility) + + typedef bool bool1; //!< \brief boolean type with 1 component. (From GLM_GTX_compatibility extension) + typedef tvec2<bool, highp> bool2; //!< \brief boolean type with 2 components. (From GLM_GTX_compatibility extension) + typedef tvec3<bool, highp> bool3; //!< \brief boolean type with 3 components. (From GLM_GTX_compatibility extension) + typedef tvec4<bool, highp> bool4; //!< \brief boolean type with 4 components. (From GLM_GTX_compatibility extension) + + typedef bool bool1x1; //!< \brief boolean matrix with 1 x 1 component. (From GLM_GTX_compatibility extension) + typedef tmat2x2<bool, highp> bool2x2; //!< \brief boolean matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat2x3<bool, highp> bool2x3; //!< \brief boolean matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat2x4<bool, highp> bool2x4; //!< \brief boolean matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef tmat3x2<bool, highp> bool3x2; //!< \brief boolean matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat3x3<bool, highp> bool3x3; //!< \brief boolean matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat3x4<bool, highp> bool3x4; //!< \brief boolean matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef tmat4x2<bool, highp> bool4x2; //!< \brief boolean matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat4x3<bool, highp> bool4x3; //!< \brief boolean matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat4x4<bool, highp> bool4x4; //!< \brief boolean matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + typedef int int1; //!< \brief integer vector with 1 component. (From GLM_GTX_compatibility extension) + typedef tvec2<int, highp> int2; //!< \brief integer vector with 2 components. (From GLM_GTX_compatibility extension) + typedef tvec3<int, highp> int3; //!< \brief integer vector with 3 components. (From GLM_GTX_compatibility extension) + typedef tvec4<int, highp> int4; //!< \brief integer vector with 4 components. (From GLM_GTX_compatibility extension) + + typedef int int1x1; //!< \brief integer matrix with 1 component. (From GLM_GTX_compatibility extension) + typedef tmat2x2<int, highp> int2x2; //!< \brief integer matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat2x3<int, highp> int2x3; //!< \brief integer matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat2x4<int, highp> int2x4; //!< \brief integer matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef tmat3x2<int, highp> int3x2; //!< \brief integer matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat3x3<int, highp> int3x3; //!< \brief integer matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat3x4<int, highp> int3x4; //!< \brief integer matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef tmat4x2<int, highp> int4x2; //!< \brief integer matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat4x3<int, highp> int4x3; //!< \brief integer matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat4x4<int, highp> int4x4; //!< \brief integer matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + typedef float float1; //!< \brief single-precision floating-point vector with 1 component. (From GLM_GTX_compatibility extension) + typedef tvec2<float, highp> float2; //!< \brief single-precision floating-point vector with 2 components. (From GLM_GTX_compatibility extension) + typedef tvec3<float, highp> float3; //!< \brief single-precision floating-point vector with 3 components. (From GLM_GTX_compatibility extension) + typedef tvec4<float, highp> float4; //!< \brief single-precision floating-point vector with 4 components. (From GLM_GTX_compatibility extension) + + typedef float float1x1; //!< \brief single-precision floating-point matrix with 1 component. (From GLM_GTX_compatibility extension) + typedef tmat2x2<float, highp> float2x2; //!< \brief single-precision floating-point matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat2x3<float, highp> float2x3; //!< \brief single-precision floating-point matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat2x4<float, highp> float2x4; //!< \brief single-precision floating-point matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef tmat3x2<float, highp> float3x2; //!< \brief single-precision floating-point matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat3x3<float, highp> float3x3; //!< \brief single-precision floating-point matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat3x4<float, highp> float3x4; //!< \brief single-precision floating-point matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef tmat4x2<float, highp> float4x2; //!< \brief single-precision floating-point matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat4x3<float, highp> float4x3; //!< \brief single-precision floating-point matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat4x4<float, highp> float4x4; //!< \brief single-precision floating-point matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + typedef double double1; //!< \brief double-precision floating-point vector with 1 component. (From GLM_GTX_compatibility extension) + typedef tvec2<double, highp> double2; //!< \brief double-precision floating-point vector with 2 components. (From GLM_GTX_compatibility extension) + typedef tvec3<double, highp> double3; //!< \brief double-precision floating-point vector with 3 components. (From GLM_GTX_compatibility extension) + typedef tvec4<double, highp> double4; //!< \brief double-precision floating-point vector with 4 components. (From GLM_GTX_compatibility extension) + + typedef double double1x1; //!< \brief double-precision floating-point matrix with 1 component. (From GLM_GTX_compatibility extension) + typedef tmat2x2<double, highp> double2x2; //!< \brief double-precision floating-point matrix with 2 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat2x3<double, highp> double2x3; //!< \brief double-precision floating-point matrix with 2 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat2x4<double, highp> double2x4; //!< \brief double-precision floating-point matrix with 2 x 4 components. (From GLM_GTX_compatibility extension) + typedef tmat3x2<double, highp> double3x2; //!< \brief double-precision floating-point matrix with 3 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat3x3<double, highp> double3x3; //!< \brief double-precision floating-point matrix with 3 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat3x4<double, highp> double3x4; //!< \brief double-precision floating-point matrix with 3 x 4 components. (From GLM_GTX_compatibility extension) + typedef tmat4x2<double, highp> double4x2; //!< \brief double-precision floating-point matrix with 4 x 2 components. (From GLM_GTX_compatibility extension) + typedef tmat4x3<double, highp> double4x3; //!< \brief double-precision floating-point matrix with 4 x 3 components. (From GLM_GTX_compatibility extension) + typedef tmat4x4<double, highp> double4x4; //!< \brief double-precision floating-point matrix with 4 x 4 components. (From GLM_GTX_compatibility extension) + + /// @} +}//namespace glm + +#include "compatibility.inl" diff --git a/extensions/common/glm/gtx/compatibility.inl b/extensions/common/glm/gtx/compatibility.inl new file mode 100644 index 0000000000..a125cbc304 --- /dev/null +++ b/extensions/common/glm/gtx/compatibility.inl @@ -0,0 +1,83 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_compatibility +/// @file glm/gtx/compatibility.inl +/// @date 2007-01-24 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include <limits> + +namespace glm +{ + // isfinite + template <typename genType> + GLM_FUNC_QUALIFIER bool isfinite( + genType const & x) + { +# if GLM_HAS_CXX11_STL + return std::isfinite(x) != 0; +# elif GLM_COMPILER & GLM_COMPILER_VC + return _finite(x); +# elif GLM_COMPILER & GLM_COMPILER_GCC && GLM_PLATFORM & GLM_PLATFORM_ANDROID + return _isfinite(x) != 0; +# else + return x >= std::numeric_limits<genType>::min() && x <= std::numeric_limits<genType>::max(); +# endif + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<bool, P> isfinite( + tvec2<T, P> const & x) + { + return tvec2<bool, P>( + isfinite(x.x), + isfinite(x.y)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<bool, P> isfinite( + tvec3<T, P> const & x) + { + return tvec3<bool, P>( + isfinite(x.x), + isfinite(x.y), + isfinite(x.z)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<bool, P> isfinite( + tvec4<T, P> const & x) + { + return tvec4<bool, P>( + isfinite(x.x), + isfinite(x.y), + isfinite(x.z), + isfinite(x.w)); + } + +}//namespace glm diff --git a/extensions/common/glm/gtx/component_wise.hpp b/extensions/common/glm/gtx/component_wise.hpp new file mode 100644 index 0000000000..e1f38d7e6a --- /dev/null +++ b/extensions/common/glm/gtx/component_wise.hpp @@ -0,0 +1,84 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_component_wise +/// @file glm/gtx/component_wise.hpp +/// @date 2007-05-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_component_wise GLM_GTX_component_wise +/// @ingroup gtx +/// +/// @brief Operations between components of a type +/// +/// <glm/gtx/component_wise.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/precision.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_component_wise extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_component_wise + /// @{ + + /// Add all vector components together. + /// @see gtx_component_wise + template <typename genType> + GLM_FUNC_DECL typename genType::value_type compAdd( + genType const & v); + + /// Multiply all vector components together. + /// @see gtx_component_wise + template <typename genType> + GLM_FUNC_DECL typename genType::value_type compMul( + genType const & v); + + /// Find the minimum value between single vector components. + /// @see gtx_component_wise + template <typename genType> + GLM_FUNC_DECL typename genType::value_type compMin( + genType const & v); + + /// Find the maximum value between single vector components. + /// @see gtx_component_wise + template <typename genType> + GLM_FUNC_DECL typename genType::value_type compMax( + genType const & v); + + /// @} +}//namespace glm + +#include "component_wise.inl" diff --git a/extensions/common/glm/gtx/component_wise.inl b/extensions/common/glm/gtx/component_wise.inl new file mode 100644 index 0000000000..32569d4376 --- /dev/null +++ b/extensions/common/glm/gtx/component_wise.inl @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_component_wise +/// @file glm/gtx/component_wise.inl +/// @date 2007-05-21 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T compAdd(vecType<T, P> const & v) + { + T result(0); + for(detail::component_count_t i = 0; i < detail::component_count(v); ++i) + result += v[i]; + return result; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T compMul(vecType<T, P> const & v) + { + T result(1); + for(detail::component_count_t i = 0; i < detail::component_count(v); ++i) + result *= v[i]; + return result; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T compMin(vecType<T, P> const & v) + { + T result(v[0]); + for(detail::component_count_t i = 1; i < detail::component_count(v); ++i) + result = min(result, v[i]); + return result; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T compMax(vecType<T, P> const & v) + { + T result(v[0]); + for(detail::component_count_t i = 1; i < detail::component_count(v); ++i) + result = max(result, v[i]); + return result; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/dual_quaternion.hpp b/extensions/common/glm/gtx/dual_quaternion.hpp new file mode 100644 index 0000000000..39447bb17e --- /dev/null +++ b/extensions/common/glm/gtx/dual_quaternion.hpp @@ -0,0 +1,321 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_dual_quaternion +/// @file glm/gtx/dual_quaternion.hpp +/// @date 2013-02-10 / 2013-02-20 +/// @author Maksim Vorobiev (msomeone@gmail.com) +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// @see gtc_constants (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_dual_quaternion GLM_GTX_dual_quaternion +/// @ingroup gtx +/// +/// @brief Defines a templated dual-quaternion type and several dual-quaternion operations. +/// +/// <glm/gtx/dual_quaternion.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/constants.hpp" +#include "../gtc/quaternion.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_dual_quaternion extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_dual_quaternion + /// @{ + + template <typename T, precision P> + struct tdualquat + { + typedef T value_type; + typedef glm::tquat<T, P> part_type; + + public: + glm::tquat<T, P> real, dual; + + ////////////////////////////////////// + // Component accesses + +# ifdef GLM_FORCE_SIZE_FUNC + typedef size_t size_type; + /// Return the count of components of a dual quaternion + GLM_FUNC_DECL GLM_CONSTEXPR size_type size() const; + + GLM_FUNC_DECL part_type & operator[](size_type i); + GLM_FUNC_DECL part_type const & operator[](size_type i) const; +# else + typedef length_t length_type; + /// Return the count of components of a dual quaternion + GLM_FUNC_DECL GLM_CONSTEXPR length_type length() const; + + GLM_FUNC_DECL part_type & operator[](length_type i); + GLM_FUNC_DECL part_type const & operator[](length_type i) const; +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Implicit basic constructors + + GLM_FUNC_DECL tdualquat(); + GLM_FUNC_DECL tdualquat(tdualquat<T, P> const & d); + template <precision Q> + GLM_FUNC_DECL tdualquat(tdualquat<T, Q> const & d); + + ////////////////////////////////////// + // Explicit basic constructors + + GLM_FUNC_DECL explicit tdualquat(ctor); + GLM_FUNC_DECL explicit tdualquat(tquat<T, P> const & real); + GLM_FUNC_DECL tdualquat(tquat<T, P> const & orientation, tvec3<T, P> const & translation); + GLM_FUNC_DECL tdualquat(tquat<T, P> const & real, tquat<T, P> const & dual); + + ////////////////////////////////////////////////////////////// + // tdualquat conversions + +# ifdef GLM_FORCE_EXPLICIT_CTOR + template <typename U, precision Q> + GLM_FUNC_DECL explicit tdualquat(tdualquat<U, Q> const & q); +# else + template <typename U, precision Q> + GLM_FUNC_DECL tdualquat(tdualquat<U, Q> const & q); +# endif + + GLM_FUNC_DECL explicit tdualquat(tmat2x4<T, P> const & holder_mat); + GLM_FUNC_DECL explicit tdualquat(tmat3x4<T, P> const & aug_mat); + + // Operators + GLM_FUNC_DECL tdualquat<T, P> & operator=(tdualquat<T, P> const & m); + + template <typename U> + GLM_FUNC_DECL tdualquat<T, P> & operator=(tdualquat<U, P> const & m); + template <typename U> + GLM_FUNC_DECL tdualquat<T, P> & operator*=(U s); + template <typename U> + GLM_FUNC_DECL tdualquat<T, P> & operator/=(U s); + }; + + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> operator- ( + tquat<T, P> const & q); + + template <typename T, precision P> + GLM_FUNC_DECL tdualquat<T, P> operator+ ( + tdualquat<T, P> const & q, + tdualquat<T, P> const & p); + + template <typename T, precision P> + GLM_FUNC_DECL tdualquat<T, P> operator* ( + tdualquat<T, P> const & q, + tdualquat<T, P> const & p); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator* ( + tquat<T, P> const & q, + tvec3<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> operator* ( + tvec3<T, P> const & v, + tquat<T, P> const & q); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator* ( + tquat<T, P> const & q, + tvec4<T, P> const & v); + + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> operator* ( + tvec4<T, P> const & v, + tquat<T, P> const & q); + + template <typename T, precision P> + GLM_FUNC_DECL tdualquat<T, P> operator* ( + tdualquat<T, P> const & q, + T const & s); + + template <typename T, precision P> + GLM_FUNC_DECL tdualquat<T, P> operator* ( + T const & s, + tdualquat<T, P> const & q); + + template <typename T, precision P> + GLM_FUNC_DECL tdualquat<T, P> operator/ ( + tdualquat<T, P> const & q, + T const & s); + + /// Returns the normalized quaternion. + /// + /// @see gtx_dual_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tdualquat<T, P> normalize( + tdualquat<T, P> const & q); + + /// Returns the linear interpolation of two dual quaternion. + /// + /// @see gtc_dual_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tdualquat<T, P> lerp( + tdualquat<T, P> const & x, + tdualquat<T, P> const & y, + T const & a); + + /// Returns the q inverse. + /// + /// @see gtx_dual_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tdualquat<T, P> inverse( + tdualquat<T, P> const & q); + + /// Converts a quaternion to a 2 * 4 matrix. + /// + /// @see gtx_dual_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> mat2x4_cast( + tdualquat<T, P> const & x); + + /// Converts a quaternion to a 3 * 4 matrix. + /// + /// @see gtx_dual_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> mat3x4_cast( + tdualquat<T, P> const & x); + + /// Converts a 2 * 4 matrix (matrix which holds real and dual parts) to a quaternion. + /// + /// @see gtx_dual_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tdualquat<T, P> dualquat_cast( + tmat2x4<T, P> const & x); + + /// Converts a 3 * 4 matrix (augmented matrix rotation + translation) to a quaternion. + /// + /// @see gtx_dual_quaternion + template <typename T, precision P> + GLM_FUNC_DECL tdualquat<T, P> dualquat_cast( + tmat3x4<T, P> const & x); + + + /// Dual-quaternion of low single-precision floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, lowp> lowp_dualquat; + + /// Dual-quaternion of medium single-precision floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, mediump> mediump_dualquat; + + /// Dual-quaternion of high single-precision floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, highp> highp_dualquat; + + + /// Dual-quaternion of low single-precision floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, lowp> lowp_fdualquat; + + /// Dual-quaternion of medium single-precision floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, mediump> mediump_fdualquat; + + /// Dual-quaternion of high single-precision floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<float, highp> highp_fdualquat; + + + /// Dual-quaternion of low double-precision floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<double, lowp> lowp_ddualquat; + + /// Dual-quaternion of medium double-precision floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<double, mediump> mediump_ddualquat; + + /// Dual-quaternion of high double-precision floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef tdualquat<double, highp> highp_ddualquat; + + +#if(!defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + /// Dual-quaternion of floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef highp_fdualquat dualquat; + + /// Dual-quaternion of single-precision floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef highp_fdualquat fdualquat; +#elif(defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + typedef highp_fdualquat dualquat; + typedef highp_fdualquat fdualquat; +#elif(!defined(GLM_PRECISION_HIGHP_FLOAT) && defined(GLM_PRECISION_MEDIUMP_FLOAT) && !defined(GLM_PRECISION_LOWP_FLOAT)) + typedef mediump_fdualquat dualquat; + typedef mediump_fdualquat fdualquat; +#elif(!defined(GLM_PRECISION_HIGHP_FLOAT) && !defined(GLM_PRECISION_MEDIUMP_FLOAT) && defined(GLM_PRECISION_LOWP_FLOAT)) + typedef lowp_fdualquat dualquat; + typedef lowp_fdualquat fdualquat; +#else +# error "GLM error: multiple default precision requested for single-precision floating-point types" +#endif + + +#if(!defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + /// Dual-quaternion of default double-precision floating-point numbers. + /// + /// @see gtx_dual_quaternion + typedef highp_ddualquat ddualquat; +#elif(defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef highp_ddualquat ddualquat; +#elif(!defined(GLM_PRECISION_HIGHP_DOUBLE) && defined(GLM_PRECISION_MEDIUMP_DOUBLE) && !defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef mediump_ddualquat ddualquat; +#elif(!defined(GLM_PRECISION_HIGHP_DOUBLE) && !defined(GLM_PRECISION_MEDIUMP_DOUBLE) && defined(GLM_PRECISION_LOWP_DOUBLE)) + typedef lowp_ddualquat ddualquat; +#else +# error "GLM error: Multiple default precision requested for double-precision floating-point types" +#endif + + /// @} +} //namespace glm + +#include "dual_quaternion.inl" diff --git a/extensions/common/glm/gtx/dual_quaternion.inl b/extensions/common/glm/gtx/dual_quaternion.inl new file mode 100644 index 0000000000..49e364dddb --- /dev/null +++ b/extensions/common/glm/gtx/dual_quaternion.inl @@ -0,0 +1,400 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_dual_quaternion +/// @file glm/gtx/dual_quaternion.inl +/// @date 2013-02-10 / 2013-02-13 +/// @author Maksim Vorobiev (msomeone@gmail.com) +/////////////////////////////////////////////////////////////////////////////////// + +#include "../geometric.hpp" +#include <limits> + +namespace glm +{ + ////////////////////////////////////// + // Component accesses + +# ifdef GLM_FORCE_SIZE_FUNC + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tdualquat<T, P>::size_type tdualquat<T, P>::size() const + { + return 2; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tdualquat<T, P>::part_type & tdualquat<T, P>::operator[](typename tdualquat<T, P>::size_type i) + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&real)[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tdualquat<T, P>::part_type const & tdualquat<T, P>::operator[](typename tdualquat<T, P>::size_type i) const + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&real)[i]; + } +# else + template <typename T, precision P> + GLM_FUNC_QUALIFIER GLM_CONSTEXPR typename tdualquat<T, P>::length_type tdualquat<T, P>::length() const + { + return 2; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tdualquat<T, P>::part_type & tdualquat<T, P>::operator[](typename tdualquat<T, P>::length_type i) + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&real)[i]; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER typename tdualquat<T, P>::part_type const & tdualquat<T, P>::operator[](typename tdualquat<T, P>::length_type i) const + { + assert(i >= 0 && static_cast<detail::component_count_t>(i) < detail::component_count(*this)); + return (&real)[i]; + } +# endif//GLM_FORCE_SIZE_FUNC + + ////////////////////////////////////// + // Implicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat() +# ifndef GLM_FORCE_NO_CTOR_INIT + : real(tquat<T, P>()) + , dual(tquat<T, P>(0, 0, 0, 0)) +# endif + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat(tdualquat<T, P> const & d) + : real(d.real) + , dual(d.dual) + {} + + template <typename T, precision P> + template <precision Q> + GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat(tdualquat<T, Q> const & d) + : real(d.real) + , dual(d.dual) + {} + + ////////////////////////////////////// + // Explicit basic constructors + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat(ctor) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat(tquat<T, P> const & r) + : real(r), dual(tquat<T, P>(0, 0, 0, 0)) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat(tquat<T, P> const & q, tvec3<T, P> const& p) + : real(q), dual( + T(-0.5) * ( p.x*q.x + p.y*q.y + p.z*q.z), + T(+0.5) * ( p.x*q.w + p.y*q.z - p.z*q.y), + T(+0.5) * (-p.x*q.z + p.y*q.w + p.z*q.x), + T(+0.5) * ( p.x*q.y - p.y*q.x + p.z*q.w)) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat(tquat<T, P> const & r, tquat<T, P> const & d) + : real(r), dual(d) + {} + + ////////////////////////////////////////////////////////////// + // tdualquat conversions + + template <typename T, precision P> + template <typename U, precision Q> + GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat(tdualquat<U, Q> const & q) + : real(q.real) + , dual(q.dual) + {} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat(tmat2x4<T, P> const & m) + { + *this = dualquat_cast(m); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P>::tdualquat(tmat3x4<T, P> const & m) + { + *this = dualquat_cast(m); + } + + ////////////////////////////////////////////////////////////// + // tdualquat operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> & tdualquat<T, P>::operator=(tdualquat<T, P> const & q) + { + this->real = q.real; + this->dual = q.dual; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tdualquat<T, P> & tdualquat<T, P>::operator=(tdualquat<U, P> const & q) + { + this->real = q.real; + this->dual = q.dual; + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tdualquat<T, P> & tdualquat<T, P>::operator*=(U s) + { + this->real *= static_cast<T>(s); + this->dual *= static_cast<T>(s); + return *this; + } + + template <typename T, precision P> + template <typename U> + GLM_FUNC_QUALIFIER tdualquat<T, P> & tdualquat<T, P>::operator/=(U s) + { + this->real /= static_cast<T>(s); + this->dual /= static_cast<T>(s); + return *this; + } + + ////////////////////////////////////////////////////////////// + // tquat<valType> external operators + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> operator-(tdualquat<T, P> const & q) + { + return tdualquat<T, P>(-q.real,-q.dual); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> operator+(tdualquat<T, P> const & q, tdualquat<T, P> const & p) + { + return tdualquat<T, P>(q.real + p.real,q.dual + p.dual); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> operator*(tdualquat<T, P> const & p, tdualquat<T, P> const & o) + { + return tdualquat<T, P>(p.real * o.real,p.real * o.dual + p.dual * o.real); + } + + // Transformation + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator*(tdualquat<T, P> const & q, tvec3<T, P> const & v) + { + tvec3<T, P> const real_v3(q.real.x,q.real.y,q.real.z); + tvec3<T, P> const dual_v3(q.dual.x,q.dual.y,q.dual.z); + return (cross(real_v3, cross(real_v3,v) + v * q.real.w + dual_v3) + dual_v3 * q.real.w - real_v3 * q.dual.w) * T(2) + v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> operator*(tvec3<T, P> const & v, tdualquat<T, P> const & q) + { + return glm::inverse(q) * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator*(tdualquat<T, P> const & q, tvec4<T, P> const & v) + { + return tvec4<T, P>(q * tvec3<T, P>(v), v.w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> operator*(tvec4<T, P> const & v, tdualquat<T, P> const & q) + { + return glm::inverse(q) * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> operator*(tdualquat<T, P> const & q, T const & s) + { + return tdualquat<T, P>(q.real * s, q.dual * s); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> operator*(T const & s, tdualquat<T, P> const & q) + { + return q * s; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> operator/(tdualquat<T, P> const & q, T const & s) + { + return tdualquat<T, P>(q.real / s, q.dual / s); + } + + ////////////////////////////////////// + // Boolean operators + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator==(tdualquat<T, P> const & q1, tdualquat<T, P> const & q2) + { + return (q1.real == q2.real) && (q1.dual == q2.dual); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool operator!=(tdualquat<T, P> const & q1, tdualquat<T, P> const & q2) + { + return (q1.real != q2.dual) || (q1.real != q2.dual); + } + + //////////////////////////////////////////////////////// + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> normalize(tdualquat<T, P> const & q) + { + return q / length(q.real); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> lerp(tdualquat<T, P> const & x, tdualquat<T, P> const & y, T const & a) + { + // Dual Quaternion Linear blend aka DLB: + // Lerp is only defined in [0, 1] + assert(a >= static_cast<T>(0)); + assert(a <= static_cast<T>(1)); + T const k = dot(x.real,y.real) < static_cast<T>(0) ? -a : a; + T const one(1); + return tdualquat<T, P>(x * (one - a) + y * k); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> inverse(tdualquat<T, P> const & q) + { + const glm::tquat<T, P> real = conjugate(q.real); + const glm::tquat<T, P> dual = conjugate(q.dual); + return tdualquat<T, P>(real, dual + (real * (-2.0f * dot(real,dual)))); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> mat2x4_cast(tdualquat<T, P> const & x) + { + return tmat2x4<T, P>( x[0].x, x[0].y, x[0].z, x[0].w, x[1].x, x[1].y, x[1].z, x[1].w ); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> mat3x4_cast(tdualquat<T, P> const & x) + { + tquat<T, P> r = x.real / length2(x.real); + + tquat<T, P> const rr(r.w * x.real.w, r.x * x.real.x, r.y * x.real.y, r.z * x.real.z); + r *= static_cast<T>(2); + + T const xy = r.x * x.real.y; + T const xz = r.x * x.real.z; + T const yz = r.y * x.real.z; + T const wx = r.w * x.real.x; + T const wy = r.w * x.real.y; + T const wz = r.w * x.real.z; + + tvec4<T, P> const a( + rr.w + rr.x - rr.y - rr.z, + xy - wz, + xz + wy, + -(x.dual.w * r.x - x.dual.x * r.w + x.dual.y * r.z - x.dual.z * r.y)); + + tvec4<T, P> const b( + xy + wz, + rr.w + rr.y - rr.x - rr.z, + yz - wx, + -(x.dual.w * r.y - x.dual.x * r.z - x.dual.y * r.w + x.dual.z * r.x)); + + tvec4<T, P> const c( + xz - wy, + yz + wx, + rr.w + rr.z - rr.x - rr.y, + -(x.dual.w * r.z + x.dual.x * r.y - x.dual.y * r.x - x.dual.z * r.w)); + + return tmat3x4<T, P>(a, b, c); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> dualquat_cast(tmat2x4<T, P> const & x) + { + return tdualquat<T, P>( + tquat<T, P>( x[0].w, x[0].x, x[0].y, x[0].z ), + tquat<T, P>( x[1].w, x[1].x, x[1].y, x[1].z )); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tdualquat<T, P> dualquat_cast(tmat3x4<T, P> const & x) + { + tquat<T, P> real(uninitialize); + + T const trace = x[0].x + x[1].y + x[2].z; + if(trace > static_cast<T>(0)) + { + T const r = sqrt(T(1) + trace); + T const invr = static_cast<T>(0.5) / r; + real.w = static_cast<T>(0.5) * r; + real.x = (x[2].y - x[1].z) * invr; + real.y = (x[0].z - x[2].x) * invr; + real.z = (x[1].x - x[0].y) * invr; + } + else if(x[0].x > x[1].y && x[0].x > x[2].z) + { + T const r = sqrt(T(1) + x[0].x - x[1].y - x[2].z); + T const invr = static_cast<T>(0.5) / r; + real.x = static_cast<T>(0.5)*r; + real.y = (x[1].x + x[0].y) * invr; + real.z = (x[0].z + x[2].x) * invr; + real.w = (x[2].y - x[1].z) * invr; + } + else if(x[1].y > x[2].z) + { + T const r = sqrt(T(1) + x[1].y - x[0].x - x[2].z); + T const invr = static_cast<T>(0.5) / r; + real.x = (x[1].x + x[0].y) * invr; + real.y = static_cast<T>(0.5) * r; + real.z = (x[2].y + x[1].z) * invr; + real.w = (x[0].z - x[2].x) * invr; + } + else + { + T const r = sqrt(T(1) + x[2].z - x[0].x - x[1].y); + T const invr = static_cast<T>(0.5) / r; + real.x = (x[0].z + x[2].x) * invr; + real.y = (x[2].y + x[1].z) * invr; + real.z = static_cast<T>(0.5) * r; + real.w = (x[1].x - x[0].y) * invr; + } + + tquat<T, P> dual(uninitialize); + dual.x = static_cast<T>(0.5) * ( x[0].w * real.w + x[1].w * real.z - x[2].w * real.y); + dual.y = static_cast<T>(0.5) * (-x[0].w * real.z + x[1].w * real.w + x[2].w * real.x); + dual.z = static_cast<T>(0.5) * ( x[0].w * real.y - x[1].w * real.x + x[2].w * real.w); + dual.w = -static_cast<T>(0.5) * ( x[0].w * real.x + x[1].w * real.y + x[2].w * real.z); + return tdualquat<T, P>(real, dual); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/euler_angles.hpp b/extensions/common/glm/gtx/euler_angles.hpp new file mode 100644 index 0000000000..f5b6e27707 --- /dev/null +++ b/extensions/common/glm/gtx/euler_angles.hpp @@ -0,0 +1,156 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_euler_angles +/// @file glm/gtx/euler_angles.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// +/// @defgroup gtx_euler_angles GLM_GTX_euler_angles +/// @ingroup gtx +/// +/// @brief Build matrices from Euler angles. +/// +/// <glm/gtx/euler_angles.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_euler_angles extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_euler_angles + /// @{ + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from an euler angle X. + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> eulerAngleX( + T const & angleX); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from an euler angle Y. + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> eulerAngleY( + T const & angleY); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from an euler angle Z. + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> eulerAngleZ( + T const & angleZ); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Y). + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> eulerAngleXY( + T const & angleX, + T const & angleY); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X). + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> eulerAngleYX( + T const & angleY, + T const & angleX); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (X * Z). + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> eulerAngleXZ( + T const & angleX, + T const & angleZ); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * X). + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> eulerAngleZX( + T const & angle, + T const & angleX); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * Z). + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> eulerAngleYZ( + T const & angleY, + T const & angleZ); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Z * Y). + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> eulerAngleZY( + T const & angleZ, + T const & angleY); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> eulerAngleYXZ( + T const & yaw, + T const & pitch, + T const & roll); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat4x4<T, defaultp> yawPitchRoll( + T const & yaw, + T const & pitch, + T const & roll); + + /// Creates a 2D 2 * 2 rotation matrix from an euler angle. + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat2x2<T, defaultp> orientate2(T const & angle); + + /// Creates a 2D 4 * 4 homogeneous rotation matrix from an euler angle. + /// @see gtx_euler_angles + template <typename T> + GLM_FUNC_DECL tmat3x3<T, defaultp> orientate3(T const & angle); + + /// Creates a 3D 3 * 3 rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> orientate3(tvec3<T, P> const & angles); + + /// Creates a 3D 4 * 4 homogeneous rotation matrix from euler angles (Y * X * Z). + /// @see gtx_euler_angles + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> orientate4(tvec3<T, P> const & angles); + + /// @} +}//namespace glm + +#include "euler_angles.inl" diff --git a/extensions/common/glm/gtx/euler_angles.inl b/extensions/common/glm/gtx/euler_angles.inl new file mode 100644 index 0000000000..41f44ad98d --- /dev/null +++ b/extensions/common/glm/gtx/euler_angles.inl @@ -0,0 +1,287 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_euler_angles +/// @file glm/gtx/euler_angles.inl +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> eulerAngleX + ( + T const & angleX + ) + { + T cosX = glm::cos(angleX); + T sinX = glm::sin(angleX); + + return tmat4x4<T, defaultp>( + T(1), T(0), T(0), T(0), + T(0), cosX, sinX, T(0), + T(0),-sinX, cosX, T(0), + T(0), T(0), T(0), T(1)); + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> eulerAngleY + ( + T const & angleY + ) + { + T cosY = glm::cos(angleY); + T sinY = glm::sin(angleY); + + return tmat4x4<T, defaultp>( + cosY, T(0), -sinY, T(0), + T(0), T(1), T(0), T(0), + sinY, T(0), cosY, T(0), + T(0), T(0), T(0), T(1)); + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> eulerAngleZ + ( + T const & angleZ + ) + { + T cosZ = glm::cos(angleZ); + T sinZ = glm::sin(angleZ); + + return tmat4x4<T, defaultp>( + cosZ, sinZ, T(0), T(0), + -sinZ, cosZ, T(0), T(0), + T(0), T(0), T(1), T(0), + T(0), T(0), T(0), T(1)); + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> eulerAngleXY + ( + T const & angleX, + T const & angleY + ) + { + T cosX = glm::cos(angleX); + T sinX = glm::sin(angleX); + T cosY = glm::cos(angleY); + T sinY = glm::sin(angleY); + + return tmat4x4<T, defaultp>( + cosY, -sinX * -sinY, cosX * -sinY, T(0), + T(0), cosX, sinX, T(0), + sinY, -sinX * cosY, cosX * cosY, T(0), + T(0), T(0), T(0), T(1)); + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> eulerAngleYX + ( + T const & angleY, + T const & angleX + ) + { + T cosX = glm::cos(angleX); + T sinX = glm::sin(angleX); + T cosY = glm::cos(angleY); + T sinY = glm::sin(angleY); + + return tmat4x4<T, defaultp>( + cosY, 0, -sinY, T(0), + sinY * sinX, cosX, cosY * sinX, T(0), + sinY * cosX, -sinX, cosY * cosX, T(0), + T(0), T(0), T(0), T(1)); + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> eulerAngleXZ + ( + T const & angleX, + T const & angleZ + ) + { + return eulerAngleX(angleX) * eulerAngleZ(angleZ); + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> eulerAngleZX + ( + T const & angleZ, + T const & angleX + ) + { + return eulerAngleZ(angleZ) * eulerAngleX(angleX); + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> eulerAngleYZ + ( + T const & angleY, + T const & angleZ + ) + { + return eulerAngleY(angleY) * eulerAngleZ(angleZ); + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> eulerAngleZY + ( + T const & angleZ, + T const & angleY + ) + { + return eulerAngleZ(angleZ) * eulerAngleY(angleY); + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> eulerAngleYXZ + ( + T const & yaw, + T const & pitch, + T const & roll + ) + { + T tmp_ch = glm::cos(yaw); + T tmp_sh = glm::sin(yaw); + T tmp_cp = glm::cos(pitch); + T tmp_sp = glm::sin(pitch); + T tmp_cb = glm::cos(roll); + T tmp_sb = glm::sin(roll); + + tmat4x4<T, defaultp> Result; + Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb; + Result[0][1] = tmp_sb * tmp_cp; + Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb; + Result[0][3] = static_cast<T>(0); + Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb; + Result[1][1] = tmp_cb * tmp_cp; + Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb; + Result[1][3] = static_cast<T>(0); + Result[2][0] = tmp_sh * tmp_cp; + Result[2][1] = -tmp_sp; + Result[2][2] = tmp_ch * tmp_cp; + Result[2][3] = static_cast<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat4x4<T, defaultp> yawPitchRoll + ( + T const & yaw, + T const & pitch, + T const & roll + ) + { + T tmp_ch = glm::cos(yaw); + T tmp_sh = glm::sin(yaw); + T tmp_cp = glm::cos(pitch); + T tmp_sp = glm::sin(pitch); + T tmp_cb = glm::cos(roll); + T tmp_sb = glm::sin(roll); + + tmat4x4<T, defaultp> Result; + Result[0][0] = tmp_ch * tmp_cb + tmp_sh * tmp_sp * tmp_sb; + Result[0][1] = tmp_sb * tmp_cp; + Result[0][2] = -tmp_sh * tmp_cb + tmp_ch * tmp_sp * tmp_sb; + Result[0][3] = static_cast<T>(0); + Result[1][0] = -tmp_ch * tmp_sb + tmp_sh * tmp_sp * tmp_cb; + Result[1][1] = tmp_cb * tmp_cp; + Result[1][2] = tmp_sb * tmp_sh + tmp_ch * tmp_sp * tmp_cb; + Result[1][3] = static_cast<T>(0); + Result[2][0] = tmp_sh * tmp_cp; + Result[2][1] = -tmp_sp; + Result[2][2] = tmp_ch * tmp_cp; + Result[2][3] = static_cast<T>(0); + Result[3][0] = static_cast<T>(0); + Result[3][1] = static_cast<T>(0); + Result[3][2] = static_cast<T>(0); + Result[3][3] = static_cast<T>(1); + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat2x2<T, defaultp> orientate2 + ( + T const & angle + ) + { + T c = glm::cos(angle); + T s = glm::sin(angle); + + tmat2x2<T, defaultp> Result; + Result[0][0] = c; + Result[0][1] = s; + Result[1][0] = -s; + Result[1][1] = c; + return Result; + } + + template <typename T> + GLM_FUNC_QUALIFIER tmat3x3<T, defaultp> orientate3 + ( + T const & angle + ) + { + T c = glm::cos(angle); + T s = glm::sin(angle); + + tmat3x3<T, defaultp> Result; + Result[0][0] = c; + Result[0][1] = s; + Result[0][2] = 0.0f; + Result[1][0] = -s; + Result[1][1] = c; + Result[1][2] = 0.0f; + Result[2][0] = 0.0f; + Result[2][1] = 0.0f; + Result[2][2] = 1.0f; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> orientate3 + ( + tvec3<T, P> const & angles + ) + { + return tmat3x3<T, P>(yawPitchRoll(angles.z, angles.x, angles.y)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> orientate4 + ( + tvec3<T, P> const & angles + ) + { + return yawPitchRoll(angles.z, angles.x, angles.y); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/extend.hpp b/extensions/common/glm/gtx/extend.hpp new file mode 100644 index 0000000000..30ff31078e --- /dev/null +++ b/extensions/common/glm/gtx/extend.hpp @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_extend +/// @file glm/gtx/extend.hpp +/// @date 2006-01-07 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_extend GLM_GTX_extend +/// @ingroup gtx +/// +/// @brief Extend a position from a source to a position at a defined length. +/// +/// <glm/gtx/extend.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_extend extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_extend + /// @{ + + /// Extends of Length the Origin position using the (Source - Origin) direction. + /// @see gtx_extend + template <typename genType> + GLM_FUNC_DECL genType extend( + genType const & Origin, + genType const & Source, + typename genType::value_type const Length); + + /// @} +}//namespace glm + +#include "extend.inl" diff --git a/extensions/common/glm/gtx/extend.inl b/extensions/common/glm/gtx/extend.inl new file mode 100644 index 0000000000..e127212268 --- /dev/null +++ b/extensions/common/glm/gtx/extend.inl @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_extend +/// @file glm/gtx/extend.inl +/// @date 2006-01-07 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename genType> + GLM_FUNC_QUALIFIER genType extend + ( + genType const & Origin, + genType const & Source, + genType const & Distance + ) + { + return Origin + (Source - Origin) * Distance; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> extend + ( + tvec2<T, P> const & Origin, + tvec2<T, P> const & Source, + T const & Distance + ) + { + return Origin + (Source - Origin) * Distance; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> extend + ( + tvec3<T, P> const & Origin, + tvec3<T, P> const & Source, + T const & Distance + ) + { + return Origin + (Source - Origin) * Distance; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> extend + ( + tvec4<T, P> const & Origin, + tvec4<T, P> const & Source, + T const & Distance + ) + { + return Origin + (Source - Origin) * Distance; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/extented_min_max.hpp b/extensions/common/glm/gtx/extented_min_max.hpp new file mode 100644 index 0000000000..67e2dc02fd --- /dev/null +++ b/extensions/common/glm/gtx/extented_min_max.hpp @@ -0,0 +1,162 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_extented_min_max +/// @file glm/gtx/extented_min_max.hpp +/// @date 2007-03-14 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_half_float (dependence) +/// +/// @defgroup gtx_extented_min_max GLM_GTX_extented_min_max +/// @ingroup gtx +/// +/// Min and max functions for 3 to 4 parameters. +/// +/// <glm/gtx/extented_min_max.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_extented_min_max extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_extented_min_max + /// @{ + + /// Return the minimum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template <typename T> + GLM_FUNC_DECL T min( + T const & x, + T const & y, + T const & z); + + /// Return the minimum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template <typename T, template <typename> class C> + GLM_FUNC_DECL C<T> min( + C<T> const & x, + typename C<T>::T const & y, + typename C<T>::T const & z); + + /// Return the minimum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template <typename T, template <typename> class C> + GLM_FUNC_DECL C<T> min( + C<T> const & x, + C<T> const & y, + C<T> const & z); + + /// Return the minimum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template <typename T> + GLM_FUNC_DECL T min( + T const & x, + T const & y, + T const & z, + T const & w); + + /// Return the minimum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template <typename T, template <typename> class C> + GLM_FUNC_DECL C<T> min( + C<T> const & x, + typename C<T>::T const & y, + typename C<T>::T const & z, + typename C<T>::T const & w); + + /// Return the minimum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template <typename T, template <typename> class C> + GLM_FUNC_DECL C<T> min( + C<T> const & x, + C<T> const & y, + C<T> const & z, + C<T> const & w); + + /// Return the maximum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template <typename T> + GLM_FUNC_DECL T max( + T const & x, + T const & y, + T const & z); + + /// Return the maximum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template <typename T, template <typename> class C> + GLM_FUNC_DECL C<T> max( + C<T> const & x, + typename C<T>::T const & y, + typename C<T>::T const & z); + + /// Return the maximum component-wise values of 3 inputs + /// @see gtx_extented_min_max + template <typename T, template <typename> class C> + GLM_FUNC_DECL C<T> max( + C<T> const & x, + C<T> const & y, + C<T> const & z); + + /// Return the maximum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template <typename T> + GLM_FUNC_DECL T max( + T const & x, + T const & y, + T const & z, + T const & w); + + /// Return the maximum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template <typename T, template <typename> class C> + GLM_FUNC_DECL C<T> max( + C<T> const & x, + typename C<T>::T const & y, + typename C<T>::T const & z, + typename C<T>::T const & w); + + /// Return the maximum component-wise values of 4 inputs + /// @see gtx_extented_min_max + template <typename T, template <typename> class C> + GLM_FUNC_DECL C<T> max( + C<T> const & x, + C<T> const & y, + C<T> const & z, + C<T> const & w); + + /// @} +}//namespace glm + +#include "extented_min_max.inl" diff --git a/extensions/common/glm/gtx/extented_min_max.inl b/extensions/common/glm/gtx/extented_min_max.inl new file mode 100644 index 0000000000..1781d4b97b --- /dev/null +++ b/extensions/common/glm/gtx/extented_min_max.inl @@ -0,0 +1,169 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_extented_min_max +/// @file glm/gtx/extented_min_max.inl +/// @date 2007-03-14 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T> + GLM_FUNC_QUALIFIER T min( + T const & x, + T const & y, + T const & z) + { + return glm::min(glm::min(x, y), z); + } + + template <typename T, template <typename> class C> + GLM_FUNC_QUALIFIER C<T> min + ( + C<T> const & x, + typename C<T>::T const & y, + typename C<T>::T const & z + ) + { + return glm::min(glm::min(x, y), z); + } + + template <typename T, template <typename> class C> + GLM_FUNC_QUALIFIER C<T> min + ( + C<T> const & x, + C<T> const & y, + C<T> const & z + ) + { + return glm::min(glm::min(x, y), z); + } + + template <typename T> + GLM_FUNC_QUALIFIER T min + ( + T const & x, + T const & y, + T const & z, + T const & w + ) + { + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template <typename T, template <typename> class C> + GLM_FUNC_QUALIFIER C<T> min + ( + C<T> const & x, + typename C<T>::T const & y, + typename C<T>::T const & z, + typename C<T>::T const & w + ) + { + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template <typename T, template <typename> class C> + GLM_FUNC_QUALIFIER C<T> min + ( + C<T> const & x, + C<T> const & y, + C<T> const & z, + C<T> const & w + ) + { + return glm::min(glm::min(x, y), glm::min(z, w)); + } + + template <typename T> + GLM_FUNC_QUALIFIER T max( + T const & x, + T const & y, + T const & z) + { + return glm::max(glm::max(x, y), z); + } + + template <typename T, template <typename> class C> + GLM_FUNC_QUALIFIER C<T> max + ( + C<T> const & x, + typename C<T>::T const & y, + typename C<T>::T const & z + ) + { + return glm::max(glm::max(x, y), z); + } + + template <typename T, template <typename> class C> + GLM_FUNC_QUALIFIER C<T> max + ( + C<T> const & x, + C<T> const & y, + C<T> const & z + ) + { + return glm::max(glm::max(x, y), z); + } + + template <typename T> + GLM_FUNC_QUALIFIER T max + ( + T const & x, + T const & y, + T const & z, + T const & w + ) + { + return glm::max(glm::max(x, y), glm::max(z, w)); + } + + template <typename T, template <typename> class C> + GLM_FUNC_QUALIFIER C<T> max + ( + C<T> const & x, + typename C<T>::T const & y, + typename C<T>::T const & z, + typename C<T>::T const & w + ) + { + return glm::max(glm::max(x, y), glm::max(z, w)); + } + + template <typename T, template <typename> class C> + GLM_FUNC_QUALIFIER C<T> max + ( + C<T> const & x, + C<T> const & y, + C<T> const & z, + C<T> const & w + ) + { + return glm::max(glm::max(x, y), glm::max(z, w)); + } + +}//namespace glm diff --git a/extensions/common/glm/gtx/fast_exponential.hpp b/extensions/common/glm/gtx/fast_exponential.hpp new file mode 100644 index 0000000000..654a70f7f8 --- /dev/null +++ b/extensions/common/glm/gtx/fast_exponential.hpp @@ -0,0 +1,120 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_fast_exponential +/// @file glm/gtx/fast_exponential.hpp +/// @date 2006-01-09 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_half_float (dependence) +/// +/// @defgroup gtx_fast_exponential GLM_GTX_fast_exponential +/// @ingroup gtx +/// +/// @brief Fast but less accurate implementations of exponential based functions. +/// +/// <glm/gtx/fast_exponential.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_fast_exponential extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_exponential + /// @{ + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template <typename genType> + GLM_FUNC_DECL genType fastPow(genType x, genType y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> fastPow(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template <typename genTypeT, typename genTypeU> + GLM_FUNC_DECL genTypeT fastPow(genTypeT x, genTypeU y); + + /// Faster than the common pow function but less accurate. + /// @see gtx_fast_exponential + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> fastPow(vecType<T, P> const & x); + + /// Faster than the common exp function but less accurate. + /// @see gtx_fast_exponential + template <typename T> + GLM_FUNC_DECL T fastExp(T x); + + /// Faster than the common exp function but less accurate. + /// @see gtx_fast_exponential + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> fastExp(vecType<T, P> const & x); + + /// Faster than the common log function but less accurate. + /// @see gtx_fast_exponential + template <typename T> + GLM_FUNC_DECL T fastLog(T x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> fastLog(vecType<T, P> const & x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template <typename T> + GLM_FUNC_DECL T fastExp2(T x); + + /// Faster than the common exp2 function but less accurate. + /// @see gtx_fast_exponential + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> fastExp2(vecType<T, P> const & x); + + /// Faster than the common log2 function but less accurate. + /// @see gtx_fast_exponential + template <typename T> + GLM_FUNC_DECL T fastLog2(T x); + + /// Faster than the common log2 function but less accurate. + /// @see gtx_fast_exponential + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> fastLog2(vecType<T, P> const & x); + + /// @} +}//namespace glm + +#include "fast_exponential.inl" diff --git a/extensions/common/glm/gtx/fast_exponential.inl b/extensions/common/glm/gtx/fast_exponential.inl new file mode 100644 index 0000000000..54e1d009c5 --- /dev/null +++ b/extensions/common/glm/gtx/fast_exponential.inl @@ -0,0 +1,166 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_fast_exponential +/// @file glm/gtx/fast_exponential.inl +/// @date 2006-01-09 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + // fastPow: + template <typename genType> + GLM_FUNC_QUALIFIER genType fastPow(genType x, genType y) + { + return exp(y * log(x)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastPow(vecType<T, P> const & x, vecType<T, P> const & y) + { + return exp(y * log(x)); + } + + template <typename T> + GLM_FUNC_QUALIFIER T fastPow(T x, int y) + { + T f = static_cast<T>(1); + for(int i = 0; i < y; ++i) + f *= x; + return f; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastPow(vecType<T, P> const & x, vecType<int, P> const & y) + { + vecType<T, P> Result(uninitialize); + for(detail::component_count_t i = 0; i < detail::component_count(x); ++i) + Result[i] = fastPow(x[i], y[i]); + return Result; + } + + // fastExp + // Note: This function provides accurate results only for value between -1 and 1, else avoid it. + template <typename T> + GLM_FUNC_QUALIFIER T fastExp(T x) + { + // This has a better looking and same performance in release mode than the following code. However, in debug mode it's slower. + // return 1.0f + x * (1.0f + x * 0.5f * (1.0f + x * 0.3333333333f * (1.0f + x * 0.25 * (1.0f + x * 0.2f)))); + T x2 = x * x; + T x3 = x2 * x; + T x4 = x3 * x; + T x5 = x4 * x; + return T(1) + x + (x2 * T(0.5)) + (x3 * T(0.1666666667)) + (x4 * T(0.041666667)) + (x5 * T(0.008333333333)); + } + /* // Try to handle all values of float... but often shower than std::exp, glm::floor and the loop kill the performance + GLM_FUNC_QUALIFIER float fastExp(float x) + { + const float e = 2.718281828f; + const float IntegerPart = floor(x); + const float FloatPart = x - IntegerPart; + float z = 1.f; + + for(int i = 0; i < int(IntegerPart); ++i) + z *= e; + + const float x2 = FloatPart * FloatPart; + const float x3 = x2 * FloatPart; + const float x4 = x3 * FloatPart; + const float x5 = x4 * FloatPart; + return z * (1.0f + FloatPart + (x2 * 0.5f) + (x3 * 0.1666666667f) + (x4 * 0.041666667f) + (x5 * 0.008333333333f)); + } + + // Increase accuracy on number bigger that 1 and smaller than -1 but it's not enough for high and negative numbers + GLM_FUNC_QUALIFIER float fastExp(float x) + { + // This has a better looking and same performance in release mode than the following code. However, in debug mode it's slower. + // return 1.0f + x * (1.0f + x * 0.5f * (1.0f + x * 0.3333333333f * (1.0f + x * 0.25 * (1.0f + x * 0.2f)))); + float x2 = x * x; + float x3 = x2 * x; + float x4 = x3 * x; + float x5 = x4 * x; + float x6 = x5 * x; + float x7 = x6 * x; + float x8 = x7 * x; + return 1.0f + x + (x2 * 0.5f) + (x3 * 0.1666666667f) + (x4 * 0.041666667f) + (x5 * 0.008333333333f)+ (x6 * 0.00138888888888f) + (x7 * 0.000198412698f) + (x8 * 0.0000248015873f);; + } + */ + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastExp(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(fastExp, x); + } + + // fastLog + template <typename genType> + GLM_FUNC_QUALIFIER genType fastLog(genType x) + { + return std::log(x); + } + + /* Slower than the VC7.1 function... + GLM_FUNC_QUALIFIER float fastLog(float x) + { + float y1 = (x - 1.0f) / (x + 1.0f); + float y2 = y1 * y1; + return 2.0f * y1 * (1.0f + y2 * (0.3333333333f + y2 * (0.2f + y2 * 0.1428571429f))); + } + */ + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastLog(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(fastLog, x); + } + + //fastExp2, ln2 = 0.69314718055994530941723212145818f + template <typename genType> + GLM_FUNC_QUALIFIER genType fastExp2(genType x) + { + return fastExp(0.69314718055994530941723212145818f * x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastExp2(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(fastExp2, x); + } + + // fastLog2, ln2 = 0.69314718055994530941723212145818f + template <typename genType> + GLM_FUNC_QUALIFIER genType fastLog2(genType x) + { + return fastLog(x) / 0.69314718055994530941723212145818f; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastLog2(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(fastLog2, x); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/fast_square_root.hpp b/extensions/common/glm/gtx/fast_square_root.hpp new file mode 100644 index 0000000000..489fc9beea --- /dev/null +++ b/extensions/common/glm/gtx/fast_square_root.hpp @@ -0,0 +1,117 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_fast_square_root +/// @file glm/gtx/fast_square_root.hpp +/// @date 2006-01-04 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_fast_square_root GLM_GTX_fast_square_root +/// @ingroup gtx +/// +/// @brief Fast but less accurate implementations of square root based functions. +/// - Sqrt optimisation based on Newton's method, +/// www.gamedev.net/community/forums/topic.asp?topic id=139956 +/// +/// <glm/gtx/fast_square_root.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../common.hpp" +#include "../exponential.hpp" +#include "../geometric.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_fast_square_root extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_square_root + /// @{ + + /// Faster than the common sqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template <typename genType> + GLM_FUNC_DECL genType fastSqrt(genType x); + + /// Faster than the common sqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> fastSqrt(vecType<T, P> const & x); + + /// Faster than the common inversesqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template <typename genType> + GLM_FUNC_DECL genType fastInverseSqrt(genType x); + + /// Faster than the common inversesqrt function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> fastInverseSqrt(vecType<T, P> const & x); + + /// Faster than the common length function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template <typename genType> + GLM_FUNC_DECL genType fastLength(genType x); + + /// Faster than the common length function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL T fastLength(vecType<T, P> const & x); + + /// Faster than the common distance function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template <typename genType> + GLM_FUNC_DECL genType fastDistance(genType x, genType y); + + /// Faster than the common distance function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL T fastDistance(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Faster than the common normalize function but less accurate. + /// + /// @see gtx_fast_square_root extension. + template <typename genType> + GLM_FUNC_DECL genType fastNormalize(genType const & x); + + /// @} +}// namespace glm + +#include "fast_square_root.inl" diff --git a/extensions/common/glm/gtx/fast_square_root.inl b/extensions/common/glm/gtx/fast_square_root.inl new file mode 100644 index 0000000000..e99ca70e8b --- /dev/null +++ b/extensions/common/glm/gtx/fast_square_root.inl @@ -0,0 +1,110 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_fast_square_root +/// @file glm/gtx/fast_square_root.inl +/// @date 2006-01-04 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + // fastSqrt + template <typename genType> + GLM_FUNC_QUALIFIER genType fastSqrt(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'fastSqrt' only accept floating-point input"); + + return genType(1) / fastInverseSqrt(x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastSqrt(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(fastSqrt, x); + } + + // fastInversesqrt + template <typename genType> + GLM_FUNC_QUALIFIER genType fastInverseSqrt(genType x) + { +# ifdef __CUDACC__ // Wordaround for a CUDA compiler bug up to CUDA6 + tvec1<T, P> tmp(detail::compute_inversesqrt<tvec1, genType, lowp>::call(tvec1<genType, lowp>(x))); + return tmp.x; +# else + return detail::compute_inversesqrt<tvec1, genType, lowp>::call(tvec1<genType, lowp>(x)).x; +# endif + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastInverseSqrt(vecType<T, P> const & x) + { + return detail::compute_inversesqrt<vecType, T, P>::call(x); + } + + // fastLength + template <typename genType> + GLM_FUNC_QUALIFIER genType fastLength(genType x) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'fastLength' only accept floating-point inputs"); + + return abs(x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T fastLength(vecType<T, P> const & x) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'fastLength' only accept floating-point inputs"); + + return fastSqrt(dot(x, x)); + } + + // fastDistance + template <typename genType> + GLM_FUNC_QUALIFIER genType fastDistance(genType x, genType y) + { + return fastLength(y - x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T fastDistance(vecType<T, P> const & x, vecType<T, P> const & y) + { + return fastLength(y - x); + } + + // fastNormalize + template <typename genType> + GLM_FUNC_QUALIFIER genType fastNormalize(genType x) + { + return x > genType(0) ? genType(1) : -genType(1); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastNormalize(vecType<T, P> const & x) + { + return x * fastInverseSqrt(dot(x, x)); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/fast_trigonometry.hpp b/extensions/common/glm/gtx/fast_trigonometry.hpp new file mode 100644 index 0000000000..ad288827c7 --- /dev/null +++ b/extensions/common/glm/gtx/fast_trigonometry.hpp @@ -0,0 +1,104 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_fast_trigonometry +/// @file glm/gtx/fast_trigonometry.hpp +/// @date 2006-01-08 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_fast_trigonometry GLM_GTX_fast_trigonometry +/// @ingroup gtx +/// +/// @brief Fast but less accurate implementations of trigonometric functions. +/// +/// <glm/gtx/fast_trigonometry.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../gtc/constants.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_fast_trigonometry extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_fast_trigonometry + /// @{ + + /// Wrap an angle to [0 2pi[ + /// From GLM_GTX_fast_trigonometry extension. + template <typename T> + GLM_FUNC_DECL T wrapAngle(T angle); + + /// Faster than the common sin function but less accurate. + /// From GLM_GTX_fast_trigonometry extension. + template <typename T> + GLM_FUNC_DECL T fastSin(T angle); + + /// Faster than the common cos function but less accurate. + /// From GLM_GTX_fast_trigonometry extension. + template <typename T> + GLM_FUNC_DECL T fastCos(T angle); + + /// Faster than the common tan function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template <typename T> + GLM_FUNC_DECL T fastTan(T angle); + + /// Faster than the common asin function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template <typename T> + GLM_FUNC_DECL T fastAsin(T angle); + + /// Faster than the common acos function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template <typename T> + GLM_FUNC_DECL T fastAcos(T angle); + + /// Faster than the common atan function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template <typename T> + GLM_FUNC_DECL T fastAtan(T y, T x); + + /// Faster than the common atan function but less accurate. + /// Defined between -2pi and 2pi. + /// From GLM_GTX_fast_trigonometry extension. + template <typename T> + GLM_FUNC_DECL T fastAtan(T angle); + + /// @} +}//namespace glm + +#include "fast_trigonometry.inl" diff --git a/extensions/common/glm/gtx/fast_trigonometry.inl b/extensions/common/glm/gtx/fast_trigonometry.inl new file mode 100644 index 0000000000..83827b9022 --- /dev/null +++ b/extensions/common/glm/gtx/fast_trigonometry.inl @@ -0,0 +1,162 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_fast_trigonometry +/// @file glm/gtx/fast_trigonometry.inl +/// @date 2006-01-08 / 2014-11-25 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail +{ + template <typename T> + GLM_FUNC_QUALIFIER T cos_52s(T x) + { + T const xx(x * x); + return (T(0.9999932946) + xx * (T(-0.4999124376) + xx * (T(0.0414877472) + xx * T(-0.0012712095)))); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> cos_52s(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(cos_52s, x); + } +}//namespace detail + + // wrapAngle + template <typename T> + GLM_FUNC_QUALIFIER T wrapAngle(T angle) + { + return abs<T>(mod<T>(angle, two_pi<T>())); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> wrapAngle(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(wrapAngle, x); + } + + // cos + template <typename T> + GLM_FUNC_QUALIFIER T fastCos(T x) + { + T const angle(wrapAngle<T>(x)); + + if(angle<half_pi<T>()) + return detail::cos_52s(angle); + if(angle<pi<T>()) + return -detail::cos_52s(pi<T>() - angle); + if(angle<(T(3) * half_pi<T>())) + return -detail::cos_52s(angle - pi<T>()); + + return detail::cos_52s(two_pi<T>() - angle); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastCos(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(fastCos, x); + } + + // sin + template <typename T> + GLM_FUNC_QUALIFIER T fastSin(T x) + { + return fastCos<T>(half_pi<T>() - x); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastSin(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(fastSin, x); + } + + // tan + template <typename T> + GLM_FUNC_QUALIFIER T fastTan(T x) + { + return x + (x * x * x * T(0.3333333333)) + (x * x * x * x * x * T(0.1333333333333)) + (x * x * x * x * x * x * x * T(0.0539682539)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastTan(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(fastTan, x); + } + + // asin + template <typename T> + GLM_FUNC_QUALIFIER T fastAsin(T x) + { + return x + (x * x * x * T(0.166666667)) + (x * x * x * x * x * T(0.075)) + (x * x * x * x * x * x * x * T(0.0446428571)) + (x * x * x * x * x * x * x * x * x * T(0.0303819444));// + (x * x * x * x * x * x * x * x * x * x * x * T(0.022372159)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastAsin(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(fastAsin, x); + } + + // acos + template <typename T> + GLM_FUNC_QUALIFIER T fastAcos(T x) + { + return T(1.5707963267948966192313216916398) - fastAsin(x); //(PI / 2) + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastAcos(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(fastAcos, x); + } + + // atan + template <typename T> + GLM_FUNC_QUALIFIER T fastAtan(T y, T x) + { + T sgn = sign(y) * sign(x); + return abs(fastAtan(y / x)) * sgn; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastAtan(vecType<T, P> const & y, vecType<T, P> const & x) + { + return detail::functor2<T, P, vecType>::call(fastAtan, y, x); + } + + template <typename T> + GLM_FUNC_QUALIFIER T fastAtan(T x) + { + return x - (x * x * x * T(0.333333333333)) + (x * x * x * x * x * T(0.2)) - (x * x * x * x * x * x * x * T(0.1428571429)) + (x * x * x * x * x * x * x * x * x * T(0.111111111111)) - (x * x * x * x * x * x * x * x * x * x * x * T(0.0909090909)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> fastAtan(vecType<T, P> const & x) + { + return detail::functor1<T, T, P, vecType>::call(fastAtan, x); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/gradient_paint.hpp b/extensions/common/glm/gtx/gradient_paint.hpp new file mode 100644 index 0000000000..6f2d1d2094 --- /dev/null +++ b/extensions/common/glm/gtx/gradient_paint.hpp @@ -0,0 +1,77 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_gradient_paint +/// @file glm/gtx/gradient_paint.hpp +/// @date 2009-03-06 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_optimum_pow (dependence) +/// +/// @defgroup gtx_gradient_paint GLM_GTX_gradient_paint +/// @ingroup gtx +/// +/// @brief Functions that return the color of procedural gradient for specific coordinates. +/// <glm/gtx/gradient_paint.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/optimum_pow.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_gradient_paint extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_gradient_paint + /// @{ + + /// Return a color from a radial gradient. + /// @see - gtx_gradient_paint + template <typename T, precision P> + GLM_FUNC_DECL T radialGradient( + tvec2<T, P> const & Center, + T const & Radius, + tvec2<T, P> const & Focal, + tvec2<T, P> const & Position); + + /// Return a color from a linear gradient. + /// @see - gtx_gradient_paint + template <typename T, precision P> + GLM_FUNC_DECL T linearGradient( + tvec2<T, P> const & Point0, + tvec2<T, P> const & Point1, + tvec2<T, P> const & Position); + + /// @} +}// namespace glm + +#include "gradient_paint.inl" diff --git a/extensions/common/glm/gtx/gradient_paint.inl b/extensions/common/glm/gtx/gradient_paint.inl new file mode 100644 index 0000000000..6c790292fb --- /dev/null +++ b/extensions/common/glm/gtx/gradient_paint.inl @@ -0,0 +1,66 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_gradient_paint +/// @file glm/gtx/gradient_paint.inl +/// @date 2009-03-06 / 2013-04-09 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER T radialGradient + ( + tvec2<T, P> const & Center, + T const & Radius, + tvec2<T, P> const & Focal, + tvec2<T, P> const & Position + ) + { + tvec2<T, P> F = Focal - Center; + tvec2<T, P> D = Position - Focal; + T Radius2 = pow2(Radius); + T Fx2 = pow2(F.x); + T Fy2 = pow2(F.y); + + T Numerator = (D.x * F.x + D.y * F.y) + sqrt(Radius2 * (pow2(D.x) + pow2(D.y)) - pow2(D.x * F.y - D.y * F.x)); + T Denominator = Radius2 - (Fx2 + Fy2); + return Numerator / Denominator; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T linearGradient + ( + tvec2<T, P> const & Point0, + tvec2<T, P> const & Point1, + tvec2<T, P> const & Position + ) + { + tvec2<T, P> Dist = Point1 - Point0; + return (Dist.x * (Position.x - Point0.x) + Dist.y * (Position.y - Point0.y)) / glm::dot(Dist, Dist); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/handed_coordinate_space.hpp b/extensions/common/glm/gtx/handed_coordinate_space.hpp new file mode 100644 index 0000000000..e24d692bea --- /dev/null +++ b/extensions/common/glm/gtx/handed_coordinate_space.hpp @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_handed_coordinate_space +/// @file glm/gtx/handed_coordinate_space.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_handed_coordinate_space GLM_GTX_handed_coordinate_space +/// @ingroup gtx +/// +/// @brief To know if a set of three basis vectors defines a right or left-handed coordinate system. +/// +/// <glm/gtx/handed_coordinate_system.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_handed_coordinate_space extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_handed_coordinate_space + /// @{ + + //! Return if a trihedron right handed or not. + //! From GLM_GTX_handed_coordinate_space extension. + template <typename T, precision P> + GLM_FUNC_DECL bool rightHanded( + tvec3<T, P> const & tangent, + tvec3<T, P> const & binormal, + tvec3<T, P> const & normal); + + //! Return if a trihedron left handed or not. + //! From GLM_GTX_handed_coordinate_space extension. + template <typename T, precision P> + GLM_FUNC_DECL bool leftHanded( + tvec3<T, P> const & tangent, + tvec3<T, P> const & binormal, + tvec3<T, P> const & normal); + + /// @} +}// namespace glm + +#include "handed_coordinate_space.inl" diff --git a/extensions/common/glm/gtx/handed_coordinate_space.inl b/extensions/common/glm/gtx/handed_coordinate_space.inl new file mode 100644 index 0000000000..f634f8dd45 --- /dev/null +++ b/extensions/common/glm/gtx/handed_coordinate_space.inl @@ -0,0 +1,56 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_handed_coordinate_space +/// @file glm/gtx/handed_coordinate_space.inl +/// @date 2005-12-21 / 2009-02-19 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool rightHanded + ( + tvec3<T, P> const & tangent, + tvec3<T, P> const & binormal, + tvec3<T, P> const & normal + ) + { + return dot(cross(normal, tangent), binormal) > T(0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool leftHanded + ( + tvec3<T, P> const & tangent, + tvec3<T, P> const & binormal, + tvec3<T, P> const & normal + ) + { + return dot(cross(normal, tangent), binormal) < T(0); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/integer.hpp b/extensions/common/glm/gtx/integer.hpp new file mode 100644 index 0000000000..3fed54f3a1 --- /dev/null +++ b/extensions/common/glm/gtx/integer.hpp @@ -0,0 +1,101 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_integer +/// @file glm/gtx/integer.hpp +/// @date 2005-12-24 / 2011-10-13 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_integer GLM_GTX_integer +/// @ingroup gtx +/// +/// @brief Add support for integer for core functions +/// +/// <glm/gtx/integer.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/integer.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_integer extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_integer + /// @{ + + //! Returns x raised to the y power. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL int pow(int x, int y); + + //! Returns the positive square root of x. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL int sqrt(int x); + + //! Returns the floor log2 of x. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL unsigned int floor_log2(unsigned int x); + + //! Modulus. Returns x - y * floor(x / y) for each component in x using the floating point value y. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL int mod(int x, int y); + + //! Return the factorial value of a number (!12 max, integer only) + //! From GLM_GTX_integer extension. + template <typename genType> + GLM_FUNC_DECL genType factorial(genType const & x); + + //! 32bit signed integer. + //! From GLM_GTX_integer extension. + typedef signed int sint; + + //! Returns x raised to the y power. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint pow(uint x, uint y); + + //! Returns the positive square root of x. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint sqrt(uint x); + + //! Modulus. Returns x - y * floor(x / y) for each component in x using the floating point value y. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint mod(uint x, uint y); + + //! Returns the number of leading zeros. + //! From GLM_GTX_integer extension. + GLM_FUNC_DECL uint nlz(uint x); + + /// @} +}//namespace glm + +#include "integer.inl" diff --git a/extensions/common/glm/gtx/integer.inl b/extensions/common/glm/gtx/integer.inl new file mode 100644 index 0000000000..55d8f1a81e --- /dev/null +++ b/extensions/common/glm/gtx/integer.inl @@ -0,0 +1,211 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_integer +/// @file glm/gtx/integer.inl +/// @date 2005-12-24 / 2011-10-13 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + // pow + GLM_FUNC_QUALIFIER int pow(int x, int y) + { + if(y == 0) + return 1; + int result = x; + for(int i = 1; i < y; ++i) + result *= x; + return result; + } + + // sqrt: From Christopher J. Musial, An integer square root, Graphics Gems, 1990, page 387 + GLM_FUNC_QUALIFIER int sqrt(int x) + { + if(x <= 1) return x; + + int NextTrial = x >> 1; + int CurrentAnswer; + + do + { + CurrentAnswer = NextTrial; + NextTrial = (NextTrial + x / NextTrial) >> 1; + } while(NextTrial < CurrentAnswer); + + return CurrentAnswer; + } + +// Henry Gordon Dietz: http://aggregate.org/MAGIC/ +namespace detail +{ + GLM_FUNC_QUALIFIER unsigned int ones32(unsigned int x) + { + /* 32-bit recursive reduction using SWAR... + but first step is mapping 2-bit values + into sum of 2 1-bit values in sneaky way + */ + x -= ((x >> 1) & 0x55555555); + x = (((x >> 2) & 0x33333333) + (x & 0x33333333)); + x = (((x >> 4) + x) & 0x0f0f0f0f); + x += (x >> 8); + x += (x >> 16); + return(x & 0x0000003f); + } +}//namespace detail + + // Henry Gordon Dietz: http://aggregate.org/MAGIC/ +/* + GLM_FUNC_QUALIFIER unsigned int floor_log2(unsigned int x) + { + x |= (x >> 1); + x |= (x >> 2); + x |= (x >> 4); + x |= (x >> 8); + x |= (x >> 16); + + return _detail::ones32(x) >> 1; + } +*/ + // mod + GLM_FUNC_QUALIFIER int mod(int x, int y) + { + return x - y * (x / y); + } + + // factorial (!12 max, integer only) + template <typename genType> + GLM_FUNC_QUALIFIER genType factorial(genType const & x) + { + genType Temp = x; + genType Result; + for(Result = 1; Temp > 1; --Temp) + Result *= Temp; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> factorial( + tvec2<T, P> const & x) + { + return tvec2<T, P>( + factorial(x.x), + factorial(x.y)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> factorial( + tvec3<T, P> const & x) + { + return tvec3<T, P>( + factorial(x.x), + factorial(x.y), + factorial(x.z)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> factorial( + tvec4<T, P> const & x) + { + return tvec4<T, P>( + factorial(x.x), + factorial(x.y), + factorial(x.z), + factorial(x.w)); + } + + GLM_FUNC_QUALIFIER uint pow(uint x, uint y) + { + uint result = x; + for(uint i = 1; i < y; ++i) + result *= x; + return result; + } + + GLM_FUNC_QUALIFIER uint sqrt(uint x) + { + if(x <= 1) return x; + + uint NextTrial = x >> 1; + uint CurrentAnswer; + + do + { + CurrentAnswer = NextTrial; + NextTrial = (NextTrial + x / NextTrial) >> 1; + } while(NextTrial < CurrentAnswer); + + return CurrentAnswer; + } + + GLM_FUNC_QUALIFIER uint mod(uint x, uint y) + { + return x - y * (x / y); + } + +#if(GLM_COMPILER & (GLM_COMPILER_VC | GLM_COMPILER_GCC)) + + GLM_FUNC_QUALIFIER unsigned int nlz(unsigned int x) + { + return 31u - findMSB(x); + } + +#else + + // Hackers Delight: http://www.hackersdelight.org/HDcode/nlz.c.txt + GLM_FUNC_QUALIFIER unsigned int nlz(unsigned int x) + { + int y, m, n; + + y = -int(x >> 16); // If left half of x is 0, + m = (y >> 16) & 16; // set n = 16. If left half + n = 16 - m; // is nonzero, set n = 0 and + x = x >> m; // shift x right 16. + // Now x is of the form 0000xxxx. + y = x - 0x100; // If positions 8-15 are 0, + m = (y >> 16) & 8; // add 8 to n and shift x left 8. + n = n + m; + x = x << m; + + y = x - 0x1000; // If positions 12-15 are 0, + m = (y >> 16) & 4; // add 4 to n and shift x left 4. + n = n + m; + x = x << m; + + y = x - 0x4000; // If positions 14-15 are 0, + m = (y >> 16) & 2; // add 2 to n and shift x left 2. + n = n + m; + x = x << m; + + y = x >> 14; // Set y = 0, 1, 2, or 3. + m = y & ~(y >> 1); // Set m = 0, 1, 2, or 2 resp. + return unsigned(n + 2 - m); + } + +#endif//(GLM_COMPILER) + +}//namespace glm diff --git a/extensions/common/glm/gtx/intersect.hpp b/extensions/common/glm/gtx/intersect.hpp new file mode 100644 index 0000000000..dd984a1b6c --- /dev/null +++ b/extensions/common/glm/gtx/intersect.hpp @@ -0,0 +1,112 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_intersect +/// @file glm/gtx/intersect.hpp +/// @date 2007-04-03 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_closest_point (dependence) +/// +/// @defgroup gtx_intersect GLM_GTX_intersect +/// @ingroup gtx +/// +/// @brief Add intersection functions +/// +/// <glm/gtx/intersect.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/closest_point.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_closest_point extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_intersect + /// @{ + + //! Compute the intersection of a ray and a triangle. + //! Ray direction and plane normal must be unit length. + //! From GLM_GTX_intersect extension. + template <typename genType> + GLM_FUNC_DECL bool intersectRayPlane( + genType const & orig, genType const & dir, + genType const & planeOrig, genType const & planeNormal, + typename genType::value_type & intersectionDistance); + + //! Compute the intersection of a ray and a triangle. + //! From GLM_GTX_intersect extension. + template <typename genType> + GLM_FUNC_DECL bool intersectRayTriangle( + genType const & orig, genType const & dir, + genType const & vert0, genType const & vert1, genType const & vert2, + genType & baryPosition); + + //! Compute the intersection of a line and a triangle. + //! From GLM_GTX_intersect extension. + template <typename genType> + GLM_FUNC_DECL bool intersectLineTriangle( + genType const & orig, genType const & dir, + genType const & vert0, genType const & vert1, genType const & vert2, + genType & position); + + //! Compute the intersection distance of a ray and a sphere. + //! The ray direction vector is unit length. + //! From GLM_GTX_intersect extension. + template <typename genType> + GLM_FUNC_DECL bool intersectRaySphere( + genType const & rayStarting, genType const & rayNormalizedDirection, + genType const & sphereCenter, typename genType::value_type const sphereRadiusSquered, + typename genType::value_type & intersectionDistance); + + //! Compute the intersection of a ray and a sphere. + //! From GLM_GTX_intersect extension. + template <typename genType> + GLM_FUNC_DECL bool intersectRaySphere( + genType const & rayStarting, genType const & rayNormalizedDirection, + genType const & sphereCenter, const typename genType::value_type sphereRadius, + genType & intersectionPosition, genType & intersectionNormal); + + //! Compute the intersection of a line and a sphere. + //! From GLM_GTX_intersect extension + template <typename genType> + GLM_FUNC_DECL bool intersectLineSphere( + genType const & point0, genType const & point1, + genType const & sphereCenter, typename genType::value_type sphereRadius, + genType & intersectionPosition1, genType & intersectionNormal1, + genType & intersectionPosition2 = genType(), genType & intersectionNormal2 = genType()); + + /// @} +}//namespace glm + +#include "intersect.inl" diff --git a/extensions/common/glm/gtx/intersect.inl b/extensions/common/glm/gtx/intersect.inl new file mode 100644 index 0000000000..60ddd30021 --- /dev/null +++ b/extensions/common/glm/gtx/intersect.inl @@ -0,0 +1,217 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// OpenGL Mathematics Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Created : 2007-04-03 +// Updated : 2009-01-20 +// Licence : This source is under MIT licence +// File : glm/gtx/intersect.inl +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "../geometric.hpp" +#include <cfloat> +#include <limits> + +namespace glm +{ + template <typename genType> + GLM_FUNC_QUALIFIER bool intersectRayPlane + ( + genType const & orig, genType const & dir, + genType const & planeOrig, genType const & planeNormal, + typename genType::value_type & intersectionDistance + ) + { + typename genType::value_type d = glm::dot(dir, planeNormal); + typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); + + if(d < Epsilon) + { + intersectionDistance = glm::dot(planeOrig - orig, planeNormal) / d; + return true; + } + + return false; + } + + template <typename genType> + GLM_FUNC_QUALIFIER bool intersectRayTriangle + ( + genType const & orig, genType const & dir, + genType const & v0, genType const & v1, genType const & v2, + genType & baryPosition + ) + { + genType e1 = v1 - v0; + genType e2 = v2 - v0; + + genType p = glm::cross(dir, e2); + + typename genType::value_type a = glm::dot(e1, p); + + typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); + if(a < Epsilon) + return false; + + typename genType::value_type f = typename genType::value_type(1.0f) / a; + + genType s = orig - v0; + baryPosition.x = f * glm::dot(s, p); + if(baryPosition.x < typename genType::value_type(0.0f)) + return false; + if(baryPosition.x > typename genType::value_type(1.0f)) + return false; + + genType q = glm::cross(s, e1); + baryPosition.y = f * glm::dot(dir, q); + if(baryPosition.y < typename genType::value_type(0.0f)) + return false; + if(baryPosition.y + baryPosition.x > typename genType::value_type(1.0f)) + return false; + + baryPosition.z = f * glm::dot(e2, q); + + return baryPosition.z >= typename genType::value_type(0.0f); + } + + //template <typename genType> + //GLM_FUNC_QUALIFIER bool intersectRayTriangle + //( + // genType const & orig, genType const & dir, + // genType const & vert0, genType const & vert1, genType const & vert2, + // genType & position + //) + //{ + // typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); + // + // genType edge1 = vert1 - vert0; + // genType edge2 = vert2 - vert0; + // + // genType pvec = cross(dir, edge2); + // + // float det = dot(edge1, pvec); + // if(det < Epsilon) + // return false; + // + // genType tvec = orig - vert0; + // + // position.y = dot(tvec, pvec); + // if (position.y < typename genType::value_type(0) || position.y > det) + // return typename genType::value_type(0); + // + // genType qvec = cross(tvec, edge1); + // + // position.z = dot(dir, qvec); + // if (position.z < typename genType::value_type(0) || position.y + position.z > det) + // return typename genType::value_type(0); + // + // position.x = dot(edge2, qvec); + // position *= typename genType::value_type(1) / det; + // + // return typename genType::value_type(1); + //} + + template <typename genType> + GLM_FUNC_QUALIFIER bool intersectLineTriangle + ( + genType const & orig, genType const & dir, + genType const & vert0, genType const & vert1, genType const & vert2, + genType & position + ) + { + typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); + + genType edge1 = vert1 - vert0; + genType edge2 = vert2 - vert0; + + genType pvec = cross(dir, edge2); + + float det = dot(edge1, pvec); + + if (det > -Epsilon && det < Epsilon) + return false; + float inv_det = typename genType::value_type(1) / det; + + genType tvec = orig - vert0; + + position.y = dot(tvec, pvec) * inv_det; + if (position.y < typename genType::value_type(0) || position.y > typename genType::value_type(1)) + return false; + + genType qvec = cross(tvec, edge1); + + position.z = dot(dir, qvec) * inv_det; + if (position.z < typename genType::value_type(0) || position.y + position.z > typename genType::value_type(1)) + return false; + + position.x = dot(edge2, qvec) * inv_det; + + return true; + } + + template <typename genType> + GLM_FUNC_QUALIFIER bool intersectRaySphere + ( + genType const & rayStarting, genType const & rayNormalizedDirection, + genType const & sphereCenter, const typename genType::value_type sphereRadiusSquered, + typename genType::value_type & intersectionDistance + ) + { + typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); + genType diff = sphereCenter - rayStarting; + typename genType::value_type t0 = dot(diff, rayNormalizedDirection); + typename genType::value_type dSquared = dot(diff, diff) - t0 * t0; + if( dSquared > sphereRadiusSquered ) + { + return false; + } + typename genType::value_type t1 = sqrt( sphereRadiusSquered - dSquared ); + intersectionDistance = t0 > t1 + Epsilon ? t0 - t1 : t0 + t1; + return intersectionDistance > Epsilon; + } + + template <typename genType> + GLM_FUNC_QUALIFIER bool intersectRaySphere + ( + genType const & rayStarting, genType const & rayNormalizedDirection, + genType const & sphereCenter, const typename genType::value_type sphereRadius, + genType & intersectionPosition, genType & intersectionNormal + ) + { + typename genType::value_type distance; + if( intersectRaySphere( rayStarting, rayNormalizedDirection, sphereCenter, sphereRadius * sphereRadius, distance ) ) + { + intersectionPosition = rayStarting + rayNormalizedDirection * distance; + intersectionNormal = (intersectionPosition - sphereCenter) / sphereRadius; + return true; + } + return false; + } + + template <typename genType> + GLM_FUNC_QUALIFIER bool intersectLineSphere + ( + genType const & point0, genType const & point1, + genType const & sphereCenter, typename genType::value_type sphereRadius, + genType & intersectionPoint1, genType & intersectionNormal1, + genType & intersectionPoint2, genType & intersectionNormal2 + ) + { + typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); + genType dir = normalize(point1 - point0); + genType diff = sphereCenter - point0; + typename genType::value_type t0 = dot(diff, dir); + typename genType::value_type dSquared = dot(diff, diff) - t0 * t0; + if( dSquared > sphereRadius * sphereRadius ) + { + return false; + } + typename genType::value_type t1 = sqrt( sphereRadius * sphereRadius - dSquared ); + if( t0 < t1 + Epsilon ) + t1 = -t1; + intersectionPoint1 = point0 + dir * (t0 - t1); + intersectionNormal1 = (intersectionPoint1 - sphereCenter) / sphereRadius; + intersectionPoint2 = point0 + dir * (t0 + t1); + intersectionNormal2 = (intersectionPoint2 - sphereCenter) / sphereRadius; + return true; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/io.hpp b/extensions/common/glm/gtx/io.hpp new file mode 100644 index 0000000000..b33ade8932 --- /dev/null +++ b/extensions/common/glm/gtx/io.hpp @@ -0,0 +1,224 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_io +/// @file glm/gtx/io.hpp +/// @date 2013-11-22 / 2014-11-25 +/// @author Jan P Springer (regnirpsj@gmail.com) +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_io GLM_GTX_io +/// @ingroup gtx +/// +/// @brief std::[w]ostream support for glm types +/// +/// std::[w]ostream support for glm types + precision/width/etc. manipulators +/// based on howard hinnant's std::chrono io proposal +/// [http://home.roadrunner.com/~hinnant/bloomington/chrono_io.html] +/// +/// <glm/gtx/io.hpp> needs to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/quaternion.hpp" + +#if(defined(GLM_MESSAGES) && !defined(glm_ext)) +# pragma message("GLM: GLM_GTX_io extension included") +#endif + +#include <iosfwd> // std::basic_ostream<> (fwd) +#include <locale> // std::locale, std::locale::facet, std::locale::id +#include <utility> // std::pair<> + +namespace glm +{ + /// @addtogroup gtx_io + /// @{ + + namespace io + { + enum order_type { column_major, row_major}; + + template <typename CTy> + class format_punct : public std::locale::facet + { + typedef CTy char_type; + + public: + + static std::locale::id id; + + bool formatted; + unsigned precision; + unsigned width; + char_type separator; + char_type delim_left; + char_type delim_right; + char_type space; + char_type newline; + order_type order; + + explicit format_punct(size_t a = 0); + explicit format_punct(format_punct const&); + }; + + template <typename CTy, typename CTr = std::char_traits<CTy> > + class basic_state_saver { + + public: + + explicit basic_state_saver(std::basic_ios<CTy,CTr>&); + ~basic_state_saver(); + + private: + + typedef ::std::basic_ios<CTy,CTr> state_type; + typedef typename state_type::char_type char_type; + typedef ::std::ios_base::fmtflags flags_type; + typedef ::std::streamsize streamsize_type; + typedef ::std::locale const locale_type; + + state_type& state_; + flags_type flags_; + streamsize_type precision_; + streamsize_type width_; + char_type fill_; + locale_type locale_; + + basic_state_saver& operator=(basic_state_saver const&); + }; + + typedef basic_state_saver<char> state_saver; + typedef basic_state_saver<wchar_t> wstate_saver; + + template <typename CTy, typename CTr = std::char_traits<CTy> > + class basic_format_saver + { + public: + + explicit basic_format_saver(std::basic_ios<CTy,CTr>&); + ~basic_format_saver(); + + private: + + basic_state_saver<CTy> const bss_; + + basic_format_saver& operator=(basic_format_saver const&); + }; + + typedef basic_format_saver<char> format_saver; + typedef basic_format_saver<wchar_t> wformat_saver; + + struct precision + { + unsigned value; + + explicit precision(unsigned); + }; + + struct width + { + unsigned value; + + explicit width(unsigned); + }; + + template <typename CTy> + struct delimeter + { + CTy value[3]; + + explicit delimeter(CTy /* left */, CTy /* right */, CTy /* separator */ = ','); + }; + + struct order + { + order_type value; + + explicit order(order_type); + }; + + // functions, inlined (inline) + + template <typename FTy, typename CTy, typename CTr> + FTy const& get_facet(std::basic_ios<CTy,CTr>&); + template <typename FTy, typename CTy, typename CTr> + std::basic_ios<CTy,CTr>& formatted(std::basic_ios<CTy,CTr>&); + template <typename FTy, typename CTy, typename CTr> + std::basic_ios<CTy,CTr>& unformattet(std::basic_ios<CTy,CTr>&); + + template <typename CTy, typename CTr> + std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, precision const&); + template <typename CTy, typename CTr> + std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, width const&); + template <typename CTy, typename CTr> + std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, delimeter<CTy> const&); + template <typename CTy, typename CTr> + std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>&, order const&); + }//namespace io + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tquat<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tvec2<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tvec3<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tvec4<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat2x2<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat2x3<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat2x4<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat3x2<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat3x3<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat3x4<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat4x2<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat4x3<T,P> const&); + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>&, tmat4x4<T,P> const&); + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_DECL std::basic_ostream<CTy,CTr> & operator<<( + std::basic_ostream<CTy,CTr> &, + std::pair<tmat4x4<T,P> const, + tmat4x4<T,P> const> const &); + + /// @} +}//namespace glm + +#include "io.inl" diff --git a/extensions/common/glm/gtx/io.inl b/extensions/common/glm/gtx/io.inl new file mode 100644 index 0000000000..63e2735964 --- /dev/null +++ b/extensions/common/glm/gtx/io.inl @@ -0,0 +1,618 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2013 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_io +/// @file glm/gtx/io.inl +/// @date 2013-11-22 / 2014-11-25 +/// @author Jan P Springer (regnirpsj@gmail.com) +/////////////////////////////////////////////////////////////////////////////////////////////////// + +#include <iomanip> // std::setfill<>, std::fixed, std::setprecision, std::right, std::setw +#include <ostream> // std::basic_ostream<> + +namespace glm{ +namespace io +{ + template <typename CTy> + /* explicit */ GLM_FUNC_QUALIFIER + format_punct<CTy>::format_punct(size_t a) + : std::locale::facet(a), + formatted (true), + precision (3), + width (1 + 4 + 1 + precision), + separator (','), + delim_left ('['), + delim_right (']'), + space (' '), + newline ('\n'), + order (row_major) + {} + + template <typename CTy> + /* explicit */ GLM_FUNC_QUALIFIER + format_punct<CTy>::format_punct(format_punct const& a) + : std::locale::facet(0), + formatted (a.formatted), + precision (a.precision), + width (a.width), + separator (a.separator), + delim_left (a.delim_left), + delim_right (a.delim_right), + space (a.space), + newline (a.newline), + order (a.order) + {} + + template <typename CTy> std::locale::id format_punct<CTy>::id; + + template <typename CTy, typename CTr> + /* explicit */ GLM_FUNC_QUALIFIER basic_state_saver<CTy,CTr>::basic_state_saver(std::basic_ios<CTy,CTr>& a) + : state_ (a), + flags_ (a.flags()), + precision_(a.precision()), + width_ (a.width()), + fill_ (a.fill()), + locale_ (a.getloc()) + {} + + template <typename CTy, typename CTr> + GLM_FUNC_QUALIFIER basic_state_saver<CTy,CTr>::~basic_state_saver() + { + state_.imbue(locale_); + state_.fill(fill_); + state_.width(width_); + state_.precision(precision_); + state_.flags(flags_); + } + + template <typename CTy, typename CTr> + /* explicit */ GLM_FUNC_QUALIFIER basic_format_saver<CTy,CTr>::basic_format_saver(std::basic_ios<CTy,CTr>& a) + : bss_(a) + { + a.imbue(std::locale(a.getloc(), new format_punct<CTy>(get_facet<format_punct<CTy> >(a)))); + } + + template <typename CTy, typename CTr> + GLM_FUNC_QUALIFIER + basic_format_saver<CTy,CTr>::~basic_format_saver() + {} + + /* explicit */ GLM_FUNC_QUALIFIER precision::precision(unsigned a) + : value(a) + {} + + /* explicit */ GLM_FUNC_QUALIFIER width::width(unsigned a) + : value(a) + {} + + template <typename CTy> + /* explicit */ GLM_FUNC_QUALIFIER delimeter<CTy>::delimeter(CTy a, CTy b, CTy c) + : value() + { + value[0] = a; + value[1] = b; + value[2] = c; + } + + /* explicit */ GLM_FUNC_QUALIFIER + order::order(order_type a) + : value(a) + {} + + template <typename FTy, typename CTy, typename CTr> + GLM_FUNC_QUALIFIER FTy const& get_facet(std::basic_ios<CTy,CTr>& ios) + { + if (!std::has_facet<FTy>(ios.getloc())) { + ios.imbue(std::locale(ios.getloc(), new FTy)); + } + + return std::use_facet<FTy>(ios.getloc()); + } + + template <typename CTy, typename CTr> + GLM_FUNC_QUALIFIER std::basic_ios<CTy,CTr>& formatted(std::basic_ios<CTy,CTr>& ios) + { + const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(ios)).formatted = true; + + return ios; + } + + template <typename CTy, typename CTr> + GLM_FUNC_QUALIFIER std::basic_ios<CTy,CTr>& unformatted(std::basic_ios<CTy,CTr>& ios) + { + const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(ios)).formatted = false; + + return ios; + } + + template <typename CTy, typename CTr> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, precision const& a) + { + const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).precision = a.value; + + return os; + } + + template <typename CTy, typename CTr> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, width const& a) + { + const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).width = a.value; + + return os; + } + + template <typename CTy, typename CTr> + std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, delimeter<CTy> const& a) + { + format_punct<CTy> & fmt(const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os))); + + fmt.delim_left = a.value[0]; + fmt.delim_right = a.value[1]; + fmt.separator = a.value[2]; + + return os; + } + + template <typename CTy, typename CTr> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy, CTr>& operator<<(std::basic_ostream<CTy, CTr>& os, order const& a) + { + const_cast<format_punct<CTy>&>(get_facet<format_punct<CTy> >(os)).order = a.value; + + return os; + } +} // namespace io + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tquat<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + + if(fmt.formatted) + { + io::basic_state_saver<CTy> const bss(os); + + os << std::fixed + << std::right + << std::setprecision(fmt.precision) + << std::setfill(fmt.space) + << fmt.delim_left + << std::setw(fmt.width) << a.w << fmt.separator + << std::setw(fmt.width) << a.x << fmt.separator + << std::setw(fmt.width) << a.y << fmt.separator + << std::setw(fmt.width) << a.z + << fmt.delim_right; + } + else + { + os << a.w << fmt.space << a.x << fmt.space << a.y << fmt.space << a.z; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tvec2<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + + if(fmt.formatted) + { + io::basic_state_saver<CTy> const bss(os); + + os << std::fixed + << std::right + << std::setprecision(fmt.precision) + << std::setfill(fmt.space) + << fmt.delim_left + << std::setw(fmt.width) << a.x << fmt.separator + << std::setw(fmt.width) << a.y + << fmt.delim_right; + } + else + { + os << a.x << fmt.space << a.y; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tvec3<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + + if(fmt.formatted) + { + io::basic_state_saver<CTy> const bss(os); + + os << std::fixed + << std::right + << std::setprecision(fmt.precision) + << std::setfill(fmt.space) + << fmt.delim_left + << std::setw(fmt.width) << a.x << fmt.separator + << std::setw(fmt.width) << a.y << fmt.separator + << std::setw(fmt.width) << a.z + << fmt.delim_right; + } + else + { + os << a.x << fmt.space << a.y << fmt.space << a.z; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tvec4<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + + if(fmt.formatted) + { + io::basic_state_saver<CTy> const bss(os); + + os << std::fixed + << std::right + << std::setprecision(fmt.precision) + << std::setfill(fmt.space) + << fmt.delim_left + << std::setw(fmt.width) << a.x << fmt.separator + << std::setw(fmt.width) << a.y << fmt.separator + << std::setw(fmt.width) << a.z << fmt.separator + << std::setw(fmt.width) << a.w + << fmt.delim_right; + } + else + { + os << a.x << fmt.space << a.y << fmt.space << a.z << fmt.space << a.w; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x2<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + tmat2x2<T,P> m(a); + + if(io::row_major == fmt.order) + m = transpose(a); + + if(fmt.formatted) + { + os << fmt.newline + << fmt.delim_left << m[0] << fmt.newline + << fmt.space << m[1] << fmt.delim_right; + } + else + { + os << m[0] << fmt.space << m[1]; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x3<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + tmat3x2<T,P> m(a); + + if(io::row_major == fmt.order) + m = transpose(a); + + if(fmt.formatted) + { + os << fmt.newline + << fmt.delim_left << m[0] << fmt.newline + << fmt.space << m[1] << fmt.newline + << fmt.space << m[2] << fmt.delim_right; + } + else + { + os << m[0] << fmt.space << m[1] << fmt.space << m[2]; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat2x4<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + tmat4x2<T,P> m(a); + + if(io::row_major == fmt.order) + m = transpose(a); + + + if(fmt.formatted) + { + os << fmt.newline + << fmt.delim_left << m[0] << fmt.newline + << fmt.space << m[1] << fmt.newline + << fmt.space << m[2] << fmt.newline + << fmt.space << m[3] << fmt.delim_right; + } + else + { + os << m[0] << fmt.space << m[1] << fmt.space << m[2] << fmt.space << m[3]; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x2<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + tmat2x3<T,P> m(a); + + if(io::row_major == fmt.order) + m = transpose(a); + + if(fmt.formatted) + { + os << fmt.newline + << fmt.delim_left << m[0] << fmt.newline + << fmt.space << m[1] << fmt.delim_right; + } + else + { + os << m[0] << fmt.space << m[1]; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x3<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + tmat3x3<T,P> m(a); + + if(io::row_major == fmt.order) + m = transpose(a); + + if(fmt.formatted) + { + os << fmt.newline + << fmt.delim_left << m[0] << fmt.newline + << fmt.space << m[1] << fmt.newline + << fmt.space << m[2] << fmt.delim_right; + } + else + { + os << m[0] << fmt.space << m[1] << fmt.space << m[2]; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat3x4<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + tmat4x3<T,P> m(a); + + if(io::row_major == fmt.order) + m = transpose(a); + + if (fmt.formatted) + { + os << fmt.newline + << fmt.delim_left << m[0] << fmt.newline + << fmt.space << m[1] << fmt.newline + << fmt.space << m[2] << fmt.newline + << fmt.space << m[3] << fmt.delim_right; + } + else + { + os << m[0] << fmt.space << m[1] << fmt.space << m[2] << fmt.space << m[3]; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x2<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + tmat2x4<T,P> m(a); + + if(io::row_major == fmt.order) + m = transpose(a); + + if (fmt.formatted) + { + os << fmt.newline + << fmt.delim_left << m[0] << fmt.newline + << fmt.space << m[1] << fmt.delim_right; + } + else + { + os << m[0] << fmt.space << m[1]; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x3<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + tmat3x4<T,P> m(a); + + if(io::row_major == fmt.order) + m = transpose(a); + + if(fmt.formatted) + { + os << fmt.newline + << fmt.delim_left << m[0] << fmt.newline + << fmt.space << m[1] << fmt.newline + << fmt.space << m[2] << fmt.delim_right; + } + else + { + os << m[0] << fmt.space << m[1] << fmt.space << m[2]; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr> & operator<<(std::basic_ostream<CTy,CTr>& os, tmat4x4<T,P> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + tmat4x4<T,P> m(a); + + if (io::row_major == fmt.order) + m = transpose(a); + + if(fmt.formatted) + { + os << fmt.newline + << fmt.delim_left << m[0] << fmt.newline + << fmt.space << m[1] << fmt.newline + << fmt.space << m[2] << fmt.newline + << fmt.space << m[3] << fmt.delim_right; + } + else + { + os << m[0] << fmt.space << m[1] << fmt.space << m[2] << fmt.space << m[3]; + } + } + + return os; + } + + template <typename CTy, typename CTr, typename T, precision P> + GLM_FUNC_QUALIFIER std::basic_ostream<CTy,CTr>& operator<<( + std::basic_ostream<CTy,CTr> & os, + std::pair<tmat4x4<T,P> const, tmat4x4<T,P> const> const& a) + { + typename std::basic_ostream<CTy,CTr>::sentry const cerberus(os); + + if(cerberus) + { + io::format_punct<CTy> const & fmt(io::get_facet<io::format_punct<CTy> >(os)); + tmat4x4<T,P> ml(a.first); + tmat4x4<T,P> mr(a.second); + + if(io::row_major == fmt.order) + { + ml = transpose(a.first); + mr = transpose(a.second); + } + + if(fmt.formatted) + { + CTy const & l(fmt.delim_left); + CTy const & r(fmt.delim_right); + CTy const & s(fmt.space); + + os << fmt.newline + << l << ml[0] << s << s << l << mr[0] << fmt.newline + << s << ml[1] << s << s << s << mr[1] << fmt.newline + << s << ml[2] << s << s << s << mr[2] << fmt.newline + << s << ml[3] << r << s << s << mr[3] << r; + } + else + { + os << ml << fmt.space << mr; + } + } + + return os; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/log_base.hpp b/extensions/common/glm/gtx/log_base.hpp new file mode 100644 index 0000000000..db8aeb1a51 --- /dev/null +++ b/extensions/common/glm/gtx/log_base.hpp @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_log_base +/// @file glm/gtx/log_base.hpp +/// @date 2008-10-24 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_log_base GLM_GTX_log_base +/// @ingroup gtx +/// +/// @brief Logarithm for any base. base can be a vector or a scalar. +/// +/// <glm/gtx/log_base.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_log_base extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_log_base + /// @{ + + //! Logarithm for any base. + //! From GLM_GTX_log_base. + template <typename genType> + GLM_FUNC_DECL genType log( + genType x, + genType base); + + //! Logarithm for any base. + //! From GLM_GTX_log_base. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<T, P> sign( + vecType<T, P> const & x, + vecType<T, P> const & base); + + /// @} +}//namespace glm + +#include "log_base.inl" diff --git a/extensions/common/glm/gtx/log_base.inl b/extensions/common/glm/gtx/log_base.inl new file mode 100644 index 0000000000..193221600a --- /dev/null +++ b/extensions/common/glm/gtx/log_base.inl @@ -0,0 +1,47 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_log_base +/// @file glm/gtx/log_base.inl +/// @date 2008-10-24 / 2014-11-25 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename genType> + GLM_FUNC_QUALIFIER genType log(genType const & x, genType const & base) + { + assert(x != genType(0)); + return glm::log(x) / glm::log(base); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> log(vecType<T, P> const & x, vecType<T, P> const & base) + { + return glm::log(x) / glm::log(base); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/matrix_cross_product.hpp b/extensions/common/glm/gtx/matrix_cross_product.hpp new file mode 100644 index 0000000000..0b9063e934 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_cross_product.hpp @@ -0,0 +1,72 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_cross_product +/// @file glm/gtx/matrix_cross_product.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_matrix_cross_product GLM_GTX_matrix_cross_product +/// @ingroup gtx +/// +/// @brief Build cross product matrices +/// +/// <glm/gtx/matrix_cross_product.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_matrix_cross_product extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_cross_product + /// @{ + + //! Build a cross product matrix. + //! From GLM_GTX_matrix_cross_product extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> matrixCross3( + tvec3<T, P> const & x); + + //! Build a cross product matrix. + //! From GLM_GTX_matrix_cross_product extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> matrixCross4( + tvec3<T, P> const & x); + + /// @} +}//namespace glm + +#include "matrix_cross_product.inl" diff --git a/extensions/common/glm/gtx/matrix_cross_product.inl b/extensions/common/glm/gtx/matrix_cross_product.inl new file mode 100644 index 0000000000..89ba5909f8 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_cross_product.inl @@ -0,0 +1,67 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_cross_product +/// @file glm/gtx/matrix_cross_product.inl +/// @date 2005-12-21 / 2005-12-21 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> matrixCross3 + ( + tvec3<T, P> const & x + ) + { + tmat3x3<T, P> Result(T(0)); + Result[0][1] = x.z; + Result[1][0] = -x.z; + Result[0][2] = -x.y; + Result[2][0] = x.y; + Result[1][2] = x.x; + Result[2][1] = -x.x; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> matrixCross4 + ( + tvec3<T, P> const & x + ) + { + tmat4x4<T, P> Result(T(0)); + Result[0][1] = x.z; + Result[1][0] = -x.z; + Result[0][2] = -x.y; + Result[2][0] = x.y; + Result[1][2] = x.x; + Result[2][1] = -x.x; + return Result; + } + +}//namespace glm diff --git a/extensions/common/glm/gtx/matrix_decompose.hpp b/extensions/common/glm/gtx/matrix_decompose.hpp new file mode 100644 index 0000000000..17180e5777 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_decompose.hpp @@ -0,0 +1,70 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_decompose +/// @file glm/gtx/matrix_decompose.hpp +/// @date 2014-08-29 / 2014-08-29 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_decompose GLM_GTX_matrix_decompose +/// @ingroup gtx +/// +/// @brief Decomposes a model matrix to translations, rotation and scale components +/// +/// <glm/gtx/decomposition.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../mat4x4.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtc/matrix_transform.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_matrix_decompose extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_decompose + /// @{ + + /// Decomposes a model matrix to translations, rotation and scale components + /// @see gtx_matrix_decompose + template <typename T, precision P> + GLM_FUNC_DECL bool decompose( + tmat4x4<T, P> const & modelMatrix, + tvec3<T, P> & scale, tquat<T, P> & orientation, tvec3<T, P> & translation, tvec3<T, P> & skew, tvec4<T, P> & perspective); + + /// @} +}//namespace glm + +#include "matrix_decompose.inl" diff --git a/extensions/common/glm/gtx/matrix_decompose.inl b/extensions/common/glm/gtx/matrix_decompose.inl new file mode 100644 index 0000000000..9bd12861f3 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_decompose.inl @@ -0,0 +1,231 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_decompose +/// @file glm/gtx/matrix_decompose.inl +/// @date 2014-08-29 / 2014-08-29 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + /// Make a linear combination of two vectors and return the result. + // result = (a * ascl) + (b * bscl) + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> combine( + tvec3<T, P> const & a, + tvec3<T, P> const & b, + T ascl, T bscl) + { + return (a * ascl) + (b * bscl); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER void v3Scale(tvec3<T, P> & v, T desiredLength) + { + T len = glm::length(v); + if(len != 0) + { + T l = desiredLength / len; + v[0] *= l; + v[1] *= l; + v[2] *= l; + } + } + + /** + * Matrix decompose + * http://www.opensource.apple.com/source/WebCore/WebCore-514/platform/graphics/transforms/TransformationMatrix.cpp + * Decomposes the mode matrix to translations,rotation scale components + * + */ + + template <typename T, precision P> + GLM_FUNC_QUALIFIER bool decompose(tmat4x4<T, P> const & ModelMatrix, tvec3<T, P> & Scale, tquat<T, P> & Orientation, tvec3<T, P> & Translation, tvec3<T, P> & Skew, tvec4<T, P> & Perspective) + { + tmat4x4<T, P> LocalMatrix(ModelMatrix); + + // Normalize the matrix. + if(LocalMatrix[3][3] == static_cast<T>(0)) + return false; + + for(length_t i = 0; i < 4; ++i) + for(length_t j = 0; j < 4; ++j) + LocalMatrix[i][j] /= LocalMatrix[3][3]; + + // perspectiveMatrix is used to solve for perspective, but it also provides + // an easy way to test for singularity of the upper 3x3 component. + tmat4x4<T, P> PerspectiveMatrix(LocalMatrix); + + for(length_t i = 0; i < 3; i++) + PerspectiveMatrix[i][3] = 0; + PerspectiveMatrix[3][3] = 1; + + /// TODO: Fixme! + if(determinant(PerspectiveMatrix) == static_cast<T>(0)) + return false; + + // First, isolate perspective. This is the messiest. + if(LocalMatrix[0][3] != 0 || LocalMatrix[1][3] != 0 || LocalMatrix[2][3] != 0) + { + // rightHandSide is the right hand side of the equation. + tvec4<T, P> RightHandSide; + RightHandSide[0] = LocalMatrix[0][3]; + RightHandSide[1] = LocalMatrix[1][3]; + RightHandSide[2] = LocalMatrix[2][3]; + RightHandSide[3] = LocalMatrix[3][3]; + + // Solve the equation by inverting PerspectiveMatrix and multiplying + // rightHandSide by the inverse. (This is the easiest way, not + // necessarily the best.) + tmat4x4<T, P> InversePerspectiveMatrix = glm::inverse(PerspectiveMatrix);// inverse(PerspectiveMatrix, inversePerspectiveMatrix); + tmat4x4<T, P> TransposedInversePerspectiveMatrix = glm::transpose(InversePerspectiveMatrix);// transposeMatrix4(inversePerspectiveMatrix, transposedInversePerspectiveMatrix); + + Perspective = TransposedInversePerspectiveMatrix * RightHandSide; + // v4MulPointByMatrix(rightHandSide, transposedInversePerspectiveMatrix, perspectivePoint); + + // Clear the perspective partition + LocalMatrix[0][3] = LocalMatrix[1][3] = LocalMatrix[2][3] = 0; + LocalMatrix[3][3] = 1; + } + else + { + // No perspective. + Perspective = tvec4<T, P>(0, 0, 0, 1); + } + + // Next take care of translation (easy). + Translation = tvec3<T, P>(LocalMatrix[3]); + LocalMatrix[3] = tvec4<T, P>(0, 0, 0, LocalMatrix[3].w); + + tvec3<T, P> Row[3], Pdum3; + + // Now get scale and shear. + for(length_t i = 0; i < 3; ++i) + for(int j = 0; j < 3; ++j) + Row[i][j] = LocalMatrix[i][j]; + + // Compute X scale factor and normalize first row. + Scale.x = length(Row[0]);// v3Length(Row[0]); + + v3Scale(Row[0], static_cast<T>(1)); + + // Compute XY shear factor and make 2nd row orthogonal to 1st. + Skew.z = dot(Row[0], Row[1]); + Row[1] = combine(Row[1], Row[0], static_cast<T>(1), -Skew.z); + + // Now, compute Y scale and normalize 2nd row. + Scale.y = length(Row[1]); + v3Scale(Row[1], static_cast<T>(1)); + Skew.z /= Scale.y; + + // Compute XZ and YZ shears, orthogonalize 3rd row. + Skew.y = glm::dot(Row[0], Row[2]); + Row[2] = combine(Row[2], Row[0], static_cast<T>(1), -Skew.y); + Skew.x = glm::dot(Row[1], Row[2]); + Row[2] = combine(Row[2], Row[1], static_cast<T>(1), -Skew.x); + + // Next, get Z scale and normalize 3rd row. + Scale.z = length(Row[2]); + v3Scale(Row[2], static_cast<T>(1)); + Skew.y /= Scale.z; + Skew.x /= Scale.z; + + // At this point, the matrix (in rows[]) is orthonormal. + // Check for a coordinate system flip. If the determinant + // is -1, then negate the matrix and the scaling factors. + Pdum3 = cross(Row[1], Row[2]); // v3Cross(row[1], row[2], Pdum3); + if(dot(Row[0], Pdum3) < 0) + { + for(length_t i = 0; i < 3; i++) + { + Scale.x *= static_cast<T>(-1); + Row[i] *= static_cast<T>(-1); + } + } + + // Now, get the rotations out, as described in the gem. + + // FIXME - Add the ability to return either quaternions (which are + // easier to recompose with) or Euler angles (rx, ry, rz), which + // are easier for authors to deal with. The latter will only be useful + // when we fix https://bugs.webkit.org/show_bug.cgi?id=23799, so I + // will leave the Euler angle code here for now. + + // ret.rotateY = asin(-Row[0][2]); + // if (cos(ret.rotateY) != 0) { + // ret.rotateX = atan2(Row[1][2], Row[2][2]); + // ret.rotateZ = atan2(Row[0][1], Row[0][0]); + // } else { + // ret.rotateX = atan2(-Row[2][0], Row[1][1]); + // ret.rotateZ = 0; + // } + + T s, t, x, y, z, w; + + t = Row[0][0] + Row[1][1] + Row[2][2] + 1.0; + + if(t > 1e-4) + { + s = 0.5 / sqrt(t); + w = 0.25 / s; + x = (Row[2][1] - Row[1][2]) * s; + y = (Row[0][2] - Row[2][0]) * s; + z = (Row[1][0] - Row[0][1]) * s; + } + else if(Row[0][0] > Row[1][1] && Row[0][0] > Row[2][2]) + { + s = sqrt (1.0 + Row[0][0] - Row[1][1] - Row[2][2]) * 2.0; // S=4*qx + x = 0.25 * s; + y = (Row[0][1] + Row[1][0]) / s; + z = (Row[0][2] + Row[2][0]) / s; + w = (Row[2][1] - Row[1][2]) / s; + } + else if(Row[1][1] > Row[2][2]) + { + s = sqrt (1.0 + Row[1][1] - Row[0][0] - Row[2][2]) * 2.0; // S=4*qy + x = (Row[0][1] + Row[1][0]) / s; + y = 0.25 * s; + z = (Row[1][2] + Row[2][1]) / s; + w = (Row[0][2] - Row[2][0]) / s; + } + else + { + s = sqrt(1.0 + Row[2][2] - Row[0][0] - Row[1][1]) * 2.0; // S=4*qz + x = (Row[0][2] + Row[2][0]) / s; + y = (Row[1][2] + Row[2][1]) / s; + z = 0.25 * s; + w = (Row[1][0] - Row[0][1]) / s; + } + + Orientation.x = x; + Orientation.y = y; + Orientation.z = z; + Orientation.w = w; + + return true; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/matrix_interpolation.hpp b/extensions/common/glm/gtx/matrix_interpolation.hpp new file mode 100644 index 0000000000..9c833b8a50 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_interpolation.hpp @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_interpolation +/// @file glm/gtx/matrix_interpolation.hpp +/// @date 2011-03-05 / 2011-06-07 +/// @author Ghenadii Ursachi (the.asteroth@gmail.com) +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_interpolation GLM_GTX_matrix_interpolation +/// @ingroup gtx +/// +/// @brief Allows to directly interpolate two exiciting matrices. +/// +/// <glm/gtx/matrix_interpolation.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_matrix_interpolation extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_interpolation + /// @{ + + /// Get the axis and angle of the rotation from a matrix. + /// From GLM_GTX_matrix_interpolation extension. + template <typename T, precision P> + GLM_FUNC_DECL void axisAngle( + tmat4x4<T, P> const & mat, + tvec3<T, P> & axis, + T & angle); + + /// Build a matrix from axis and angle. + /// From GLM_GTX_matrix_interpolation extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> axisAngleMatrix( + tvec3<T, P> const & axis, + T const angle); + + /// Extracts the rotation part of a matrix. + /// From GLM_GTX_matrix_interpolation extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> extractMatrixRotation( + tmat4x4<T, P> const & mat); + + /// Build a interpolation of 4 * 4 matrixes. + /// From GLM_GTX_matrix_interpolation extension. + /// Warning! works only with rotation and/or translation matrixes, scale will generate unexpected results. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> interpolate( + tmat4x4<T, P> const & m1, + tmat4x4<T, P> const & m2, + T const delta); + + /// @} +}//namespace glm + +#include "matrix_interpolation.inl" diff --git a/extensions/common/glm/gtx/matrix_interpolation.inl b/extensions/common/glm/gtx/matrix_interpolation.inl new file mode 100644 index 0000000000..57680024b0 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_interpolation.inl @@ -0,0 +1,163 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_interpolation +/// @file glm/gtx/matrix_interpolation.hpp +/// @date 2011-03-05 / 2011-03-05 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER void axisAngle + ( + tmat4x4<T, P> const & mat, + tvec3<T, P> & axis, + T & angle + ) + { + T epsilon = (T)0.01; + T epsilon2 = (T)0.1; + + if((abs(mat[1][0] - mat[0][1]) < epsilon) && (abs(mat[2][0] - mat[0][2]) < epsilon) && (abs(mat[2][1] - mat[1][2]) < epsilon)) + { + if ((abs(mat[1][0] + mat[0][1]) < epsilon2) && (abs(mat[2][0] + mat[0][2]) < epsilon2) && (abs(mat[2][1] + mat[1][2]) < epsilon2) && (abs(mat[0][0] + mat[1][1] + mat[2][2] - (T)3.0) < epsilon2)) + { + angle = (T)0.0; + axis.x = (T)1.0; + axis.y = (T)0.0; + axis.z = (T)0.0; + return; + } + angle = static_cast<T>(3.1415926535897932384626433832795); + T xx = (mat[0][0] + (T)1.0) / (T)2.0; + T yy = (mat[1][1] + (T)1.0) / (T)2.0; + T zz = (mat[2][2] + (T)1.0) / (T)2.0; + T xy = (mat[1][0] + mat[0][1]) / (T)4.0; + T xz = (mat[2][0] + mat[0][2]) / (T)4.0; + T yz = (mat[2][1] + mat[1][2]) / (T)4.0; + if((xx > yy) && (xx > zz)) + { + if (xx < epsilon) { + axis.x = (T)0.0; + axis.y = (T)0.7071; + axis.z = (T)0.7071; + } else { + axis.x = sqrt(xx); + axis.y = xy / axis.x; + axis.z = xz / axis.x; + } + } + else if (yy > zz) + { + if (yy < epsilon) { + axis.x = (T)0.7071; + axis.y = (T)0.0; + axis.z = (T)0.7071; + } else { + axis.y = sqrt(yy); + axis.x = xy / axis.y; + axis.z = yz / axis.y; + } + } + else + { + if (zz < epsilon) { + axis.x = (T)0.7071; + axis.y = (T)0.7071; + axis.z = (T)0.0; + } else { + axis.z = sqrt(zz); + axis.x = xz / axis.z; + axis.y = yz / axis.z; + } + } + return; + } + T s = sqrt((mat[2][1] - mat[1][2]) * (mat[2][1] - mat[1][2]) + (mat[2][0] - mat[0][2]) * (mat[2][0] - mat[0][2]) + (mat[1][0] - mat[0][1]) * (mat[1][0] - mat[0][1])); + if (glm::abs(s) < T(0.001)) + s = (T)1.0; + angle = acos((mat[0][0] + mat[1][1] + mat[2][2] - (T)1.0) / (T)2.0); + axis.x = (mat[1][2] - mat[2][1]) / s; + axis.y = (mat[2][0] - mat[0][2]) / s; + axis.z = (mat[0][1] - mat[1][0]) / s; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> axisAngleMatrix + ( + tvec3<T, P> const & axis, + T const angle + ) + { + T c = cos(angle); + T s = sin(angle); + T t = static_cast<T>(1) - c; + tvec3<T, P> n = normalize(axis); + + return tmat4x4<T, P>( + t * n.x * n.x + c, t * n.x * n.y + n.z * s, t * n.x * n.z - n.y * s, T(0), + t * n.x * n.y - n.z * s, t * n.y * n.y + c, t * n.y * n.z + n.x * s, T(0), + t * n.x * n.z + n.y * s, t * n.y * n.z - n.x * s, t * n.z * n.z + c, T(0), + T(0), T(0), T(0), T(1) + ); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> extractMatrixRotation + ( + tmat4x4<T, P> const & mat + ) + { + return tmat4x4<T, P>( + mat[0][0], mat[0][1], mat[0][2], 0.0, + mat[1][0], mat[1][1], mat[1][2], 0.0, + mat[2][0], mat[2][1], mat[2][2], 0.0, + 0.0, 0.0, 0.0, 1.0 + ); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> interpolate + ( + tmat4x4<T, P> const & m1, + tmat4x4<T, P> const & m2, + T const delta + ) + { + tmat4x4<T, P> m1rot = extractMatrixRotation(m1); + tmat4x4<T, P> dltRotation = m2 * transpose(m1rot); + tvec3<T, P> dltAxis; + T dltAngle; + axisAngle(dltRotation, dltAxis, dltAngle); + tmat4x4<T, P> out = axisAngleMatrix(dltAxis, dltAngle * delta) * m1rot; + out[3][0] = m1[3][0] + delta * (m2[3][0] - m1[3][0]); + out[3][1] = m1[3][1] + delta * (m2[3][1] - m1[3][1]); + out[3][2] = m1[3][2] + delta * (m2[3][2] - m1[3][2]); + return out; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/matrix_major_storage.hpp b/extensions/common/glm/gtx/matrix_major_storage.hpp new file mode 100644 index 0000000000..9c4062d46c --- /dev/null +++ b/extensions/common/glm/gtx/matrix_major_storage.hpp @@ -0,0 +1,144 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_major_storage +/// @file glm/gtx/matrix_major_storage.hpp +/// @date 2006-04-19 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_matrix_major_storage GLM_GTX_matrix_major_storage +/// @ingroup gtx +/// +/// @brief Build matrices with specific matrix order, row or column +/// +/// <glm/gtx/matrix_major_storage.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_matrix_major_storage extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_major_storage + /// @{ + + //! Build a row major matrix from row vectors. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> rowMajor2( + tvec2<T, P> const & v1, + tvec2<T, P> const & v2); + + //! Build a row major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> rowMajor2( + tmat2x2<T, P> const & m); + + //! Build a row major matrix from row vectors. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> rowMajor3( + tvec3<T, P> const & v1, + tvec3<T, P> const & v2, + tvec3<T, P> const & v3); + + //! Build a row major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> rowMajor3( + tmat3x3<T, P> const & m); + + //! Build a row major matrix from row vectors. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> rowMajor4( + tvec4<T, P> const & v1, + tvec4<T, P> const & v2, + tvec4<T, P> const & v3, + tvec4<T, P> const & v4); + + //! Build a row major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> rowMajor4( + tmat4x4<T, P> const & m); + + //! Build a column major matrix from column vectors. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> colMajor2( + tvec2<T, P> const & v1, + tvec2<T, P> const & v2); + + //! Build a column major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> colMajor2( + tmat2x2<T, P> const & m); + + //! Build a column major matrix from column vectors. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> colMajor3( + tvec3<T, P> const & v1, + tvec3<T, P> const & v2, + tvec3<T, P> const & v3); + + //! Build a column major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> colMajor3( + tmat3x3<T, P> const & m); + + //! Build a column major matrix from column vectors. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> colMajor4( + tvec4<T, P> const & v1, + tvec4<T, P> const & v2, + tvec4<T, P> const & v3, + tvec4<T, P> const & v4); + + //! Build a column major matrix from other matrix. + //! From GLM_GTX_matrix_major_storage extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> colMajor4( + tmat4x4<T, P> const & m); + + /// @} +}//namespace glm + +#include "matrix_major_storage.inl" diff --git a/extensions/common/glm/gtx/matrix_major_storage.inl b/extensions/common/glm/gtx/matrix_major_storage.inl new file mode 100644 index 0000000000..354dc1de97 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_major_storage.inl @@ -0,0 +1,196 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_major_storage +/// @file glm/gtx/matrix_major_storage.hpp +/// @date 2006-04-19 / 2014-11-25 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> rowMajor2 + ( + tvec2<T, P> const & v1, + tvec2<T, P> const & v2 + ) + { + tmat2x2<T, P> Result; + Result[0][0] = v1.x; + Result[1][0] = v1.y; + Result[0][1] = v2.x; + Result[1][1] = v2.y; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> rowMajor2( + const tmat2x2<T, P>& m) + { + tmat2x2<T, P> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> rowMajor3( + const tvec3<T, P>& v1, + const tvec3<T, P>& v2, + const tvec3<T, P>& v3) + { + tmat3x3<T, P> Result; + Result[0][0] = v1.x; + Result[1][0] = v1.y; + Result[2][0] = v1.z; + Result[0][1] = v2.x; + Result[1][1] = v2.y; + Result[2][1] = v2.z; + Result[0][2] = v3.x; + Result[1][2] = v3.y; + Result[2][2] = v3.z; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> rowMajor3( + const tmat3x3<T, P>& m) + { + tmat3x3<T, P> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> rowMajor4( + const tvec4<T, P>& v1, + const tvec4<T, P>& v2, + const tvec4<T, P>& v3, + const tvec4<T, P>& v4) + { + tmat4x4<T, P> Result; + Result[0][0] = v1.x; + Result[1][0] = v1.y; + Result[2][0] = v1.z; + Result[3][0] = v1.w; + Result[0][1] = v2.x; + Result[1][1] = v2.y; + Result[2][1] = v2.z; + Result[3][1] = v2.w; + Result[0][2] = v3.x; + Result[1][2] = v3.y; + Result[2][2] = v3.z; + Result[3][2] = v3.w; + Result[0][3] = v4.x; + Result[1][3] = v4.y; + Result[2][3] = v4.z; + Result[3][3] = v4.w; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> rowMajor4( + const tmat4x4<T, P>& m) + { + tmat4x4<T, P> Result; + Result[0][0] = m[0][0]; + Result[0][1] = m[1][0]; + Result[0][2] = m[2][0]; + Result[0][3] = m[3][0]; + Result[1][0] = m[0][1]; + Result[1][1] = m[1][1]; + Result[1][2] = m[2][1]; + Result[1][3] = m[3][1]; + Result[2][0] = m[0][2]; + Result[2][1] = m[1][2]; + Result[2][2] = m[2][2]; + Result[2][3] = m[3][2]; + Result[3][0] = m[0][3]; + Result[3][1] = m[1][3]; + Result[3][2] = m[2][3]; + Result[3][3] = m[3][3]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> colMajor2( + const tvec2<T, P>& v1, + const tvec2<T, P>& v2) + { + return tmat2x2<T, P>(v1, v2); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> colMajor2( + const tmat2x2<T, P>& m) + { + return tmat2x2<T, P>(m); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> colMajor3( + const tvec3<T, P>& v1, + const tvec3<T, P>& v2, + const tvec3<T, P>& v3) + { + return tmat3x3<T, P>(v1, v2, v3); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> colMajor3( + const tmat3x3<T, P>& m) + { + return tmat3x3<T, P>(m); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> colMajor4( + const tvec4<T, P>& v1, + const tvec4<T, P>& v2, + const tvec4<T, P>& v3, + const tvec4<T, P>& v4) + { + return tmat4x4<T, P>(v1, v2, v3, v4); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> colMajor4( + const tmat4x4<T, P>& m) + { + return tmat4x4<T, P>(m); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/matrix_operation.hpp b/extensions/common/glm/gtx/matrix_operation.hpp new file mode 100644 index 0000000000..ebd4f07ee3 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_operation.hpp @@ -0,0 +1,113 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_operation +/// @file glm/gtx/matrix_operation.hpp +/// @date 2009-08-29 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_operation GLM_GTX_matrix_operation +/// @ingroup gtx +/// +/// @brief Build diagonal matrices from vectors. +/// +/// <glm/gtx/matrix_operation.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_matrix_operation extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_operation + /// @{ + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat2x2<T, P> diagonal2x2( + tvec2<T, P> const & v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat2x3<T, P> diagonal2x3( + tvec2<T, P> const & v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat2x4<T, P> diagonal2x4( + tvec2<T, P> const & v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat3x2<T, P> diagonal3x2( + tvec2<T, P> const & v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> diagonal3x3( + tvec3<T, P> const & v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat3x4<T, P> diagonal3x4( + tvec3<T, P> const & v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x2<T, P> diagonal4x2( + tvec2<T, P> const & v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x3<T, P> diagonal4x3( + tvec3<T, P> const & v); + + //! Build a diagonal matrix. + //! From GLM_GTX_matrix_operation extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> diagonal4x4( + tvec4<T, P> const & v); + + /// @} +}//namespace glm + +#include "matrix_operation.inl" diff --git a/extensions/common/glm/gtx/matrix_operation.inl b/extensions/common/glm/gtx/matrix_operation.inl new file mode 100644 index 0000000000..591aac7ff8 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_operation.inl @@ -0,0 +1,147 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_operation +/// @file glm/gtx/matrix_operation.inl +/// @date 2009-08-29 / 2009-08-29 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x2<T, P> diagonal2x2 + ( + tvec2<T, P> const & v + ) + { + tmat2x2<T, P> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x3<T, P> diagonal2x3 + ( + tvec2<T, P> const & v + ) + { + tmat2x3<T, P> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat2x4<T, P> diagonal2x4 + ( + tvec2<T, P> const & v + ) + { + tmat2x4<T, P> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x2<T, P> diagonal3x2 + ( + tvec2<T, P> const & v + ) + { + tmat3x2<T, P> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> diagonal3x3 + ( + tvec3<T, P> const & v + ) + { + tmat3x3<T, P> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x4<T, P> diagonal3x4 + ( + tvec3<T, P> const & v + ) + { + tmat3x4<T, P> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> diagonal4x4 + ( + tvec4<T, P> const & v + ) + { + tmat4x4<T, P> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + Result[3][3] = v[3]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x3<T, P> diagonal4x3 + ( + tvec3<T, P> const & v + ) + { + tmat4x3<T, P> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + Result[2][2] = v[2]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x2<T, P> diagonal4x2 + ( + tvec2<T, P> const & v + ) + { + tmat4x2<T, P> Result(static_cast<T>(1)); + Result[0][0] = v[0]; + Result[1][1] = v[1]; + return Result; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/matrix_query.hpp b/extensions/common/glm/gtx/matrix_query.hpp new file mode 100644 index 0000000000..1c145fc5ad --- /dev/null +++ b/extensions/common/glm/gtx/matrix_query.hpp @@ -0,0 +1,102 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_query +/// @file glm/gtx/matrix_query.hpp +/// @date 2007-03-05 / 2011-08-28 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_vector_query (dependence) +/// +/// @defgroup gtx_matrix_query GLM_GTX_matrix_query +/// @ingroup gtx +/// +/// @brief Query to evaluate matrix properties +/// +/// <glm/gtx/matrix_query.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/vector_query.hpp" +#include <limits> + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_matrix_query extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_query + /// @{ + + /// Return whether a matrix a null matrix. + /// From GLM_GTX_matrix_query extension. + template<typename T, precision P> + GLM_FUNC_DECL bool isNull(tmat2x2<T, P> const & m, T const & epsilon); + + /// Return whether a matrix a null matrix. + /// From GLM_GTX_matrix_query extension. + template<typename T, precision P> + GLM_FUNC_DECL bool isNull(tmat3x3<T, P> const & m, T const & epsilon); + + /// Return whether a matrix is a null matrix. + /// From GLM_GTX_matrix_query extension. + template<typename T, precision P> + GLM_FUNC_DECL bool isNull(tmat4x4<T, P> const & m, T const & epsilon); + + /// Return whether a matrix is an identity matrix. + /// From GLM_GTX_matrix_query extension. + template<typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_DECL bool isIdentity(matType<T, P> const & m, T const & epsilon); + + /// Return whether a matrix is a normalized matrix. + /// From GLM_GTX_matrix_query extension. + template<typename T, precision P> + GLM_FUNC_DECL bool isNormalized(tmat2x2<T, P> const & m, T const & epsilon); + + /// Return whether a matrix is a normalized matrix. + /// From GLM_GTX_matrix_query extension. + template<typename T, precision P> + GLM_FUNC_DECL bool isNormalized(tmat3x3<T, P> const & m, T const & epsilon); + + /// Return whether a matrix is a normalized matrix. + /// From GLM_GTX_matrix_query extension. + template<typename T, precision P> + GLM_FUNC_DECL bool isNormalized(tmat4x4<T, P> const & m, T const & epsilon); + + /// Return whether a matrix is an orthonormalized matrix. + /// From GLM_GTX_matrix_query extension. + template<typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_DECL bool isOrthogonal(matType<T, P> const & m, T const & epsilon); + + /// @} +}//namespace glm + +#include "matrix_query.inl" diff --git a/extensions/common/glm/gtx/matrix_query.inl b/extensions/common/glm/gtx/matrix_query.inl new file mode 100644 index 0000000000..621a9b9ab6 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_query.inl @@ -0,0 +1,143 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_query +/// @file glm/gtx/matrix_query.inl +/// @date 2007-03-05 / 2007-03-05 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template<typename T, precision P> + GLM_FUNC_QUALIFIER bool isNull(tmat2x2<T, P> const & m, T const & epsilon) + { + bool result = true; + for(detail::component_count_t i = 0; result && i < 2 ; ++i) + result = isNull(m[i], epsilon); + return result; + } + + template<typename T, precision P> + GLM_FUNC_QUALIFIER bool isNull(tmat3x3<T, P> const & m, T const & epsilon) + { + bool result = true; + for(detail::component_count_t i = 0; result && i < 3 ; ++i) + result = isNull(m[i], epsilon); + return result; + } + + template<typename T, precision P> + GLM_FUNC_QUALIFIER bool isNull(tmat4x4<T, P> const & m, T const & epsilon) + { + bool result = true; + for(detail::component_count_t i = 0; result && i < 4 ; ++i) + result = isNull(m[i], epsilon); + return result; + } + + template<typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_QUALIFIER bool isIdentity(matType<T, P> const & m, T const & epsilon) + { + bool result = true; + for(detail::component_count_t i(0); result && i < detail::component_count(m[0]); ++i) + { + for(detail::component_count_t j(0); result && j < i ; ++j) + result = abs(m[i][j]) <= epsilon; + if(result) + result = abs(m[i][i] - 1) <= epsilon; + for(detail::component_count_t j(i + 1); result && j < detail::component_count(m); ++j) + result = abs(m[i][j]) <= epsilon; + } + return result; + } + + template<typename T, precision P> + GLM_FUNC_QUALIFIER bool isNormalized(tmat2x2<T, P> const & m, T const & epsilon) + { + bool result(true); + for(detail::component_count_t i(0); result && i < detail::component_count(m); ++i) + result = isNormalized(m[i], epsilon); + for(detail::component_count_t i(0); result && i < detail::component_count(m); ++i) + { + typename tmat2x2<T, P>::col_type v; + for(detail::component_count_t j(0); j < detail::component_count(m); ++j) + v[j] = m[j][i]; + result = isNormalized(v, epsilon); + } + return result; + } + + template<typename T, precision P> + GLM_FUNC_QUALIFIER bool isNormalized(tmat3x3<T, P> const & m, T const & epsilon) + { + bool result(true); + for(detail::component_count_t i(0); result && i < detail::component_count(m); ++i) + result = isNormalized(m[i], epsilon); + for(detail::component_count_t i(0); result && i < detail::component_count(m); ++i) + { + typename tmat3x3<T, P>::col_type v; + for(detail::component_count_t j(0); j < detail::component_count(m); ++j) + v[j] = m[j][i]; + result = isNormalized(v, epsilon); + } + return result; + } + + template<typename T, precision P> + GLM_FUNC_QUALIFIER bool isNormalized(tmat4x4<T, P> const & m, T const & epsilon) + { + bool result(true); + for(detail::component_count_t i(0); result && i < detail::component_count(m); ++i) + result = isNormalized(m[i], epsilon); + for(detail::component_count_t i(0); result && i < detail::component_count(m); ++i) + { + typename tmat4x4<T, P>::col_type v; + for(detail::component_count_t j(0); j < detail::component_count(m); ++j) + v[j] = m[j][i]; + result = isNormalized(v, epsilon); + } + return result; + } + + template<typename T, precision P, template <typename, precision> class matType> + GLM_FUNC_QUALIFIER bool isOrthogonal(matType<T, P> const & m, T const & epsilon) + { + bool result(true); + for(detail::component_count_t i(0); result && i < detail::component_count(m) - 1; ++i) + for(detail::component_count_t j(i + 1); result && j < detail::component_count(m); ++j) + result = areOrthogonal(m[i], m[j], epsilon); + + if(result) + { + matType<T, P> tmp = transpose(m); + for(detail::component_count_t i(0); result && i < detail::component_count(m) - 1 ; ++i) + for(detail::component_count_t j(i + 1); result && j < detail::component_count(m); ++j) + result = areOrthogonal(tmp[i], tmp[j], epsilon); + } + return result; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/matrix_transform_2d.hpp b/extensions/common/glm/gtx/matrix_transform_2d.hpp new file mode 100644 index 0000000000..d30622fcd0 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_transform_2d.hpp @@ -0,0 +1,106 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_transform_2d +/// @file glm/gtx/matrix_transform_2d.hpp +/// @date 2014-02-20 +/// @author Miguel Ángel Pérez Martínez +/// +/// @see core (dependence) +/// +/// @defgroup gtx_matrix_transform_2d GLM_GTX_matrix_transform_2d +/// @ingroup gtx +/// +/// @brief Defines functions that generate common 2d transformation matrices. +/// +/// <glm/gtx/matrix_transform_2d.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../mat3x3.hpp" +#include "../vec2.hpp" + + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_matrix_transform_2d extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_matrix_transform_2d + /// @{ + + /// Builds a translation 3 * 3 matrix created from a vector of 2 components. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param v Coordinates of a translation vector. + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> translate( + tmat3x3<T, P> const & m, + tvec2<T, P> const & v); + + /// Builds a rotation 3 * 3 matrix created from an angle. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param angle Rotation angle expressed in radians if GLM_FORCE_RADIANS is defined or degrees otherwise. + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> rotate( + tmat3x3<T, P> const & m, + T angle); + + /// Builds a scale 3 * 3 matrix created from a vector of 2 components. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param v Coordinates of a scale vector. + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> scale( + tmat3x3<T, P> const & m, + tvec2<T, P> const & v); + + /// Builds an horizontal (parallel to the x axis) shear 3 * 3 matrix. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param y Shear factor. + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> shearX( + tmat3x3<T, P> const & m, + T y); + + /// Builds a vertical (parallel to the y axis) shear 3 * 3 matrix. + /// + /// @param m Input matrix multiplied by this translation matrix. + /// @param x Shear factor. + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> shearY( + tmat3x3<T, P> const & m, + T x); + + /// @} +}//namespace glm + +#include "matrix_transform_2d.inl" diff --git a/extensions/common/glm/gtx/matrix_transform_2d.inl b/extensions/common/glm/gtx/matrix_transform_2d.inl new file mode 100644 index 0000000000..976c42a460 --- /dev/null +++ b/extensions/common/glm/gtx/matrix_transform_2d.inl @@ -0,0 +1,97 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_matrix_transform_2d +/// @file glm/gtc/matrix_transform_2d.inl +/// @date 2014-02-20 +/// @author Miguel Ángel Pérez Martínez +/////////////////////////////////////////////////////////////////////////////////// + +#include "../trigonometric.hpp" + +namespace glm +{ + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> translate( + tmat3x3<T, P> const & m, + tvec2<T, P> const & v) + { + tmat3x3<T, P> Result(m); + Result[2] = m[0] * v[0] + m[1] * v[1] + m[2]; + return Result; + } + + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> rotate( + tmat3x3<T, P> const & m, + T angle) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + + tmat3x3<T, P> Result(uninitialize); + Result[0] = m[0] * c + m[1] * s; + Result[1] = m[0] * -s + m[1] * c; + Result[2] = m[2]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> scale( + tmat3x3<T, P> const & m, + tvec2<T, P> const & v) + { + tmat3x3<T, P> Result(uninitialize); + Result[0] = m[0] * v[0]; + Result[1] = m[1] * v[1]; + Result[2] = m[2]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> shearX( + tmat3x3<T, P> const & m, + T y) + { + tmat3x3<T, P> Result(1); + Result[0][1] = y; + return m * Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> shearY( + tmat3x3<T, P> const & m, + T x) + { + tmat3x3<T, P> Result(1); + Result[1][0] = x; + return m * Result; + } + +}//namespace glm diff --git a/extensions/common/glm/gtx/mixed_product.hpp b/extensions/common/glm/gtx/mixed_product.hpp new file mode 100644 index 0000000000..53b982d161 --- /dev/null +++ b/extensions/common/glm/gtx/mixed_product.hpp @@ -0,0 +1,66 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_mixed_product +/// @file glm/gtx/mixed_product.hpp +/// @date 2007-04-03 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_mixed_product GLM_GTX_mixed_producte +/// @ingroup gtx +/// +/// @brief Mixed product of 3 vectors. +/// +/// <glm/gtx/mixed_product.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_mixed_product extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_mixed_product + /// @{ + + /// @brief Mixed product of 3 vectors (from GLM_GTX_mixed_product extension) + template <typename T, precision P> + GLM_FUNC_DECL T mixedProduct( + tvec3<T, P> const & v1, + tvec3<T, P> const & v2, + tvec3<T, P> const & v3); + + /// @} +}// namespace glm + +#include "mixed_product.inl" diff --git a/extensions/common/glm/gtx/mixed_product.inl b/extensions/common/glm/gtx/mixed_product.inl new file mode 100644 index 0000000000..6305793725 --- /dev/null +++ b/extensions/common/glm/gtx/mixed_product.inl @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_mixed_product +/// @file glm/gtx/mixed_product.inl +/// @date 2007-04-03 / 2008-09-17 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER T mixedProduct + ( + tvec3<T, P> const & v1, + tvec3<T, P> const & v2, + tvec3<T, P> const & v3 + ) + { + return dot(cross(v1, v2), v3); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/multiple.hpp b/extensions/common/glm/gtx/multiple.hpp new file mode 100644 index 0000000000..4fd94d5632 --- /dev/null +++ b/extensions/common/glm/gtx/multiple.hpp @@ -0,0 +1,106 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_multiple +/// @file glm/gtx/multiple.hpp +/// @date 2009-10-26 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_multiple GLM_GTX_multiple +/// @ingroup gtx +/// +/// @brief Find the closest number of a number multiple of other number. +/// +/// <glm/gtx/multiple.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../gtc/round.hpp" + +#pragma message("GLM: GLM_GTX_multiple extension is deprecated, use GLM_GTC_round instead.") + +namespace glm +{ + /// @addtogroup gtx_multiple + /// @{ + + /// Higher multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// @param Source + /// @param Multiple Must be a null or positive value + /// + /// @see gtx_multiple + template <typename genType> + GLM_DEPRECATED GLM_FUNC_DECL genType higherMultiple( + genType Source, + genType Multiple); + + /// Higher multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// @param Source + /// @param Multiple Must be a null or positive value + /// + /// @see gtx_multiple + template <typename T, precision P, template <typename, precision> class vecType> + GLM_DEPRECATED GLM_FUNC_DECL vecType<T, P> higherMultiple( + vecType<T, P> const & Source, + vecType<T, P> const & Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// @param Source + /// @param Multiple Must be a null or positive value + /// + /// @see gtx_multiple + template <typename genType> + GLM_DEPRECATED GLM_FUNC_DECL genType lowerMultiple( + genType Source, + genType Multiple); + + /// Lower multiple number of Source. + /// + /// @tparam genType Floating-point or integer scalar or vector types. + /// @param Source + /// @param Multiple Must be a null or positive value + /// + /// @see gtx_multiple + template <typename T, precision P, template <typename, precision> class vecType> + GLM_DEPRECATED GLM_FUNC_DECL vecType<T, P> lowerMultiple( + vecType<T, P> const & Source, + vecType<T, P> const & Multiple); + + /// @} +}//namespace glm + +#include "multiple.inl" diff --git a/extensions/common/glm/gtx/multiple.inl b/extensions/common/glm/gtx/multiple.inl new file mode 100644 index 0000000000..dff7aa558f --- /dev/null +++ b/extensions/common/glm/gtx/multiple.inl @@ -0,0 +1,64 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_multiple +/// @file glm/gtx/multiple.inl +/// @date 2009-10-26 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + ////////////////////// + // higherMultiple + + template <typename genType> + GLM_FUNC_QUALIFIER genType higherMultiple(genType Source, genType Multiple) + { + return detail::compute_ceilMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> higherMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple) + { + return detail::functor2<T, P, vecType>::call(higherMultiple, Source, Multiple); + } + + ////////////////////// + // lowerMultiple + + template <typename genType> + GLM_FUNC_QUALIFIER genType lowerMultiple(genType Source, genType Multiple) + { + return detail::compute_floorMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<T, P> lowerMultiple(vecType<T, P> const & Source, vecType<T, P> const & Multiple) + { + return detail::functor2<T, P, vecType>::call(lowerMultiple, Source, Multiple); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/norm.hpp b/extensions/common/glm/gtx/norm.hpp new file mode 100644 index 0000000000..f7af9e0fe1 --- /dev/null +++ b/extensions/common/glm/gtx/norm.hpp @@ -0,0 +1,128 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_norm +/// @file glm/gtx/norm.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_quaternion (dependence) +/// +/// @defgroup gtx_norm GLM_GTX_norm +/// @ingroup gtx +/// +/// @brief Various ways to compute vector norms. +/// +/// <glm/gtx/norm.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/quaternion.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_norm extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_norm + /// @{ + + //! Returns the squared length of x. + //! From GLM_GTX_norm extension. + template <typename T> + GLM_FUNC_DECL T length2( + T const & x); + + //! Returns the squared length of x. + //! From GLM_GTX_norm extension. + template <typename genType> + GLM_FUNC_DECL typename genType::value_type length2( + genType const & x); + + //! Returns the squared distance between p0 and p1, i.e., length(p0 - p1). + //! From GLM_GTX_norm extension. + template <typename T> + GLM_FUNC_DECL T distance2( + T const & p0, + T const & p1); + + //! Returns the squared distance between p0 and p1, i.e., length(p0 - p1). + //! From GLM_GTX_norm extension. + template <typename genType> + GLM_FUNC_DECL typename genType::value_type distance2( + genType const & p0, + genType const & p1); + + //! Returns the L1 norm between x and y. + //! From GLM_GTX_norm extension. + template <typename T, precision P> + GLM_FUNC_DECL T l1Norm( + tvec3<T, P> const & x, + tvec3<T, P> const & y); + + //! Returns the L1 norm of v. + //! From GLM_GTX_norm extension. + template <typename T, precision P> + GLM_FUNC_DECL T l1Norm( + tvec3<T, P> const & v); + + //! Returns the L2 norm between x and y. + //! From GLM_GTX_norm extension. + template <typename T, precision P> + GLM_FUNC_DECL T l2Norm( + tvec3<T, P> const & x, + tvec3<T, P> const & y); + + //! Returns the L2 norm of v. + //! From GLM_GTX_norm extension. + template <typename T, precision P> + GLM_FUNC_DECL T l2Norm( + tvec3<T, P> const & x); + + //! Returns the L norm between x and y. + //! From GLM_GTX_norm extension. + template <typename T, precision P> + GLM_FUNC_DECL T lxNorm( + tvec3<T, P> const & x, + tvec3<T, P> const & y, + unsigned int Depth); + + //! Returns the L norm of v. + //! From GLM_GTX_norm extension. + template <typename T, precision P> + GLM_FUNC_DECL T lxNorm( + tvec3<T, P> const & x, + unsigned int Depth); + + /// @} +}//namespace glm + +#include "norm.inl" diff --git a/extensions/common/glm/gtx/norm.inl b/extensions/common/glm/gtx/norm.inl new file mode 100644 index 0000000000..d5e0ff87fd --- /dev/null +++ b/extensions/common/glm/gtx/norm.inl @@ -0,0 +1,170 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_norm +/// @file glm/gtx/norm.inl +/// @date 2005-12-21 / 2008-07-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T> + GLM_FUNC_QUALIFIER T length2 + ( + T const & x + ) + { + return x * x; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T length2 + ( + tvec2<T, P> const & x + ) + { + return dot(x, x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T length2 + ( + tvec3<T, P> const & x + ) + { + return dot(x, x); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T length2 + ( + tvec4<T, P> const & x + ) + { + return dot(x, x); + } + + template <typename T> + GLM_FUNC_QUALIFIER T distance2 + ( + T const & p0, + T const & p1 + ) + { + return length2(p1 - p0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T distance2 + ( + tvec2<T, P> const & p0, + tvec2<T, P> const & p1 + ) + { + return length2(p1 - p0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T distance2 + ( + tvec3<T, P> const & p0, + tvec3<T, P> const & p1 + ) + { + return length2(p1 - p0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T distance2 + ( + tvec4<T, P> const & p0, + tvec4<T, P> const & p1 + ) + { + return length2(p1 - p0); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T l1Norm + ( + tvec3<T, P> const & a, + tvec3<T, P> const & b + ) + { + return abs(b.x - a.x) + abs(b.y - a.y) + abs(b.z - a.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T l1Norm + ( + tvec3<T, P> const & v + ) + { + return abs(v.x) + abs(v.y) + abs(v.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T l2Norm + ( + tvec3<T, P> const & a, + tvec3<T, P> const & b + ) + { + return length(b - a); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T l2Norm + ( + tvec3<T, P> const & v + ) + { + return length(v); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T lxNorm + ( + tvec3<T, P> const & x, + tvec3<T, P> const & y, + unsigned int Depth + ) + { + return pow(pow(y.x - x.x, T(Depth)) + pow(y.y - x.y, T(Depth)) + pow(y.z - x.z, T(Depth)), T(1) / T(Depth)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T lxNorm + ( + tvec3<T, P> const & v, + unsigned int Depth + ) + { + return pow(pow(v.x, T(Depth)) + pow(v.y, T(Depth)) + pow(v.z, T(Depth)), T(1) / T(Depth)); + } + +}//namespace glm diff --git a/extensions/common/glm/gtx/normal.hpp b/extensions/common/glm/gtx/normal.hpp new file mode 100644 index 0000000000..03cc2e4bdb --- /dev/null +++ b/extensions/common/glm/gtx/normal.hpp @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_normal +/// @file glm/gtx/normal.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_normal GLM_GTX_normal +/// @ingroup gtx +/// +/// @brief Compute the normal of a triangle. +/// +/// <glm/gtx/normal.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_normal extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_normal + /// @{ + + //! Computes triangle normal from triangle points. + //! From GLM_GTX_normal extension. + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> triangleNormal( + tvec3<T, P> const & p1, + tvec3<T, P> const & p2, + tvec3<T, P> const & p3); + + /// @} +}//namespace glm + +#include "normal.inl" diff --git a/extensions/common/glm/gtx/normal.inl b/extensions/common/glm/gtx/normal.inl new file mode 100644 index 0000000000..e20a1c8db2 --- /dev/null +++ b/extensions/common/glm/gtx/normal.inl @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_normal +/// @file glm/gtx/normal.inl +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> triangleNormal + ( + tvec3<T, P> const & p1, + tvec3<T, P> const & p2, + tvec3<T, P> const & p3 + ) + { + return normalize(cross(p1 - p2, p1 - p3)); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/normalize_dot.hpp b/extensions/common/glm/gtx/normalize_dot.hpp new file mode 100644 index 0000000000..149a8cca53 --- /dev/null +++ b/extensions/common/glm/gtx/normalize_dot.hpp @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_normalize_dot +/// @file glm/gtx/normalize_dot.hpp +/// @date 2007-09-28 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_fast_square_root (dependence) +/// +/// @defgroup gtx_normalize_dot GLM_GTX_normalize_dot +/// @ingroup gtx +/// +/// @brief Dot product of vectors that need to be normalize with a single square root. +/// +/// <glm/gtx/normalized_dot.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../gtx/fast_square_root.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_normalize_dot extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_normalize_dot + /// @{ + + /// Normalize parameters and returns the dot product of x and y. + /// It's faster that dot(normalize(x), normalize(y)). + /// + /// @see gtx_normalize_dot extension. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL T normalizeDot(vecType<T, P> const & x, vecType<T, P> const & y); + + /// Normalize parameters and returns the dot product of x and y. + /// Faster that dot(fastNormalize(x), fastNormalize(y)). + /// + /// @see gtx_normalize_dot extension. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL T fastNormalizeDot(vecType<T, P> const & x, vecType<T, P> const & y); + + /// @} +}//namespace glm + +#include "normalize_dot.inl" diff --git a/extensions/common/glm/gtx/normalize_dot.inl b/extensions/common/glm/gtx/normalize_dot.inl new file mode 100644 index 0000000000..6db462a326 --- /dev/null +++ b/extensions/common/glm/gtx/normalize_dot.inl @@ -0,0 +1,46 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_normalize_dot +/// @file glm/gtx/normalize_dot.inl +/// @date 2007-09-28 / 2008-10-07 +/// @author Christophe Riccio +////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T normalizeDot(vecType<T, P> const & x, vecType<T, P> const & y) + { + return glm::dot(x, y) * glm::inversesqrt(glm::dot(x, x) * glm::dot(y, y)); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T fastNormalizeDot(vecType<T, P> const & x, vecType<T, P> const & y) + { + return glm::dot(x, y) * glm::fastInverseSqrt(glm::dot(x, x) * glm::dot(y, y)); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/number_precision.hpp b/extensions/common/glm/gtx/number_precision.hpp new file mode 100644 index 0000000000..34f71821c4 --- /dev/null +++ b/extensions/common/glm/gtx/number_precision.hpp @@ -0,0 +1,86 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_number_precision +/// @file glm/gtx/number_precision.hpp +/// @date 2007-05-10 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_type_precision (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_number_precision GLM_GTX_number_precision +/// @ingroup gtx +/// +/// @brief Defined size types. +/// +/// <glm/gtx/number_precision.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/type_precision.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_number_precision extension included") +#endif + +namespace glm{ +namespace gtx +{ + ///////////////////////////// + // Unsigned int vector types + + /// @addtogroup gtx_number_precision + /// @{ + + typedef u8 u8vec1; //!< \brief 8bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + typedef u16 u16vec1; //!< \brief 16bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + typedef u32 u32vec1; //!< \brief 32bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + typedef u64 u64vec1; //!< \brief 64bit unsigned integer scalar. (from GLM_GTX_number_precision extension) + + ////////////////////// + // Float vector types + + typedef f32 f32vec1; //!< \brief Single-precision floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f64 f64vec1; //!< \brief Single-precision floating-point scalar. (from GLM_GTX_number_precision extension) + + ////////////////////// + // Float matrix types + + typedef f32 f32mat1; //!< \brief Single-precision floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f32 f32mat1x1; //!< \brief Single-precision floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f64 f64mat1; //!< \brief Double-precision floating-point scalar. (from GLM_GTX_number_precision extension) + typedef f64 f64mat1x1; //!< \brief Double-precision floating-point scalar. (from GLM_GTX_number_precision extension) + + /// @} +}//namespace gtx +}//namespace glm + +#include "number_precision.inl" diff --git a/extensions/common/glm/gtx/number_precision.inl b/extensions/common/glm/gtx/number_precision.inl new file mode 100644 index 0000000000..7cc8914c33 --- /dev/null +++ b/extensions/common/glm/gtx/number_precision.inl @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_number_precision +/// @file glm/gtx/number_precision.inl +/// @date 2007-05-10 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + +} diff --git a/extensions/common/glm/gtx/optimum_pow.hpp b/extensions/common/glm/gtx/optimum_pow.hpp new file mode 100644 index 0000000000..78e72e7413 --- /dev/null +++ b/extensions/common/glm/gtx/optimum_pow.hpp @@ -0,0 +1,79 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_optimum_pow +/// @file glm/gtx/optimum_pow.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_optimum_pow GLM_GTX_optimum_pow +/// @ingroup gtx +/// +/// @brief Integer exponentiation of power functions. +/// +/// <glm/gtx/optimum_pow.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_optimum_pow extension included") +#endif + +namespace glm{ +namespace gtx +{ + /// @addtogroup gtx_optimum_pow + /// @{ + + /// Returns x raised to the power of 2. + /// + /// @see gtx_optimum_pow + template <typename genType> + GLM_FUNC_DECL genType pow2(genType const & x); + + /// Returns x raised to the power of 3. + /// + /// @see gtx_optimum_pow + template <typename genType> + GLM_FUNC_DECL genType pow3(genType const & x); + + /// Returns x raised to the power of 4. + /// + /// @see gtx_optimum_pow + template <typename genType> + GLM_FUNC_DECL genType pow4(genType const & x); + + /// @} +}//namespace gtx +}//namespace glm + +#include "optimum_pow.inl" diff --git a/extensions/common/glm/gtx/optimum_pow.inl b/extensions/common/glm/gtx/optimum_pow.inl new file mode 100644 index 0000000000..3c0d2e4d97 --- /dev/null +++ b/extensions/common/glm/gtx/optimum_pow.inl @@ -0,0 +1,52 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_optimum_pow +/// @file glm/gtx/optimum_pow.inl +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename genType> + GLM_FUNC_QUALIFIER genType pow2(genType const & x) + { + return x * x; + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType pow3(genType const & x) + { + return x * x * x; + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType pow4(genType const & x) + { + return (x * x) * (x * x); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/orthonormalize.hpp b/extensions/common/glm/gtx/orthonormalize.hpp new file mode 100644 index 0000000000..8782883f16 --- /dev/null +++ b/extensions/common/glm/gtx/orthonormalize.hpp @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_orthonormalize +/// @file glm/gtx/orthonormalize.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_orthonormalize GLM_GTX_orthonormalize +/// @ingroup gtx +/// +/// @brief Orthonormalize matrices. +/// +/// <glm/gtx/orthonormalize.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../vec3.hpp" +#include "../mat3x3.hpp" +#include "../geometric.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_orthonormalize extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_orthonormalize + /// @{ + + /// Returns the orthonormalized matrix of m. + /// + /// @see gtx_orthonormalize + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> orthonormalize(tmat3x3<T, P> const & m); + + /// Orthonormalizes x according y. + /// + /// @see gtx_orthonormalize + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> orthonormalize(tvec3<T, P> const & x, tvec3<T, P> const & y); + + /// @} +}//namespace glm + +#include "orthonormalize.inl" diff --git a/extensions/common/glm/gtx/orthonormalize.inl b/extensions/common/glm/gtx/orthonormalize.inl new file mode 100644 index 0000000000..461f84bbb5 --- /dev/null +++ b/extensions/common/glm/gtx/orthonormalize.inl @@ -0,0 +1,59 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_orthonormalize +/// @file glm/gtx/orthonormalize.inl +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> orthonormalize(tmat3x3<T, P> const & m) + { + tmat3x3<T, P> r = m; + + r[0] = normalize(r[0]); + + T d0 = dot(r[0], r[1]); + r[1] -= r[0] * d0; + r[1] = normalize(r[1]); + + T d1 = dot(r[1], r[2]); + d0 = dot(r[0], r[2]); + r[2] -= r[0] * d0 + r[1] * d1; + r[2] = normalize(r[2]); + + return r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> orthonormalize(tvec3<T, P> const & x, tvec3<T, P> const & y) + { + return normalize(x - y * dot(y, x)); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/perpendicular.hpp b/extensions/common/glm/gtx/perpendicular.hpp new file mode 100644 index 0000000000..84fdfa016e --- /dev/null +++ b/extensions/common/glm/gtx/perpendicular.hpp @@ -0,0 +1,68 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_perpendicular +/// @file glm/gtx/perpendicular.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_projection (dependence) +/// +/// @defgroup gtx_perpendicular GLM_GTX_perpendicular +/// @ingroup gtx +/// +/// @brief Perpendicular of a vector from other one +/// +/// <glm/gtx/perpendicular.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/projection.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_perpendicular extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_perpendicular + /// @{ + + //! Projects x a perpendicular axis of Normal. + //! From GLM_GTX_perpendicular extension. + template <typename vecType> + GLM_FUNC_DECL vecType perp( + vecType const & x, + vecType const & Normal); + + /// @} +}//namespace glm + +#include "perpendicular.inl" diff --git a/extensions/common/glm/gtx/perpendicular.inl b/extensions/common/glm/gtx/perpendicular.inl new file mode 100644 index 0000000000..22bbb23eef --- /dev/null +++ b/extensions/common/glm/gtx/perpendicular.inl @@ -0,0 +1,44 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_perpendicular +/// @file glm/gtx/perpendicular.inl +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename vecType> + GLM_FUNC_QUALIFIER vecType perp + ( + vecType const & x, + vecType const & Normal + ) + { + return x - proj(x, Normal); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/polar_coordinates.hpp b/extensions/common/glm/gtx/polar_coordinates.hpp new file mode 100644 index 0000000000..bdc21d48d3 --- /dev/null +++ b/extensions/common/glm/gtx/polar_coordinates.hpp @@ -0,0 +1,73 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_polar_coordinates +/// @file glm/gtx/polar_coordinates.hpp +/// @date 2007-03-06 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_polar_coordinates GLM_GTX_polar_coordinates +/// @ingroup gtx +/// +/// @brief Conversion from Euclidean space to polar space and revert. +/// +/// <glm/gtx/polar_coordinates.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_polar_coordinates extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_polar_coordinates + /// @{ + + /// Convert Euclidean to Polar coordinates, x is the xz distance, y, the latitude and z the longitude. + /// + /// @see gtx_polar_coordinates + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> polar( + tvec3<T, P> const & euclidean); + + /// Convert Polar to Euclidean coordinates. + /// + /// @see gtx_polar_coordinates + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> euclidean( + tvec2<T, P> const & polar); + + /// @} +}//namespace glm + +#include "polar_coordinates.inl" diff --git a/extensions/common/glm/gtx/polar_coordinates.inl b/extensions/common/glm/gtx/polar_coordinates.inl new file mode 100644 index 0000000000..4de58e3ca4 --- /dev/null +++ b/extensions/common/glm/gtx/polar_coordinates.inl @@ -0,0 +1,66 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_polar_coordinates +/// @file glm/gtx/polar_coordinates.inl +/// @date 2007-03-06 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> polar + ( + tvec3<T, P> const & euclidean + ) + { + T const Length(length(euclidean)); + tvec3<T, P> const tmp(euclidean / Length); + T const xz_dist(sqrt(tmp.x * tmp.x + tmp.z * tmp.z)); + + return tvec3<T, P>( + atan(xz_dist, tmp.y), // latitude + atan(tmp.x, tmp.z), // longitude + xz_dist); // xz distance + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> euclidean + ( + tvec2<T, P> const & polar + ) + { + T const latitude(polar.x); + T const longitude(polar.y); + + return tvec3<T, P>( + cos(latitude) * sin(longitude), + sin(latitude), + cos(latitude) * cos(longitude)); + } + +}//namespace glm diff --git a/extensions/common/glm/gtx/projection.hpp b/extensions/common/glm/gtx/projection.hpp new file mode 100644 index 0000000000..2186f7b161 --- /dev/null +++ b/extensions/common/glm/gtx/projection.hpp @@ -0,0 +1,65 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_projection +/// @file glm/gtx/projection.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_projection GLM_GTX_projection +/// @ingroup gtx +/// +/// @brief Projection of a vector to other one +/// +/// <glm/gtx/projection.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../geometric.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_projection extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_projection + /// @{ + + /// Projects x on Normal. + /// + /// @see gtx_projection + template <typename vecType> + GLM_FUNC_DECL vecType proj(vecType const & x, vecType const & Normal); + + /// @} +}//namespace glm + +#include "projection.inl" diff --git a/extensions/common/glm/gtx/projection.inl b/extensions/common/glm/gtx/projection.inl new file mode 100644 index 0000000000..ce742a8dce --- /dev/null +++ b/extensions/common/glm/gtx/projection.inl @@ -0,0 +1,40 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_projection +/// @file glm/gtx/projection.inl +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename vecType> + GLM_FUNC_QUALIFIER vecType proj(vecType const & x, vecType const & Normal) + { + return glm::dot(x, Normal) / glm::dot(Normal, Normal) * Normal; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/quaternion.hpp b/extensions/common/glm/gtx/quaternion.hpp new file mode 100644 index 0000000000..f65efc118b --- /dev/null +++ b/extensions/common/glm/gtx/quaternion.hpp @@ -0,0 +1,214 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_quaternion +/// @file glm/gtx/quaternion.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_quaternion GLM_GTX_quaternion +/// @ingroup gtx +/// +/// @brief Extented quaternion types and functions +/// +/// <glm/gtx/quaternion.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/constants.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtx/norm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_quaternion extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_quaternion + /// @{ + + //! Compute a cross product between a quaternion and a vector. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> cross( + tquat<T, P> const & q, + tvec3<T, P> const & v); + + //! Compute a cross product between a vector and a quaternion. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> cross( + tvec3<T, P> const & v, + tquat<T, P> const & q); + + //! Compute a point on a path according squad equation. + //! q1 and q2 are control points; s1 and s2 are intermediate control points. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tquat<T, P> squad( + tquat<T, P> const & q1, + tquat<T, P> const & q2, + tquat<T, P> const & s1, + tquat<T, P> const & s2, + T const & h); + + //! Returns an intermediate control point for squad interpolation. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tquat<T, P> intermediate( + tquat<T, P> const & prev, + tquat<T, P> const & curr, + tquat<T, P> const & next); + + //! Returns a exp of a quaternion. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tquat<T, P> exp( + tquat<T, P> const & q); + + //! Returns a log of a quaternion. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tquat<T, P> log( + tquat<T, P> const & q); + + /// Returns x raised to the y power. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tquat<T, P> pow( + tquat<T, P> const & x, + T const & y); + + //! Returns quarternion square root. + /// + /// @see gtx_quaternion + //template<typename T, precision P> + //tquat<T, P> sqrt( + // tquat<T, P> const & q); + + //! Rotates a 3 components vector by a quaternion. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> rotate( + tquat<T, P> const & q, + tvec3<T, P> const & v); + + /// Rotates a 4 components vector by a quaternion. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> rotate( + tquat<T, P> const & q, + tvec4<T, P> const & v); + + /// Extract the real component of a quaternion. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL T extractRealComponent( + tquat<T, P> const & q); + + /// Converts a quaternion to a 3 * 3 matrix. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> toMat3( + tquat<T, P> const & x){return mat3_cast(x);} + + /// Converts a quaternion to a 4 * 4 matrix. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> toMat4( + tquat<T, P> const & x){return mat4_cast(x);} + + /// Converts a 3 * 3 matrix to a quaternion. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tquat<T, P> toQuat( + tmat3x3<T, P> const & x){return quat_cast(x);} + + /// Converts a 4 * 4 matrix to a quaternion. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tquat<T, P> toQuat( + tmat4x4<T, P> const & x){return quat_cast(x);} + + /// Quaternion interpolation using the rotation short path. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tquat<T, P> shortMix( + tquat<T, P> const & x, + tquat<T, P> const & y, + T const & a); + + /// Quaternion normalized linear interpolation. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tquat<T, P> fastMix( + tquat<T, P> const & x, + tquat<T, P> const & y, + T const & a); + + /// Compute the rotation between two vectors. + /// param orig vector, needs to be normalized + /// param dest vector, needs to be normalized + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL tquat<T, P> rotation( + tvec3<T, P> const & orig, + tvec3<T, P> const & dest); + + /// Returns the squared length of x. + /// + /// @see gtx_quaternion + template<typename T, precision P> + GLM_FUNC_DECL T length2(tquat<T, P> const & q); + + /// @} +}//namespace glm + +#include "quaternion.inl" diff --git a/extensions/common/glm/gtx/quaternion.inl b/extensions/common/glm/gtx/quaternion.inl new file mode 100644 index 0000000000..9db6a1c1ab --- /dev/null +++ b/extensions/common/glm/gtx/quaternion.inl @@ -0,0 +1,285 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_quaternion +/// @file glm/gtx/quaternion.inl +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include <limits> +#include "../gtc/constants.hpp" + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> cross + ( + tvec3<T, P> const & v, + tquat<T, P> const & q + ) + { + return inverse(q) * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> cross + ( + tquat<T, P> const & q, + tvec3<T, P> const & v + ) + { + return q * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> squad + ( + tquat<T, P> const & q1, + tquat<T, P> const & q2, + tquat<T, P> const & s1, + tquat<T, P> const & s2, + T const & h) + { + return mix(mix(q1, q2, h), mix(s1, s2, h), static_cast<T>(2) * (static_cast<T>(1) - h) * h); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> intermediate + ( + tquat<T, P> const & prev, + tquat<T, P> const & curr, + tquat<T, P> const & next + ) + { + tquat<T, P> invQuat = inverse(curr); + return exp((log(next + invQuat) + log(prev + invQuat)) / static_cast<T>(-4)) * curr; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> exp + ( + tquat<T, P> const & q + ) + { + tvec3<T, P> u(q.x, q.y, q.z); + T Angle = glm::length(u); + if (Angle < epsilon<T>()) + return tquat<T, P>(); + + tvec3<T, P> v(u / Angle); + return tquat<T, P>(cos(Angle), sin(Angle) * v); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> log + ( + tquat<T, P> const & q + ) + { + tvec3<T, P> u(q.x, q.y, q.z); + T Vec3Len = length(u); + + if (Vec3Len < epsilon<T>()) + { + if(q.w > static_cast<T>(0)) + return tquat<T, P>(log(q.w), static_cast<T>(0), static_cast<T>(0), static_cast<T>(0)); + else if(q.w < static_cast<T>(0)) + return tquat<T, P>(log(-q.w), pi<T>(), static_cast<T>(0), static_cast<T>(0)); + else + return tquat<T, P>(std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity(), std::numeric_limits<T>::infinity()); + } + else + { + T QuatLen = sqrt(Vec3Len * Vec3Len + q.w * q.w); + T t = atan(Vec3Len, T(q.w)) / Vec3Len; + return tquat<T, P>(log(QuatLen), t * q.x, t * q.y, t * q.z); + } + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> pow + ( + tquat<T, P> const & x, + T const & y + ) + { + if(abs(x.w) > (static_cast<T>(1) - epsilon<T>())) + return x; + T Angle = acos(y); + T NewAngle = Angle * y; + T Div = sin(NewAngle) / sin(Angle); + return tquat<T, P>( + cos(NewAngle), + x.x * Div, + x.y * Div, + x.z * Div); + } + + //template <typename T, precision P> + //GLM_FUNC_QUALIFIER tquat<T, P> sqrt + //( + // tquat<T, P> const & q + //) + //{ + // T q0 = static_cast<T>(1) - dot(q, q); + // return T(2) * (T(1) + q0) * q; + //} + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> rotate + ( + tquat<T, P> const & q, + tvec3<T, P> const & v + ) + { + return q * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> rotate + ( + tquat<T, P> const & q, + tvec4<T, P> const & v + ) + { + return q * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T extractRealComponent + ( + tquat<T, P> const & q + ) + { + T w = static_cast<T>(1) - q.x * q.x - q.y * q.y - q.z * q.z; + if(w < T(0)) + return T(0); + else + return -sqrt(w); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T length2 + ( + tquat<T, P> const & q + ) + { + return q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> shortMix + ( + tquat<T, P> const & x, + tquat<T, P> const & y, + T const & a + ) + { + if(a <= static_cast<T>(0)) return x; + if(a >= static_cast<T>(1)) return y; + + T fCos = dot(x, y); + tquat<T, P> y2(y); //BUG!!! tquat<T> y2; + if(fCos < static_cast<T>(0)) + { + y2 = -y; + fCos = -fCos; + } + + //if(fCos > 1.0f) // problem + T k0, k1; + if(fCos > (static_cast<T>(1) - epsilon<T>())) + { + k0 = static_cast<T>(1) - a; + k1 = static_cast<T>(0) + a; //BUG!!! 1.0f + a; + } + else + { + T fSin = sqrt(T(1) - fCos * fCos); + T fAngle = atan(fSin, fCos); + T fOneOverSin = static_cast<T>(1) / fSin; + k0 = sin((static_cast<T>(1) - a) * fAngle) * fOneOverSin; + k1 = sin((static_cast<T>(0) + a) * fAngle) * fOneOverSin; + } + + return tquat<T, P>( + k0 * x.w + k1 * y2.w, + k0 * x.x + k1 * y2.x, + k0 * x.y + k1 * y2.y, + k0 * x.z + k1 * y2.z); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> fastMix + ( + tquat<T, P> const & x, + tquat<T, P> const & y, + T const & a + ) + { + return glm::normalize(x * (static_cast<T>(1) - a) + (y * a)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> rotation + ( + tvec3<T, P> const & orig, + tvec3<T, P> const & dest + ) + { + T cosTheta = dot(orig, dest); + tvec3<T, P> rotationAxis; + + if(cosTheta < static_cast<T>(-1) + epsilon<T>()) + { + // special case when vectors in opposite directions : + // there is no "ideal" rotation axis + // So guess one; any will do as long as it's perpendicular to start + // This implementation favors a rotation around the Up axis (Y), + // since it's often what you want to do. + rotationAxis = cross(tvec3<T, P>(0, 0, 1), orig); + if(length2(rotationAxis) < epsilon<T>()) // bad luck, they were parallel, try again! + rotationAxis = cross(tvec3<T, P>(1, 0, 0), orig); + + rotationAxis = normalize(rotationAxis); + return angleAxis(pi<T>(), rotationAxis); + } + + // Implementation from Stan Melax's Game Programming Gems 1 article + rotationAxis = cross(orig, dest); + + T s = sqrt((T(1) + cosTheta) * static_cast<T>(2)); + T invs = static_cast<T>(1) / s; + + return tquat<T, P>( + s * static_cast<T>(0.5f), + rotationAxis.x * invs, + rotationAxis.y * invs, + rotationAxis.z * invs); + } + +}//namespace glm diff --git a/extensions/common/glm/gtx/range.hpp b/extensions/common/glm/gtx/range.hpp new file mode 100644 index 0000000000..c972b08b8e --- /dev/null +++ b/extensions/common/glm/gtx/range.hpp @@ -0,0 +1,102 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_range +/// @file glm/gtx/range.hpp +/// @date 2014-09-19 / 2014-09-19 +/// @author Joshua Moerman +/// +/// @defgroup gtx_range GLM_GTX_range +/// @ingroup gtx +/// +/// @brief Defines begin and end for vectors and matrices. Useful for range-based for loop. +/// The range is defined over the elements, not over columns or rows (e.g. mat4 has 16 elements). +/// +/// <glm/gtx/range.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#if !GLM_HAS_RANGE_FOR +# error "GLM_GTX_range requires C++11 suppport or 'range for'" +#endif + +#include "../gtc/type_ptr.hpp" + +namespace glm{ +namespace detail +{ + /* The glm types provide a .length() member, but for matrices + this only defines the number of columns, so we need to work around this */ + template <typename T, precision P> + detail::component_count_t number_of_elements_(tvec2<T, P> const & v){ + return detail::component_count(v); + } + + template <typename T, precision P> + detail::component_count_t number_of_elements_(tvec3<T, P> const & v){ + return detail::component_count(v); + } + + template <typename T, precision P> + detail::component_count_t number_of_elements_(tvec4<T, P> const & v){ + return detail::component_count(v); + } + + template <typename genType> + detail::component_count_t number_of_elements_(genType const & m){ + return detail::component_count(m) * detail::component_count(m[0]); + } +}//namespace + + /// @addtogroup gtx_range + /// @{ + + template <typename genType> + const typename genType::value_type * begin(genType const & v){ + return value_ptr(v); + } + + template <typename genType> + const typename genType::value_type * end(genType const & v){ + return begin(v) + detail::number_of_elements_(v); + } + + template <typename genType> + typename genType::value_type * begin(genType& v){ + return value_ptr(v); + } + + template <typename genType> + typename genType::value_type * end(genType& v){ + return begin(v) + detail::number_of_elements_(v); + } + + /// @} +}//namespace glm diff --git a/extensions/common/glm/gtx/raw_data.hpp b/extensions/common/glm/gtx/raw_data.hpp new file mode 100644 index 0000000000..482510d4ed --- /dev/null +++ b/extensions/common/glm/gtx/raw_data.hpp @@ -0,0 +1,76 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_raw_data +/// @file glm/gtx/raw_data.hpp +/// @date 2008-11-19 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_raw_data GLM_GTX_raw_data +/// @ingroup gtx +/// +/// @brief Projection of a vector to other one +/// +/// <glm/gtx/raw_data.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" +#include "../detail/type_int.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_raw_data extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_raw_data + /// @{ + + //! Type for byte numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint8 byte; + + //! Type for word numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint16 word; + + //! Type for dword numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint32 dword; + + //! Type for qword numbers. + //! From GLM_GTX_raw_data extension. + typedef detail::uint64 qword; + + /// @} +}// namespace glm + +#include "raw_data.inl" diff --git a/extensions/common/glm/gtx/raw_data.inl b/extensions/common/glm/gtx/raw_data.inl new file mode 100644 index 0000000000..5e7e9e330c --- /dev/null +++ b/extensions/common/glm/gtx/raw_data.inl @@ -0,0 +1,31 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_raw_data +/// @file glm/gtx/raw_data.inl +/// @date 2008-11-19 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// diff --git a/extensions/common/glm/gtx/rotate_normalized_axis.hpp b/extensions/common/glm/gtx/rotate_normalized_axis.hpp new file mode 100644 index 0000000000..9daf06a7f2 --- /dev/null +++ b/extensions/common/glm/gtx/rotate_normalized_axis.hpp @@ -0,0 +1,93 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_rotate_normalized_axis +/// @file glm/gtx/rotate_normalized_axis.hpp +/// @date 2012-12-13 / 2012-12-13 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_matrix_transform +/// @see gtc_quaternion +/// +/// @defgroup gtx_rotate_normalized_axis GLM_GTX_rotate_normalized_axis +/// @ingroup gtx +/// +/// @brief Quaternions and matrices rotations around normalized axis. +/// +/// <glm/gtx/rotate_normalized_axis.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/epsilon.hpp" +#include "../gtc/quaternion.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_rotate_normalized_axis extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_rotate_normalized_axis + /// @{ + + /// Builds a rotation 4 * 4 matrix created from a normalized axis and an angle. + /// + /// @param m Input matrix multiplied by this rotation matrix. + /// @param angle Rotation angle expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise. + /// @param axis Rotation axis, must be normalized. + /// @tparam T Value type used to build the matrix. Currently supported: half (not recommanded), float or double. + /// + /// @see gtx_rotate_normalized_axis + /// @see - rotate(T angle, T x, T y, T z) + /// @see - rotate(tmat4x4<T, P> const & m, T angle, T x, T y, T z) + /// @see - rotate(T angle, tvec3<T, P> const & v) + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> rotateNormalizedAxis( + tmat4x4<T, P> const & m, + T const & angle, + tvec3<T, P> const & axis); + + /// Rotates a quaternion from a vector of 3 components normalized axis and an angle. + /// + /// @param q Source orientation + /// @param angle Angle expressed in radians if GLM_FORCE_RADIANS is define or degrees otherwise. + /// @param axis Normalized axis of the rotation, must be normalized. + /// + /// @see gtx_rotate_normalized_axis + template <typename T, precision P> + GLM_FUNC_DECL tquat<T, P> rotateNormalizedAxis( + tquat<T, P> const & q, + T const & angle, + tvec3<T, P> const & axis); + + /// @} +}//namespace glm + +#include "rotate_normalized_axis.inl" diff --git a/extensions/common/glm/gtx/rotate_normalized_axis.inl b/extensions/common/glm/gtx/rotate_normalized_axis.inl new file mode 100644 index 0000000000..54f95a453b --- /dev/null +++ b/extensions/common/glm/gtx/rotate_normalized_axis.inl @@ -0,0 +1,88 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_rotate_normalized_axis +/// @file glm/gtx/rotate_normalized_axis.inl +/// @date 2012-12-13 / 2012-12-13 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> rotateNormalizedAxis + ( + tmat4x4<T, P> const & m, + T const & angle, + tvec3<T, P> const & v + ) + { + T const a = angle; + T const c = cos(a); + T const s = sin(a); + + tvec3<T, P> const axis(v); + + tvec3<T, P> const temp((static_cast<T>(1) - c) * axis); + + tmat4x4<T, P> Rotate(uninitialize); + Rotate[0][0] = c + temp[0] * axis[0]; + Rotate[0][1] = 0 + temp[0] * axis[1] + s * axis[2]; + Rotate[0][2] = 0 + temp[0] * axis[2] - s * axis[1]; + + Rotate[1][0] = 0 + temp[1] * axis[0] - s * axis[2]; + Rotate[1][1] = c + temp[1] * axis[1]; + Rotate[1][2] = 0 + temp[1] * axis[2] + s * axis[0]; + + Rotate[2][0] = 0 + temp[2] * axis[0] + s * axis[1]; + Rotate[2][1] = 0 + temp[2] * axis[1] - s * axis[0]; + Rotate[2][2] = c + temp[2] * axis[2]; + + tmat4x4<T, P> Result(uninitialize); + Result[0] = m[0] * Rotate[0][0] + m[1] * Rotate[0][1] + m[2] * Rotate[0][2]; + Result[1] = m[0] * Rotate[1][0] + m[1] * Rotate[1][1] + m[2] * Rotate[1][2]; + Result[2] = m[0] * Rotate[2][0] + m[1] * Rotate[2][1] + m[2] * Rotate[2][2]; + Result[3] = m[3]; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tquat<T, P> rotateNormalizedAxis + ( + tquat<T, P> const & q, + T const & angle, + tvec3<T, P> const & v + ) + { + tvec3<T, P> const Tmp(v); + + T const AngleRad(angle); + T const Sin = sin(AngleRad * T(0.5)); + + return q * tquat<T, P>(cos(AngleRad * static_cast<T>(0.5)), Tmp.x * Sin, Tmp.y * Sin, Tmp.z * Sin); + //return gtc::quaternion::cross(q, tquat<T, P>(cos(AngleRad * T(0.5)), Tmp.x * fSin, Tmp.y * fSin, Tmp.z * fSin)); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/rotate_vector.hpp b/extensions/common/glm/gtx/rotate_vector.hpp new file mode 100644 index 0000000000..61024c338e --- /dev/null +++ b/extensions/common/glm/gtx/rotate_vector.hpp @@ -0,0 +1,146 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_rotate_vector +/// @file glm/gtx/rotate_vector.hpp +/// @date 2006-11-02 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_transform (dependence) +/// +/// @defgroup gtx_rotate_vector GLM_GTX_rotate_vector +/// @ingroup gtx +/// +/// @brief Function to directly rotate a vector +/// +/// <glm/gtx/rotate_vector.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/transform.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_rotate_vector extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_rotate_vector + /// @{ + + /// Returns Spherical interpolation between two vectors + /// + /// @param x A first vector + /// @param y A second vector + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// + /// @see gtx_rotate_vector + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> slerp( + tvec3<T, P> const & x, + tvec3<T, P> const & y, + T const & a); + + //! Rotate a two dimensional vector. + //! From GLM_GTX_rotate_vector extension. + template <typename T, precision P> + GLM_FUNC_DECL tvec2<T, P> rotate( + tvec2<T, P> const & v, + T const & angle); + + //! Rotate a three dimensional vector around an axis. + //! From GLM_GTX_rotate_vector extension. + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> rotate( + tvec3<T, P> const & v, + T const & angle, + tvec3<T, P> const & normal); + + //! Rotate a four dimensional vector around an axis. + //! From GLM_GTX_rotate_vector extension. + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> rotate( + tvec4<T, P> const & v, + T const & angle, + tvec3<T, P> const & normal); + + //! Rotate a three dimensional vector around the X axis. + //! From GLM_GTX_rotate_vector extension. + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> rotateX( + tvec3<T, P> const & v, + T const & angle); + + //! Rotate a three dimensional vector around the Y axis. + //! From GLM_GTX_rotate_vector extension. + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> rotateY( + tvec3<T, P> const & v, + T const & angle); + + //! Rotate a three dimensional vector around the Z axis. + //! From GLM_GTX_rotate_vector extension. + template <typename T, precision P> + GLM_FUNC_DECL tvec3<T, P> rotateZ( + tvec3<T, P> const & v, + T const & angle); + + //! Rotate a four dimentionnals vector around the X axis. + //! From GLM_GTX_rotate_vector extension. + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> rotateX( + tvec4<T, P> const & v, + T const & angle); + + //! Rotate a four dimensional vector around the X axis. + //! From GLM_GTX_rotate_vector extension. + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> rotateY( + tvec4<T, P> const & v, + T const & angle); + + //! Rotate a four dimensional vector around the X axis. + //! From GLM_GTX_rotate_vector extension. + template <typename T, precision P> + GLM_FUNC_DECL tvec4<T, P> rotateZ( + tvec4<T, P> const & v, + T const & angle); + + //! Build a rotation matrix from a normal and a up vector. + //! From GLM_GTX_rotate_vector extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> orientation( + tvec3<T, P> const & Normal, + tvec3<T, P> const & Up); + + /// @} +}//namespace glm + +#include "rotate_vector.inl" diff --git a/extensions/common/glm/gtx/rotate_vector.inl b/extensions/common/glm/gtx/rotate_vector.inl new file mode 100644 index 0000000000..dc1d07c8b8 --- /dev/null +++ b/extensions/common/glm/gtx/rotate_vector.inl @@ -0,0 +1,217 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_rotate_vector +/// @file glm/gtx/rotate_vector.inl +/// @date 2006-11-02 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> slerp + ( + tvec3<T, P> const & x, + tvec3<T, P> const & y, + T const & a + ) + { + // get cosine of angle between vectors (-1 -> 1) + T CosAlpha = dot(x, y); + // get angle (0 -> pi) + T Alpha = acos(CosAlpha); + // get sine of angle between vectors (0 -> 1) + T SinAlpha = sin(Alpha); + // this breaks down when SinAlpha = 0, i.e. Alpha = 0 or pi + T t1 = sin((static_cast<T>(1) - a) * Alpha) / SinAlpha; + T t2 = sin(a * Alpha) / SinAlpha; + + // interpolate src vectors + return x * t1 + y * t2; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> rotate + ( + tvec2<T, P> const & v, + T const & angle + ) + { + tvec2<T, P> Result; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos - v.y * Sin; + Result.y = v.x * Sin + v.y * Cos; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> rotate + ( + tvec3<T, P> const & v, + T const & angle, + tvec3<T, P> const & normal + ) + { + return tmat3x3<T, P>(glm::rotate(angle, normal)) * v; + } + /* + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> rotateGTX( + const tvec3<T, P>& x, + T angle, + const tvec3<T, P>& normal) + { + const T Cos = cos(radians(angle)); + const T Sin = sin(radians(angle)); + return x * Cos + ((x * normal) * (T(1) - Cos)) * normal + cross(x, normal) * Sin; + } + */ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> rotate + ( + tvec4<T, P> const & v, + T const & angle, + tvec3<T, P> const & normal + ) + { + return rotate(angle, normal) * v; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> rotateX + ( + tvec3<T, P> const & v, + T const & angle + ) + { + tvec3<T, P> Result(v); + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.y = v.y * Cos - v.z * Sin; + Result.z = v.y * Sin + v.z * Cos; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> rotateY + ( + tvec3<T, P> const & v, + T const & angle + ) + { + tvec3<T, P> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos + v.z * Sin; + Result.z = -v.x * Sin + v.z * Cos; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> rotateZ + ( + tvec3<T, P> const & v, + T const & angle + ) + { + tvec3<T, P> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos - v.y * Sin; + Result.y = v.x * Sin + v.y * Cos; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> rotateX + ( + tvec4<T, P> const & v, + T const & angle + ) + { + tvec4<T, P> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.y = v.y * Cos - v.z * Sin; + Result.z = v.y * Sin + v.z * Cos; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> rotateY + ( + tvec4<T, P> const & v, + T const & angle + ) + { + tvec4<T, P> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos + v.z * Sin; + Result.z = -v.x * Sin + v.z * Cos; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> rotateZ + ( + tvec4<T, P> const & v, + T const & angle + ) + { + tvec4<T, P> Result = v; + T const Cos(cos(angle)); + T const Sin(sin(angle)); + + Result.x = v.x * Cos - v.y * Sin; + Result.y = v.x * Sin + v.y * Cos; + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> orientation + ( + tvec3<T, P> const & Normal, + tvec3<T, P> const & Up + ) + { + if(all(equal(Normal, Up))) + return tmat4x4<T, P>(T(1)); + + tvec3<T, P> RotationAxis = cross(Up, Normal); + T Angle = acos(dot(Normal, Up)); + + return rotate(Angle, RotationAxis); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/scalar_multiplication.hpp b/extensions/common/glm/gtx/scalar_multiplication.hpp new file mode 100644 index 0000000000..481edd4154 --- /dev/null +++ b/extensions/common/glm/gtx/scalar_multiplication.hpp @@ -0,0 +1,98 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx +/// @file glm/gtx/scalar_multiplication.hpp +/// @date 2014-09-22 / 2014-09-22 +/// @author Joshua Moerman +/// +/// @brief Enables scalar multiplication for all types +/// +/// Since GLSL is very strict about types, the following (often used) combinations do not work: +/// double * vec4 +/// int * vec4 +/// vec4 / int +/// So we'll fix that! Of course "float * vec4" should remain the same (hence the enable_if magic) +/// +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "../detail/setup.hpp" + +#if !GLM_HAS_TEMPLATE_ALIASES && !(GLM_COMPILER & GLM_COMPILER_GCC) +# error "GLM_GTX_scalar_multiplication requires C++11 suppport or alias templates and if not support for GCC" +#endif + +#include "../vec2.hpp" +#include "../vec3.hpp" +#include "../vec4.hpp" +#include "../mat2x2.hpp" +#include <type_traits> + +namespace glm +{ + template <typename T, typename Vec> + using return_type_scalar_multiplication = typename std::enable_if< + !std::is_same<T, float>::value // T may not be a float + && std::is_arithmetic<T>::value, Vec // But it may be an int or double (no vec3 or mat3, ...) + >::type; + +#define GLM_IMPLEMENT_SCAL_MULT(Vec) \ + template <typename T> \ + return_type_scalar_multiplication<T, Vec> \ + operator*(T const & s, Vec rh){ \ + return rh *= static_cast<float>(s); \ + } \ + \ + template <typename T> \ + return_type_scalar_multiplication<T, Vec> \ + operator*(Vec lh, T const & s){ \ + return lh *= static_cast<float>(s); \ + } \ + \ + template <typename T> \ + return_type_scalar_multiplication<T, Vec> \ + operator/(Vec lh, T const & s){ \ + return lh *= 1.0f / s; \ + } + +GLM_IMPLEMENT_SCAL_MULT(vec2) +GLM_IMPLEMENT_SCAL_MULT(vec3) +GLM_IMPLEMENT_SCAL_MULT(vec4) + +GLM_IMPLEMENT_SCAL_MULT(mat2) +GLM_IMPLEMENT_SCAL_MULT(mat2x3) +GLM_IMPLEMENT_SCAL_MULT(mat2x4) +GLM_IMPLEMENT_SCAL_MULT(mat3x2) +GLM_IMPLEMENT_SCAL_MULT(mat3) +GLM_IMPLEMENT_SCAL_MULT(mat3x4) +GLM_IMPLEMENT_SCAL_MULT(mat4x2) +GLM_IMPLEMENT_SCAL_MULT(mat4x3) +GLM_IMPLEMENT_SCAL_MULT(mat4) + +#undef GLM_IMPLEMENT_SCAL_MULT +} // namespace glm diff --git a/extensions/common/glm/gtx/scalar_relational.hpp b/extensions/common/glm/gtx/scalar_relational.hpp new file mode 100644 index 0000000000..917af7b429 --- /dev/null +++ b/extensions/common/glm/gtx/scalar_relational.hpp @@ -0,0 +1,61 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_scalar_relational +/// @file glm/gtx/scalar_relational.hpp +/// @date 2013-02-04 / 2013-02-04 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_scalar_relational GLM_GTX_scalar_relational +/// @ingroup gtx +/// +/// @brief Extend a position from a source to a position at a defined length. +/// +/// <glm/gtx/scalar_relational.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_extend extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_scalar_relational + /// @{ + + + + /// @} +}//namespace glm + +#include "scalar_relational.inl" diff --git a/extensions/common/glm/gtx/scalar_relational.inl b/extensions/common/glm/gtx/scalar_relational.inl new file mode 100644 index 0000000000..137edd2168 --- /dev/null +++ b/extensions/common/glm/gtx/scalar_relational.inl @@ -0,0 +1,118 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2012 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_scalar_relational +/// @file glm/gtx/scalar_relational.inl +/// @date 2013-02-04 / 2013-02-04 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T> + GLM_FUNC_QUALIFIER bool lessThan + ( + T const & x, + T const & y + ) + { + return x < y; + } + + template <typename T> + GLM_FUNC_QUALIFIER bool lessThanEqual + ( + T const & x, + T const & y + ) + { + return x <= y; + } + + template <typename T> + GLM_FUNC_QUALIFIER bool greaterThan + ( + T const & x, + T const & y + ) + { + return x > y; + } + + template <typename T> + GLM_FUNC_QUALIFIER bool greaterThanEqual + ( + T const & x, + T const & y + ) + { + return x >= y; + } + + template <typename T> + GLM_FUNC_QUALIFIER bool equal + ( + T const & x, + T const & y + ) + { + return x == y; + } + + template <typename T> + GLM_FUNC_QUALIFIER bool notEqual + ( + T const & x, + T const & y + ) + { + return x != y; + } + + GLM_FUNC_QUALIFIER bool any + ( + bool const & x + ) + { + return x; + } + + GLM_FUNC_QUALIFIER bool all + ( + bool const & x + ) + { + return x; + } + + GLM_FUNC_QUALIFIER bool not_ + ( + bool const & x + ) + { + return !x; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/simd_mat4.hpp b/extensions/common/glm/gtx/simd_mat4.hpp new file mode 100644 index 0000000000..c4b0aa6749 --- /dev/null +++ b/extensions/common/glm/gtx/simd_mat4.hpp @@ -0,0 +1,205 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_simd_mat4 +/// @file glm/gtx/simd_mat4.hpp +/// @date 2009-05-07 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_simd_mat4 GLM_GTX_simd_mat4 +/// @ingroup gtx +/// +/// @brief SIMD implementation of mat4 type. +/// +/// <glm/gtx/simd_mat4.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependencies +#include "../detail/setup.hpp" + +#if(GLM_ARCH != GLM_ARCH_PURE) + +#if(GLM_ARCH & GLM_ARCH_SSE2) +# include "../detail/intrinsic_matrix.hpp" +# include "../gtx/simd_vec4.hpp" +#else +# error "GLM: GLM_GTX_simd_mat4 requires compiler support of SSE2 through intrinsics" +#endif + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_simd_mat4 extension included") +#endif + +namespace glm{ +namespace detail +{ + /// 4x4 Matrix implemented using SIMD SEE intrinsics. + /// \ingroup gtx_simd_mat4 + GLM_ALIGNED_STRUCT(16) fmat4x4SIMD + { + typedef float value_type; + typedef fvec4SIMD col_type; + typedef fvec4SIMD row_type; + typedef std::size_t size_type; + typedef fmat4x4SIMD type; + typedef fmat4x4SIMD transpose_type; + + GLM_FUNC_DECL length_t length() const; + + fvec4SIMD Data[4]; + + ////////////////////////////////////// + // Constructors + + fmat4x4SIMD(); + explicit fmat4x4SIMD(float const & s); + explicit fmat4x4SIMD( + float const & x0, float const & y0, float const & z0, float const & w0, + float const & x1, float const & y1, float const & z1, float const & w1, + float const & x2, float const & y2, float const & z2, float const & w2, + float const & x3, float const & y3, float const & z3, float const & w3); + explicit fmat4x4SIMD( + fvec4SIMD const & v0, + fvec4SIMD const & v1, + fvec4SIMD const & v2, + fvec4SIMD const & v3); + explicit fmat4x4SIMD( + mat4x4 const & m); + explicit fmat4x4SIMD( + __m128 const in[4]); + + // Conversions + //template <typename U> + //explicit tmat4x4(tmat4x4<U> const & m); + + //explicit tmat4x4(tmat2x2<T> const & x); + //explicit tmat4x4(tmat3x3<T> const & x); + //explicit tmat4x4(tmat2x3<T> const & x); + //explicit tmat4x4(tmat3x2<T> const & x); + //explicit tmat4x4(tmat2x4<T> const & x); + //explicit tmat4x4(tmat4x2<T> const & x); + //explicit tmat4x4(tmat3x4<T> const & x); + //explicit tmat4x4(tmat4x3<T> const & x); + + // Accesses + fvec4SIMD & operator[](length_t i); + fvec4SIMD const & operator[](length_t i) const; + + // Unary updatable operators + fmat4x4SIMD & operator= (fmat4x4SIMD const & m); + fmat4x4SIMD & operator+= (float const & s); + fmat4x4SIMD & operator+= (fmat4x4SIMD const & m); + fmat4x4SIMD & operator-= (float const & s); + fmat4x4SIMD & operator-= (fmat4x4SIMD const & m); + fmat4x4SIMD & operator*= (float const & s); + fmat4x4SIMD & operator*= (fmat4x4SIMD const & m); + fmat4x4SIMD & operator/= (float const & s); + fmat4x4SIMD & operator/= (fmat4x4SIMD const & m); + fmat4x4SIMD & operator++ (); + fmat4x4SIMD & operator-- (); + }; + + // Binary operators + fmat4x4SIMD operator+ (fmat4x4SIMD const & m, float const & s); + fmat4x4SIMD operator+ (float const & s, fmat4x4SIMD const & m); + fmat4x4SIMD operator+ (fmat4x4SIMD const & m1, fmat4x4SIMD const & m2); + + fmat4x4SIMD operator- (fmat4x4SIMD const & m, float const & s); + fmat4x4SIMD operator- (float const & s, fmat4x4SIMD const & m); + fmat4x4SIMD operator- (fmat4x4SIMD const & m1, fmat4x4SIMD const & m2); + + fmat4x4SIMD operator* (fmat4x4SIMD const & m, float const & s); + fmat4x4SIMD operator* (float const & s, fmat4x4SIMD const & m); + + fvec4SIMD operator* (fmat4x4SIMD const & m, fvec4SIMD const & v); + fvec4SIMD operator* (fvec4SIMD const & v, fmat4x4SIMD const & m); + + fmat4x4SIMD operator* (fmat4x4SIMD const & m1, fmat4x4SIMD const & m2); + + fmat4x4SIMD operator/ (fmat4x4SIMD const & m, float const & s); + fmat4x4SIMD operator/ (float const & s, fmat4x4SIMD const & m); + + fvec4SIMD operator/ (fmat4x4SIMD const & m, fvec4SIMD const & v); + fvec4SIMD operator/ (fvec4SIMD const & v, fmat4x4SIMD const & m); + + fmat4x4SIMD operator/ (fmat4x4SIMD const & m1, fmat4x4SIMD const & m2); + + // Unary constant operators + fmat4x4SIMD const operator- (fmat4x4SIMD const & m); + fmat4x4SIMD const operator-- (fmat4x4SIMD const & m, int); + fmat4x4SIMD const operator++ (fmat4x4SIMD const & m, int); +}//namespace detail + + typedef detail::fmat4x4SIMD simdMat4; + + /// @addtogroup gtx_simd_mat4 + /// @{ + + //! Convert a simdMat4 to a mat4. + //! (From GLM_GTX_simd_mat4 extension) + mat4 mat4_cast( + detail::fmat4x4SIMD const & x); + + //! Multiply matrix x by matrix y component-wise, i.e., + //! result[i][j] is the scalar product of x[i][j] and y[i][j]. + //! (From GLM_GTX_simd_mat4 extension). + detail::fmat4x4SIMD matrixCompMult( + detail::fmat4x4SIMD const & x, + detail::fmat4x4SIMD const & y); + + //! Treats the first parameter c as a column vector + //! and the second parameter r as a row vector + //! and does a linear algebraic matrix multiply c * r. + //! (From GLM_GTX_simd_mat4 extension). + detail::fmat4x4SIMD outerProduct( + detail::fvec4SIMD const & c, + detail::fvec4SIMD const & r); + + //! Returns the transposed matrix of x + //! (From GLM_GTX_simd_mat4 extension). + detail::fmat4x4SIMD transpose( + detail::fmat4x4SIMD const & x); + + //! Return the determinant of a mat4 matrix. + //! (From GLM_GTX_simd_mat4 extension). + float determinant( + detail::fmat4x4SIMD const & m); + + //! Return the inverse of a mat4 matrix. + //! (From GLM_GTX_simd_mat4 extension). + detail::fmat4x4SIMD inverse( + detail::fmat4x4SIMD const & m); + + /// @} +}// namespace glm + +#include "simd_mat4.inl" + +#endif//(GLM_ARCH != GLM_ARCH_PURE) diff --git a/extensions/common/glm/gtx/simd_mat4.inl b/extensions/common/glm/gtx/simd_mat4.inl new file mode 100644 index 0000000000..b27ef4f2ea --- /dev/null +++ b/extensions/common/glm/gtx/simd_mat4.inl @@ -0,0 +1,602 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_simd_mat4 +/// @file glm/gtx/simd_mat4.inl +/// @date 2009-05-07 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail{ + +GLM_FUNC_QUALIFIER length_t fmat4x4SIMD::length() const +{ + return 4; +} + +////////////////////////////////////// +// Accesses + +GLM_FUNC_QUALIFIER fvec4SIMD & fmat4x4SIMD::operator[] +( + length_t i +) +{ + assert(i < this->length()); + + return this->Data[i]; +} + +GLM_FUNC_QUALIFIER fvec4SIMD const & fmat4x4SIMD::operator[] +( + length_t i +) const +{ + assert(i < this->length()); + + return this->Data[i]; +} + +////////////////////////////////////////////////////////////// +// Constructors + +GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD() +{ +# ifndef GLM_FORCE_NO_CTOR_INIT + this->Data[0] = fvec4SIMD(1, 0, 0, 0); + this->Data[1] = fvec4SIMD(0, 1, 0, 0); + this->Data[2] = fvec4SIMD(0, 0, 1, 0); + this->Data[3] = fvec4SIMD(0, 0, 0, 1); +# endif +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD(float const & s) +{ + this->Data[0] = fvec4SIMD(s, 0, 0, 0); + this->Data[1] = fvec4SIMD(0, s, 0, 0); + this->Data[2] = fvec4SIMD(0, 0, s, 0); + this->Data[3] = fvec4SIMD(0, 0, 0, s); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD +( + float const & x0, float const & y0, float const & z0, float const & w0, + float const & x1, float const & y1, float const & z1, float const & w1, + float const & x2, float const & y2, float const & z2, float const & w2, + float const & x3, float const & y3, float const & z3, float const & w3 +) +{ + this->Data[0] = fvec4SIMD(x0, y0, z0, w0); + this->Data[1] = fvec4SIMD(x1, y1, z1, w1); + this->Data[2] = fvec4SIMD(x2, y2, z2, w2); + this->Data[3] = fvec4SIMD(x3, y3, z3, w3); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD +( + fvec4SIMD const & v0, + fvec4SIMD const & v1, + fvec4SIMD const & v2, + fvec4SIMD const & v3 +) +{ + this->Data[0] = v0; + this->Data[1] = v1; + this->Data[2] = v2; + this->Data[3] = v3; +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD +( + mat4 const & m +) +{ + this->Data[0] = fvec4SIMD(m[0]); + this->Data[1] = fvec4SIMD(m[1]); + this->Data[2] = fvec4SIMD(m[2]); + this->Data[3] = fvec4SIMD(m[3]); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD +( + __m128 const in[4] +) +{ + this->Data[0] = in[0]; + this->Data[1] = in[1]; + this->Data[2] = in[2]; + this->Data[3] = in[3]; +} + +////////////////////////////////////////////////////////////// +// mat4 operators + +GLM_FUNC_QUALIFIER fmat4x4SIMD& fmat4x4SIMD::operator= +( + fmat4x4SIMD const & m +) +{ + this->Data[0] = m[0]; + this->Data[1] = m[1]; + this->Data[2] = m[2]; + this->Data[3] = m[3]; + return *this; +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator+= +( + fmat4x4SIMD const & m +) +{ + this->Data[0].Data = _mm_add_ps(this->Data[0].Data, m[0].Data); + this->Data[1].Data = _mm_add_ps(this->Data[1].Data, m[1].Data); + this->Data[2].Data = _mm_add_ps(this->Data[2].Data, m[2].Data); + this->Data[3].Data = _mm_add_ps(this->Data[3].Data, m[3].Data); + return *this; +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator-= +( + fmat4x4SIMD const & m +) +{ + this->Data[0].Data = _mm_sub_ps(this->Data[0].Data, m[0].Data); + this->Data[1].Data = _mm_sub_ps(this->Data[1].Data, m[1].Data); + this->Data[2].Data = _mm_sub_ps(this->Data[2].Data, m[2].Data); + this->Data[3].Data = _mm_sub_ps(this->Data[3].Data, m[3].Data); + + return *this; +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator*= +( + fmat4x4SIMD const & m +) +{ + sse_mul_ps(&this->Data[0].Data, &m.Data[0].Data, &this->Data[0].Data); + return *this; +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator/= +( + fmat4x4SIMD const & m +) +{ + __m128 Inv[4]; + sse_inverse_ps(&m.Data[0].Data, Inv); + sse_mul_ps(&this->Data[0].Data, Inv, &this->Data[0].Data); + return *this; +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator+= +( + float const & s +) +{ + __m128 Operand = _mm_set_ps1(s); + this->Data[0].Data = _mm_add_ps(this->Data[0].Data, Operand); + this->Data[1].Data = _mm_add_ps(this->Data[1].Data, Operand); + this->Data[2].Data = _mm_add_ps(this->Data[2].Data, Operand); + this->Data[3].Data = _mm_add_ps(this->Data[3].Data, Operand); + return *this; +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator-= +( + float const & s +) +{ + __m128 Operand = _mm_set_ps1(s); + this->Data[0].Data = _mm_sub_ps(this->Data[0].Data, Operand); + this->Data[1].Data = _mm_sub_ps(this->Data[1].Data, Operand); + this->Data[2].Data = _mm_sub_ps(this->Data[2].Data, Operand); + this->Data[3].Data = _mm_sub_ps(this->Data[3].Data, Operand); + return *this; +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator*= +( + float const & s +) +{ + __m128 Operand = _mm_set_ps1(s); + this->Data[0].Data = _mm_mul_ps(this->Data[0].Data, Operand); + this->Data[1].Data = _mm_mul_ps(this->Data[1].Data, Operand); + this->Data[2].Data = _mm_mul_ps(this->Data[2].Data, Operand); + this->Data[3].Data = _mm_mul_ps(this->Data[3].Data, Operand); + return *this; +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator/= +( + float const & s +) +{ + __m128 Operand = _mm_div_ps(one, _mm_set_ps1(s)); + this->Data[0].Data = _mm_mul_ps(this->Data[0].Data, Operand); + this->Data[1].Data = _mm_mul_ps(this->Data[1].Data, Operand); + this->Data[2].Data = _mm_mul_ps(this->Data[2].Data, Operand); + this->Data[3].Data = _mm_mul_ps(this->Data[3].Data, Operand); + return *this; +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator++ () +{ + this->Data[0].Data = _mm_add_ps(this->Data[0].Data, one); + this->Data[1].Data = _mm_add_ps(this->Data[1].Data, one); + this->Data[2].Data = _mm_add_ps(this->Data[2].Data, one); + this->Data[3].Data = _mm_add_ps(this->Data[3].Data, one); + return *this; +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator-- () +{ + this->Data[0].Data = _mm_sub_ps(this->Data[0].Data, one); + this->Data[1].Data = _mm_sub_ps(this->Data[1].Data, one); + this->Data[2].Data = _mm_sub_ps(this->Data[2].Data, one); + this->Data[3].Data = _mm_sub_ps(this->Data[3].Data, one); + return *this; +} + + +////////////////////////////////////////////////////////////// +// Binary operators + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator+ +( + const fmat4x4SIMD &m, + float const & s +) +{ + return detail::fmat4x4SIMD + ( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s + ); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator+ +( + float const & s, + const fmat4x4SIMD &m +) +{ + return detail::fmat4x4SIMD + ( + m[0] + s, + m[1] + s, + m[2] + s, + m[3] + s + ); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator+ +( + const fmat4x4SIMD &m1, + const fmat4x4SIMD &m2 +) +{ + return detail::fmat4x4SIMD + ( + m1[0] + m2[0], + m1[1] + m2[1], + m1[2] + m2[2], + m1[3] + m2[3] + ); +} + + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator- +( + const fmat4x4SIMD &m, + float const & s +) +{ + return detail::fmat4x4SIMD + ( + m[0] - s, + m[1] - s, + m[2] - s, + m[3] - s + ); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator- +( + float const & s, + const fmat4x4SIMD &m +) +{ + return detail::fmat4x4SIMD + ( + s - m[0], + s - m[1], + s - m[2], + s - m[3] + ); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator- +( + const fmat4x4SIMD &m1, + const fmat4x4SIMD &m2 +) +{ + return detail::fmat4x4SIMD + ( + m1[0] - m2[0], + m1[1] - m2[1], + m1[2] - m2[2], + m1[3] - m2[3] + ); +} + + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator* +( + const fmat4x4SIMD &m, + float const & s +) +{ + return detail::fmat4x4SIMD + ( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s + ); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator* +( + float const & s, + const fmat4x4SIMD &m +) +{ + return detail::fmat4x4SIMD + ( + m[0] * s, + m[1] * s, + m[2] * s, + m[3] * s + ); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator* +( + const fmat4x4SIMD &m, + fvec4SIMD const & v +) +{ + return sse_mul_ps(&m.Data[0].Data, v.Data); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator* +( + fvec4SIMD const & v, + const fmat4x4SIMD &m +) +{ + return sse_mul_ps(v.Data, &m.Data[0].Data); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator* +( + const fmat4x4SIMD &m1, + const fmat4x4SIMD &m2 +) +{ + fmat4x4SIMD result; + sse_mul_ps(&m1.Data[0].Data, &m2.Data[0].Data, &result.Data[0].Data); + + return result; +} + + + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator/ +( + const fmat4x4SIMD &m, + float const & s +) +{ + return detail::fmat4x4SIMD + ( + m[0] / s, + m[1] / s, + m[2] / s, + m[3] / s + ); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator/ +( + float const & s, + const fmat4x4SIMD &m +) +{ + return detail::fmat4x4SIMD + ( + s / m[0], + s / m[1], + s / m[2], + s / m[3] + ); +} + +GLM_FUNC_QUALIFIER detail::fmat4x4SIMD inverse(detail::fmat4x4SIMD const & m) +{ + detail::fmat4x4SIMD result; + detail::sse_inverse_ps(&m[0].Data, &result[0].Data); + return result; +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator/ +( + const fmat4x4SIMD & m, + fvec4SIMD const & v +) +{ + return inverse(m) * v; +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator/ +( + fvec4SIMD const & v, + const fmat4x4SIMD &m +) +{ + return v * inverse(m); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD operator/ +( + const fmat4x4SIMD &m1, + const fmat4x4SIMD &m2 +) +{ + __m128 result[4]; + __m128 inv[4]; + + sse_inverse_ps(&m2.Data[0].Data, inv); + sse_mul_ps(&m1.Data[0].Data, inv, result); + + return fmat4x4SIMD(result); +} + + +////////////////////////////////////////////////////////////// +// Unary constant operators +GLM_FUNC_QUALIFIER fmat4x4SIMD const operator- +( + fmat4x4SIMD const & m +) +{ + return detail::fmat4x4SIMD + ( + -m[0], + -m[1], + -m[2], + -m[3] + ); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD const operator-- +( + fmat4x4SIMD const & m, + int +) +{ + return detail::fmat4x4SIMD + ( + m[0] - 1.0f, + m[1] - 1.0f, + m[2] - 1.0f, + m[3] - 1.0f + ); +} + +GLM_FUNC_QUALIFIER fmat4x4SIMD const operator++ +( + fmat4x4SIMD const & m, + int +) +{ + return detail::fmat4x4SIMD + ( + m[0] + 1.0f, + m[1] + 1.0f, + m[2] + 1.0f, + m[3] + 1.0f + ); +} + +}//namespace detail + +GLM_FUNC_QUALIFIER mat4 mat4_cast +( + detail::fmat4x4SIMD const & x +) +{ + GLM_ALIGN(16) mat4 Result; + _mm_store_ps(&Result[0][0], x.Data[0].Data); + _mm_store_ps(&Result[1][0], x.Data[1].Data); + _mm_store_ps(&Result[2][0], x.Data[2].Data); + _mm_store_ps(&Result[3][0], x.Data[3].Data); + return Result; +} + +GLM_FUNC_QUALIFIER detail::fmat4x4SIMD matrixCompMult +( + detail::fmat4x4SIMD const & x, + detail::fmat4x4SIMD const & y +) +{ + detail::fmat4x4SIMD result; + result[0] = x[0] * y[0]; + result[1] = x[1] * y[1]; + result[2] = x[2] * y[2]; + result[3] = x[3] * y[3]; + return result; +} + +GLM_FUNC_QUALIFIER detail::fmat4x4SIMD outerProduct +( + detail::fvec4SIMD const & c, + detail::fvec4SIMD const & r +) +{ + __m128 Shu0 = _mm_shuffle_ps(r.Data, r.Data, _MM_SHUFFLE(0, 0, 0, 0)); + __m128 Shu1 = _mm_shuffle_ps(r.Data, r.Data, _MM_SHUFFLE(1, 1, 1, 1)); + __m128 Shu2 = _mm_shuffle_ps(r.Data, r.Data, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 Shu3 = _mm_shuffle_ps(r.Data, r.Data, _MM_SHUFFLE(3, 3, 3, 3)); + + detail::fmat4x4SIMD result(uninitialize); + result[0].Data = _mm_mul_ps(c.Data, Shu0); + result[1].Data = _mm_mul_ps(c.Data, Shu1); + result[2].Data = _mm_mul_ps(c.Data, Shu2); + result[3].Data = _mm_mul_ps(c.Data, Shu3); + return result; +} + +GLM_FUNC_QUALIFIER detail::fmat4x4SIMD transpose(detail::fmat4x4SIMD const & m) +{ + detail::fmat4x4SIMD result; + detail::sse_transpose_ps(&m[0].Data, &result[0].Data); + return result; +} + +GLM_FUNC_QUALIFIER float determinant(detail::fmat4x4SIMD const & m) +{ + float Result; + _mm_store_ss(&Result, detail::sse_det_ps(&m[0].Data)); + return Result; +} + +}//namespace glm diff --git a/extensions/common/glm/gtx/simd_quat.hpp b/extensions/common/glm/gtx/simd_quat.hpp new file mode 100644 index 0000000000..643cade660 --- /dev/null +++ b/extensions/common/glm/gtx/simd_quat.hpp @@ -0,0 +1,335 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_simd_quat +/// @file glm/gtx/simd_quat.hpp +/// @date 2013-04-22 / 2014-11-25 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_simd_quat GLM_GTX_simd_quat +/// @ingroup gtx +/// +/// @brief SIMD implementation of quat type. +/// +/// <glm/gtx/simd_quat.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/quaternion.hpp" +#include "../gtx/fast_trigonometry.hpp" + +#if(GLM_ARCH != GLM_ARCH_PURE) + +#if(GLM_ARCH & GLM_ARCH_SSE2) +# include "../gtx/simd_mat4.hpp" +#else +# error "GLM: GLM_GTX_simd_quat requires compiler support of SSE2 through intrinsics" +#endif + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_simd_quat extension included") +#endif + +// Warning silencer for nameless struct/union. +#if (GLM_COMPILER & GLM_COMPILER_VC) +# pragma warning(push) +# pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union +#endif + +namespace glm{ +namespace detail +{ + GLM_ALIGNED_STRUCT(16) fquatSIMD + { + typedef __m128 value_type; + typedef std::size_t size_type; + static size_type value_size(); + + typedef fquatSIMD type; + typedef tquat<bool, defaultp> bool_type; + +#ifdef GLM_SIMD_ENABLE_XYZW_UNION + union + { + __m128 Data; + struct {float x, y, z, w;}; + }; +#else + __m128 Data; +#endif + + ////////////////////////////////////// + // Implicit basic constructors + + fquatSIMD(); + fquatSIMD(__m128 const & Data); + fquatSIMD(fquatSIMD const & q); + + ////////////////////////////////////// + // Explicit basic constructors + + explicit fquatSIMD( + ctor); + explicit fquatSIMD( + float const & w, + float const & x, + float const & y, + float const & z); + explicit fquatSIMD( + quat const & v); + explicit fquatSIMD( + vec3 const & eulerAngles); + + + ////////////////////////////////////// + // Unary arithmetic operators + + fquatSIMD& operator =(fquatSIMD const & q); + fquatSIMD& operator*=(float const & s); + fquatSIMD& operator/=(float const & s); + }; + + + ////////////////////////////////////// + // Arithmetic operators + + detail::fquatSIMD operator- ( + detail::fquatSIMD const & q); + + detail::fquatSIMD operator+ ( + detail::fquatSIMD const & q, + detail::fquatSIMD const & p); + + detail::fquatSIMD operator* ( + detail::fquatSIMD const & q, + detail::fquatSIMD const & p); + + detail::fvec4SIMD operator* ( + detail::fquatSIMD const & q, + detail::fvec4SIMD const & v); + + detail::fvec4SIMD operator* ( + detail::fvec4SIMD const & v, + detail::fquatSIMD const & q); + + detail::fquatSIMD operator* ( + detail::fquatSIMD const & q, + float s); + + detail::fquatSIMD operator* ( + float s, + detail::fquatSIMD const & q); + + detail::fquatSIMD operator/ ( + detail::fquatSIMD const & q, + float s); + +}//namespace detail + + /// @addtogroup gtx_simd_quat + /// @{ + + typedef glm::detail::fquatSIMD simdQuat; + + //! Convert a simdQuat to a quat. + /// @see gtx_simd_quat + quat quat_cast( + detail::fquatSIMD const & x); + + //! Convert a simdMat4 to a simdQuat. + /// @see gtx_simd_quat + detail::fquatSIMD quatSIMD_cast( + detail::fmat4x4SIMD const & m); + + //! Converts a mat4 to a simdQuat. + /// @see gtx_simd_quat + template <typename T, precision P> + detail::fquatSIMD quatSIMD_cast( + tmat4x4<T, P> const & m); + + //! Converts a mat3 to a simdQuat. + /// @see gtx_simd_quat + template <typename T, precision P> + detail::fquatSIMD quatSIMD_cast( + tmat3x3<T, P> const & m); + + //! Convert a simdQuat to a simdMat4 + /// @see gtx_simd_quat + detail::fmat4x4SIMD mat4SIMD_cast( + detail::fquatSIMD const & q); + + //! Converts a simdQuat to a standard mat4. + /// @see gtx_simd_quat + mat4 mat4_cast( + detail::fquatSIMD const & q); + + + /// Returns the length of the quaternion. + /// + /// @see gtx_simd_quat + float length( + detail::fquatSIMD const & x); + + /// Returns the normalized quaternion. + /// + /// @see gtx_simd_quat + detail::fquatSIMD normalize( + detail::fquatSIMD const & x); + + /// Returns dot product of q1 and q2, i.e., q1[0] * q2[0] + q1[1] * q2[1] + ... + /// + /// @see gtx_simd_quat + float dot( + detail::fquatSIMD const & q1, + detail::fquatSIMD const & q2); + + /// Spherical linear interpolation of two quaternions. + /// The interpolation is oriented and the rotation is performed at constant speed. + /// For short path spherical linear interpolation, use the slerp function. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// @tparam T Value type used to build the quaternion. Supported: half, float or double. + /// @see gtx_simd_quat + /// @see - slerp(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a) + detail::fquatSIMD mix( + detail::fquatSIMD const & x, + detail::fquatSIMD const & y, + float const & a); + + /// Linear interpolation of two quaternions. + /// The interpolation is oriented. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined in the range [0, 1]. + /// @tparam T Value type used to build the quaternion. Supported: half, float or double. + /// @see gtx_simd_quat + detail::fquatSIMD lerp( + detail::fquatSIMD const & x, + detail::fquatSIMD const & y, + float const & a); + + /// Spherical linear interpolation of two quaternions. + /// The interpolation always take the short path and the rotation is performed at constant speed. + /// + /// @param x A quaternion + /// @param y A quaternion + /// @param a Interpolation factor. The interpolation is defined beyond the range [0, 1]. + /// @tparam T Value type used to build the quaternion. Supported: half, float or double. + /// @see gtx_simd_quat + detail::fquatSIMD slerp( + detail::fquatSIMD const & x, + detail::fquatSIMD const & y, + float const & a); + + + /// Faster spherical linear interpolation of two unit length quaternions. + /// + /// This is the same as mix(), except for two rules: + /// 1) The two quaternions must be unit length. + /// 2) The interpolation factor (a) must be in the range [0, 1]. + /// + /// This will use the equivalent to fastAcos() and fastSin(). + /// + /// @see gtx_simd_quat + /// @see - mix(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a) + detail::fquatSIMD fastMix( + detail::fquatSIMD const & x, + detail::fquatSIMD const & y, + float const & a); + + /// Identical to fastMix() except takes the shortest path. + /// + /// The same rules apply here as those in fastMix(). Both quaternions must be unit length and 'a' must be + /// in the range [0, 1]. + /// + /// @see - fastMix(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a) + /// @see - slerp(detail::fquatSIMD const & x, detail::fquatSIMD const & y, T const & a) + detail::fquatSIMD fastSlerp( + detail::fquatSIMD const & x, + detail::fquatSIMD const & y, + float const & a); + + + /// Returns the q conjugate. + /// + /// @see gtx_simd_quat + detail::fquatSIMD conjugate( + detail::fquatSIMD const & q); + + /// Returns the q inverse. + /// + /// @see gtx_simd_quat + detail::fquatSIMD inverse( + detail::fquatSIMD const & q); + + /// Build a quaternion from an angle and a normalized axis. + /// + /// @param angle Angle expressed in radians. + /// @param axis Axis of the quaternion, must be normalized. + /// + /// @see gtx_simd_quat + detail::fquatSIMD angleAxisSIMD( + float const & angle, + vec3 const & axis); + + /// Build a quaternion from an angle and a normalized axis. + /// + /// @param angle Angle expressed in radians. + /// @param x x component of the x-axis, x, y, z must be a normalized axis + /// @param y y component of the y-axis, x, y, z must be a normalized axis + /// @param z z component of the z-axis, x, y, z must be a normalized axis + /// + /// @see gtx_simd_quat + detail::fquatSIMD angleAxisSIMD( + float const & angle, + float const & x, + float const & y, + float const & z); + + // TODO: Move this to somewhere more appropriate. Used with fastMix() and fastSlerp(). + /// Performs the equivalent of glm::fastSin() on each component of the given __m128. + __m128 fastSin(__m128 x); + + /// @} +}//namespace glm + +#include "simd_quat.inl" + + +#if (GLM_COMPILER & GLM_COMPILER_VC) +# pragma warning(pop) +#endif + + +#endif//(GLM_ARCH != GLM_ARCH_PURE) diff --git a/extensions/common/glm/gtx/simd_quat.inl b/extensions/common/glm/gtx/simd_quat.inl new file mode 100644 index 0000000000..58bbddffea --- /dev/null +++ b/extensions/common/glm/gtx/simd_quat.inl @@ -0,0 +1,645 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_simd_quat +/// @file glm/gtx/simd_quat.inl +/// @date 2013-04-22 / 2014-11-25 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail{ + + +////////////////////////////////////// +// Debugging +#if 0 +void print(__m128 v) +{ + GLM_ALIGN(16) float result[4]; + _mm_store_ps(result, v); + + printf("__m128: %f %f %f %f\n", result[0], result[1], result[2], result[3]); +} + +void print(const fvec4SIMD &v) +{ + printf("fvec4SIMD: %f %f %f %f\n", v.x, v.y, v.z, v.w); +} +#endif + + +////////////////////////////////////// +// Implicit basic constructors + +GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD() +# ifdef GLM_FORCE_NO_CTOR_INIT + : Data(_mm_set_ps(1.0f, 0.0f, 0.0f, 0.0f)) +# endif +{} + +GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD(__m128 const & Data) : + Data(Data) +{} + +GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD(fquatSIMD const & q) : + Data(q.Data) +{} + + +////////////////////////////////////// +// Explicit basic constructors + +GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD(float const & w, float const & x, float const & y, float const & z) : + Data(_mm_set_ps(w, z, y, x)) +{} + +GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD(quat const & q) : + Data(_mm_set_ps(q.w, q.z, q.y, q.x)) +{} + +GLM_FUNC_QUALIFIER fquatSIMD::fquatSIMD(vec3 const & eulerAngles) +{ + vec3 c = glm::cos(eulerAngles * 0.5f); + vec3 s = glm::sin(eulerAngles * 0.5f); + + Data = _mm_set_ps( + (c.x * c.y * c.z) + (s.x * s.y * s.z), + (c.x * c.y * s.z) - (s.x * s.y * c.z), + (c.x * s.y * c.z) + (s.x * c.y * s.z), + (s.x * c.y * c.z) - (c.x * s.y * s.z)); +} + + +////////////////////////////////////// +// Unary arithmetic operators + +GLM_FUNC_QUALIFIER fquatSIMD& fquatSIMD::operator=(fquatSIMD const & q) +{ + this->Data = q.Data; + return *this; +} + +GLM_FUNC_QUALIFIER fquatSIMD& fquatSIMD::operator*=(float const & s) +{ + this->Data = _mm_mul_ps(this->Data, _mm_set_ps1(s)); + return *this; +} + +GLM_FUNC_QUALIFIER fquatSIMD& fquatSIMD::operator/=(float const & s) +{ + this->Data = _mm_div_ps(Data, _mm_set1_ps(s)); + return *this; +} + + + +// negate operator +GLM_FUNC_QUALIFIER fquatSIMD operator- (fquatSIMD const & q) +{ + return fquatSIMD(_mm_mul_ps(q.Data, _mm_set_ps(-1.0f, -1.0f, -1.0f, -1.0f))); +} + +// operator+ +GLM_FUNC_QUALIFIER fquatSIMD operator+ (fquatSIMD const & q1, fquatSIMD const & q2) +{ + return fquatSIMD(_mm_add_ps(q1.Data, q2.Data)); +} + +//operator* +GLM_FUNC_QUALIFIER fquatSIMD operator* (fquatSIMD const & q1, fquatSIMD const & q2) +{ + // SSE2 STATS: + // 11 shuffle + // 8 mul + // 8 add + + // SSE4 STATS: + // 3 shuffle + // 4 mul + // 4 dpps + + __m128 mul0 = _mm_mul_ps(q1.Data, _mm_shuffle_ps(q2.Data, q2.Data, _MM_SHUFFLE(0, 1, 2, 3))); + __m128 mul1 = _mm_mul_ps(q1.Data, _mm_shuffle_ps(q2.Data, q2.Data, _MM_SHUFFLE(1, 0, 3, 2))); + __m128 mul2 = _mm_mul_ps(q1.Data, _mm_shuffle_ps(q2.Data, q2.Data, _MM_SHUFFLE(2, 3, 0, 1))); + __m128 mul3 = _mm_mul_ps(q1.Data, q2.Data); + +# if((GLM_ARCH & GLM_ARCH_SSE4)) + __m128 add0 = _mm_dp_ps(mul0, _mm_set_ps(1.0f, -1.0f, 1.0f, 1.0f), 0xff); + __m128 add1 = _mm_dp_ps(mul1, _mm_set_ps(1.0f, 1.0f, 1.0f, -1.0f), 0xff); + __m128 add2 = _mm_dp_ps(mul2, _mm_set_ps(1.0f, 1.0f, -1.0f, 1.0f), 0xff); + __m128 add3 = _mm_dp_ps(mul3, _mm_set_ps(1.0f, -1.0f, -1.0f, -1.0f), 0xff); +# else + mul0 = _mm_mul_ps(mul0, _mm_set_ps(1.0f, -1.0f, 1.0f, 1.0f)); + __m128 add0 = _mm_add_ps(mul0, _mm_movehl_ps(mul0, mul0)); + add0 = _mm_add_ss(add0, _mm_shuffle_ps(add0, add0, 1)); + + mul1 = _mm_mul_ps(mul1, _mm_set_ps(1.0f, 1.0f, 1.0f, -1.0f)); + __m128 add1 = _mm_add_ps(mul1, _mm_movehl_ps(mul1, mul1)); + add1 = _mm_add_ss(add1, _mm_shuffle_ps(add1, add1, 1)); + + mul2 = _mm_mul_ps(mul2, _mm_set_ps(1.0f, 1.0f, -1.0f, 1.0f)); + __m128 add2 = _mm_add_ps(mul2, _mm_movehl_ps(mul2, mul2)); + add2 = _mm_add_ss(add2, _mm_shuffle_ps(add2, add2, 1)); + + mul3 = _mm_mul_ps(mul3, _mm_set_ps(1.0f, -1.0f, -1.0f, -1.0f)); + __m128 add3 = _mm_add_ps(mul3, _mm_movehl_ps(mul3, mul3)); + add3 = _mm_add_ss(add3, _mm_shuffle_ps(add3, add3, 1)); +#endif + + + // This SIMD code is a politically correct way of doing this, but in every test I've tried it has been slower than + // the final code below. I'll keep this here for reference - maybe somebody else can do something better... + // + //__m128 xxyy = _mm_shuffle_ps(add0, add1, _MM_SHUFFLE(0, 0, 0, 0)); + //__m128 zzww = _mm_shuffle_ps(add2, add3, _MM_SHUFFLE(0, 0, 0, 0)); + // + //return _mm_shuffle_ps(xxyy, zzww, _MM_SHUFFLE(2, 0, 2, 0)); + + float x; + float y; + float z; + float w; + + _mm_store_ss(&x, add0); + _mm_store_ss(&y, add1); + _mm_store_ss(&z, add2); + _mm_store_ss(&w, add3); + + return detail::fquatSIMD(w, x, y, z); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator* (fquatSIMD const & q, fvec4SIMD const & v) +{ + static const __m128 two = _mm_set1_ps(2.0f); + + __m128 q_wwww = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 3, 3, 3)); + __m128 q_swp0 = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 q_swp1 = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 v_swp0 = _mm_shuffle_ps(v.Data, v.Data, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 v_swp1 = _mm_shuffle_ps(v.Data, v.Data, _MM_SHUFFLE(3, 1, 0, 2)); + + __m128 uv = _mm_sub_ps(_mm_mul_ps(q_swp0, v_swp1), _mm_mul_ps(q_swp1, v_swp0)); + __m128 uv_swp0 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 0, 2, 1)); + __m128 uv_swp1 = _mm_shuffle_ps(uv, uv, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 uuv = _mm_sub_ps(_mm_mul_ps(q_swp0, uv_swp1), _mm_mul_ps(q_swp1, uv_swp0)); + + + uv = _mm_mul_ps(uv, _mm_mul_ps(q_wwww, two)); + uuv = _mm_mul_ps(uuv, two); + + return _mm_add_ps(v.Data, _mm_add_ps(uv, uuv)); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator* (fvec4SIMD const & v, fquatSIMD const & q) +{ + return glm::inverse(q) * v; +} + +GLM_FUNC_QUALIFIER fquatSIMD operator* (fquatSIMD const & q, float s) +{ + return fquatSIMD(_mm_mul_ps(q.Data, _mm_set1_ps(s))); +} + +GLM_FUNC_QUALIFIER fquatSIMD operator* (float s, fquatSIMD const & q) +{ + return fquatSIMD(_mm_mul_ps(_mm_set1_ps(s), q.Data)); +} + + +//operator/ +GLM_FUNC_QUALIFIER fquatSIMD operator/ (fquatSIMD const & q, float s) +{ + return fquatSIMD(_mm_div_ps(q.Data, _mm_set1_ps(s))); +} + + +}//namespace detail + + +GLM_FUNC_QUALIFIER quat quat_cast +( + detail::fquatSIMD const & x +) +{ + GLM_ALIGN(16) quat Result; + _mm_store_ps(&Result[0], x.Data); + + return Result; +} + +template <typename T> +GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast_impl(const T m0[], const T m1[], const T m2[]) +{ + T trace = m0[0] + m1[1] + m2[2] + T(1.0); + if (trace > T(0)) + { + T s = static_cast<T>(0.5) / sqrt(trace); + + return _mm_set_ps( + static_cast<float>(T(0.25) / s), + static_cast<float>((m0[1] - m1[0]) * s), + static_cast<float>((m2[0] - m0[2]) * s), + static_cast<float>((m1[2] - m2[1]) * s)); + } + else + { + if (m0[0] > m1[1]) + { + if (m0[0] > m2[2]) + { + // X is biggest. + T s = sqrt(m0[0] - m1[1] - m2[2] + T(1.0)) * T(0.5); + + return _mm_set_ps( + static_cast<float>((m1[2] - m2[1]) * s), + static_cast<float>((m2[0] + m0[2]) * s), + static_cast<float>((m0[1] + m1[0]) * s), + static_cast<float>(T(0.5) * s)); + } + } + else + { + if (m1[1] > m2[2]) + { + // Y is biggest. + T s = sqrt(m1[1] - m0[0] - m2[2] + T(1.0)) * T(0.5); + + return _mm_set_ps( + static_cast<float>((m2[0] - m0[2]) * s), + static_cast<float>((m1[2] + m2[1]) * s), + static_cast<float>(T(0.5) * s), + static_cast<float>((m0[1] + m1[0]) * s)); + } + } + + // Z is biggest. + T s = sqrt(m2[2] - m0[0] - m1[1] + T(1.0)) * T(0.5); + + return _mm_set_ps( + static_cast<float>((m0[1] - m1[0]) * s), + static_cast<float>(T(0.5) * s), + static_cast<float>((m1[2] + m2[1]) * s), + static_cast<float>((m2[0] + m0[2]) * s)); + } +} + +GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast +( + detail::fmat4x4SIMD const & m +) +{ + // Scalar implementation for now. + GLM_ALIGN(16) float m0[4]; + GLM_ALIGN(16) float m1[4]; + GLM_ALIGN(16) float m2[4]; + + _mm_store_ps(m0, m[0].Data); + _mm_store_ps(m1, m[1].Data); + _mm_store_ps(m2, m[2].Data); + + return quatSIMD_cast_impl(m0, m1, m2); +} + +template <typename T, precision P> +GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast +( + tmat4x4<T, P> const & m +) +{ + return quatSIMD_cast_impl(&m[0][0], &m[1][0], &m[2][0]); +} + +template <typename T, precision P> +GLM_FUNC_QUALIFIER detail::fquatSIMD quatSIMD_cast +( + tmat3x3<T, P> const & m +) +{ + return quatSIMD_cast_impl(&m[0][0], &m[1][0], &m[2][0]); +} + + +GLM_FUNC_QUALIFIER detail::fmat4x4SIMD mat4SIMD_cast +( + detail::fquatSIMD const & q +) +{ + detail::fmat4x4SIMD result; + + __m128 _wwww = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 3, 3, 3)); + __m128 _xyzw = q.Data; + __m128 _zxyw = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 _yzxw = _mm_shuffle_ps(q.Data, q.Data, _MM_SHUFFLE(3, 0, 2, 1)); + + __m128 _xyzw2 = _mm_add_ps(_xyzw, _xyzw); + __m128 _zxyw2 = _mm_shuffle_ps(_xyzw2, _xyzw2, _MM_SHUFFLE(3, 1, 0, 2)); + __m128 _yzxw2 = _mm_shuffle_ps(_xyzw2, _xyzw2, _MM_SHUFFLE(3, 0, 2, 1)); + + __m128 _tmp0 = _mm_sub_ps(_mm_set1_ps(1.0f), _mm_mul_ps(_yzxw2, _yzxw)); + _tmp0 = _mm_sub_ps(_tmp0, _mm_mul_ps(_zxyw2, _zxyw)); + + __m128 _tmp1 = _mm_mul_ps(_yzxw2, _xyzw); + _tmp1 = _mm_add_ps(_tmp1, _mm_mul_ps(_zxyw2, _wwww)); + + __m128 _tmp2 = _mm_mul_ps(_zxyw2, _xyzw); + _tmp2 = _mm_sub_ps(_tmp2, _mm_mul_ps(_yzxw2, _wwww)); + + + // There's probably a better, more politically correct way of doing this... + result[0].Data = _mm_set_ps( + 0.0f, + reinterpret_cast<float*>(&_tmp2)[0], + reinterpret_cast<float*>(&_tmp1)[0], + reinterpret_cast<float*>(&_tmp0)[0]); + + result[1].Data = _mm_set_ps( + 0.0f, + reinterpret_cast<float*>(&_tmp1)[1], + reinterpret_cast<float*>(&_tmp0)[1], + reinterpret_cast<float*>(&_tmp2)[1]); + + result[2].Data = _mm_set_ps( + 0.0f, + reinterpret_cast<float*>(&_tmp0)[2], + reinterpret_cast<float*>(&_tmp2)[2], + reinterpret_cast<float*>(&_tmp1)[2]); + + result[3].Data = _mm_set_ps( + 1.0f, + 0.0f, + 0.0f, + 0.0f); + + + return result; +} + +GLM_FUNC_QUALIFIER mat4 mat4_cast +( + detail::fquatSIMD const & q +) +{ + return mat4_cast(mat4SIMD_cast(q)); +} + + + +GLM_FUNC_QUALIFIER float length +( + detail::fquatSIMD const & q +) +{ + return glm::sqrt(dot(q, q)); +} + +GLM_FUNC_QUALIFIER detail::fquatSIMD normalize +( + detail::fquatSIMD const & q +) +{ + return _mm_mul_ps(q.Data, _mm_set1_ps(1.0f / length(q))); +} + +GLM_FUNC_QUALIFIER float dot +( + detail::fquatSIMD const & q1, + detail::fquatSIMD const & q2 +) +{ + float result; + _mm_store_ss(&result, detail::sse_dot_ps(q1.Data, q2.Data)); + + return result; +} + +GLM_FUNC_QUALIFIER detail::fquatSIMD mix +( + detail::fquatSIMD const & x, + detail::fquatSIMD const & y, + float const & a +) +{ + float cosTheta = dot(x, y); + + if (cosTheta > 1.0f - glm::epsilon<float>()) + { + return _mm_add_ps(x.Data, _mm_mul_ps(_mm_set1_ps(a), _mm_sub_ps(y.Data, x.Data))); + } + else + { + float angle = glm::acos(cosTheta); + + + float s0 = glm::sin((1.0f - a) * angle); + float s1 = glm::sin(a * angle); + float d = 1.0f / glm::sin(angle); + + return (s0 * x + s1 * y) * d; + } +} + +GLM_FUNC_QUALIFIER detail::fquatSIMD lerp +( + detail::fquatSIMD const & x, + detail::fquatSIMD const & y, + float const & a +) +{ + // Lerp is only defined in [0, 1] + assert(a >= 0.0f); + assert(a <= 1.0f); + + return _mm_add_ps(x.Data, _mm_mul_ps(_mm_set1_ps(a), _mm_sub_ps(y.Data, x.Data))); +} + +GLM_FUNC_QUALIFIER detail::fquatSIMD slerp +( + detail::fquatSIMD const & x, + detail::fquatSIMD const & y, + float const & a +) +{ + detail::fquatSIMD z = y; + + float cosTheta = dot(x, y); + + // If cosTheta < 0, the interpolation will take the long way around the sphere. + // To fix this, one quat must be negated. + if (cosTheta < 0.0f) + { + z = -y; + cosTheta = -cosTheta; + } + + // Perform a linear interpolation when cosTheta is close to 1 to avoid side effect of sin(angle) becoming a zero denominator + if(cosTheta > 1.0f - epsilon<float>()) + { + return _mm_add_ps(x.Data, _mm_mul_ps(_mm_set1_ps(a), _mm_sub_ps(y.Data, x.Data))); + } + else + { + float angle = glm::acos(cosTheta); + + + float s0 = glm::sin((1.0f - a) * angle); + float s1 = glm::sin(a * angle); + float d = 1.0f / glm::sin(angle); + + return (s0 * x + s1 * y) * d; + } +} + + +GLM_FUNC_QUALIFIER detail::fquatSIMD fastMix +( + detail::fquatSIMD const & x, + detail::fquatSIMD const & y, + float const & a +) +{ + float cosTheta = dot(x, y); + + if (cosTheta > 1.0f - glm::epsilon<float>()) + { + return _mm_add_ps(x.Data, _mm_mul_ps(_mm_set1_ps(a), _mm_sub_ps(y.Data, x.Data))); + } + else + { + float angle = glm::fastAcos(cosTheta); + + + __m128 s = glm::fastSin(_mm_set_ps((1.0f - a) * angle, a * angle, angle, 0.0f)); + + __m128 s0 = _mm_shuffle_ps(s, s, _MM_SHUFFLE(3, 3, 3, 3)); + __m128 s1 = _mm_shuffle_ps(s, s, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 d = _mm_div_ps(_mm_set1_ps(1.0f), _mm_shuffle_ps(s, s, _MM_SHUFFLE(1, 1, 1, 1))); + + return _mm_mul_ps(_mm_add_ps(_mm_mul_ps(s0, x.Data), _mm_mul_ps(s1, y.Data)), d); + } +} + +GLM_FUNC_QUALIFIER detail::fquatSIMD fastSlerp +( + detail::fquatSIMD const & x, + detail::fquatSIMD const & y, + float const & a +) +{ + detail::fquatSIMD z = y; + + float cosTheta = dot(x, y); + if (cosTheta < 0.0f) + { + z = -y; + cosTheta = -cosTheta; + } + + + if(cosTheta > 1.0f - epsilon<float>()) + { + return _mm_add_ps(x.Data, _mm_mul_ps(_mm_set1_ps(a), _mm_sub_ps(y.Data, x.Data))); + } + else + { + float angle = glm::fastAcos(cosTheta); + + + __m128 s = glm::fastSin(_mm_set_ps((1.0f - a) * angle, a * angle, angle, 0.0f)); + + __m128 s0 = _mm_shuffle_ps(s, s, _MM_SHUFFLE(3, 3, 3, 3)); + __m128 s1 = _mm_shuffle_ps(s, s, _MM_SHUFFLE(2, 2, 2, 2)); + __m128 d = _mm_div_ps(_mm_set1_ps(1.0f), _mm_shuffle_ps(s, s, _MM_SHUFFLE(1, 1, 1, 1))); + + return _mm_mul_ps(_mm_add_ps(_mm_mul_ps(s0, x.Data), _mm_mul_ps(s1, y.Data)), d); + } +} + + + +GLM_FUNC_QUALIFIER detail::fquatSIMD conjugate +( + detail::fquatSIMD const & q +) +{ + return detail::fquatSIMD(_mm_mul_ps(q.Data, _mm_set_ps(1.0f, -1.0f, -1.0f, -1.0f))); +} + +GLM_FUNC_QUALIFIER detail::fquatSIMD inverse +( + detail::fquatSIMD const & q +) +{ + return conjugate(q) / dot(q, q); +} + + +GLM_FUNC_QUALIFIER detail::fquatSIMD angleAxisSIMD +( + float const & angle, + vec3 const & v +) +{ + float s = glm::sin(angle * 0.5f); + + return _mm_set_ps( + glm::cos(angle * 0.5f), + v.z * s, + v.y * s, + v.x * s); +} + +GLM_FUNC_QUALIFIER detail::fquatSIMD angleAxisSIMD +( + float const & angle, + float const & x, + float const & y, + float const & z +) +{ + return angleAxisSIMD(angle, vec3(x, y, z)); +} + + +GLM_FUNC_QUALIFIER __m128 fastSin(__m128 x) +{ + static const __m128 c0 = _mm_set1_ps(0.16666666666666666666666666666667f); + static const __m128 c1 = _mm_set1_ps(0.00833333333333333333333333333333f); + static const __m128 c2 = _mm_set1_ps(0.00019841269841269841269841269841f); + + __m128 x3 = _mm_mul_ps(x, _mm_mul_ps(x, x)); + __m128 x5 = _mm_mul_ps(x3, _mm_mul_ps(x, x)); + __m128 x7 = _mm_mul_ps(x5, _mm_mul_ps(x, x)); + + __m128 y0 = _mm_mul_ps(x3, c0); + __m128 y1 = _mm_mul_ps(x5, c1); + __m128 y2 = _mm_mul_ps(x7, c2); + + return _mm_sub_ps(_mm_add_ps(_mm_sub_ps(x, y0), y1), y2); +} + + +}//namespace glm diff --git a/extensions/common/glm/gtx/simd_vec4.hpp b/extensions/common/glm/gtx/simd_vec4.hpp new file mode 100644 index 0000000000..4fa9c6300d --- /dev/null +++ b/extensions/common/glm/gtx/simd_vec4.hpp @@ -0,0 +1,574 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_simd_vec4 +/// @file glm/gtx/simd_vec4.hpp +/// @date 2009-05-07 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_simd_vec4 GLM_GTX_simd_vec4 +/// @ingroup gtx +/// +/// @brief SIMD implementation of vec4 type. +/// +/// <glm/gtx/simd_vec4.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(GLM_ARCH != GLM_ARCH_PURE) + +#if(GLM_ARCH & GLM_ARCH_SSE2) +# include "../detail/intrinsic_common.hpp" +# include "../detail/intrinsic_geometric.hpp" +# include "../detail/intrinsic_integer.hpp" +#else +# error "GLM: GLM_GTX_simd_vec4 requires compiler support of SSE2 through intrinsics" +#endif + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_simd_vec4 extension included") +#endif + + +// Warning silencer for nameless struct/union. +#if (GLM_COMPILER & GLM_COMPILER_VC) +# pragma warning(push) +# pragma warning(disable:4201) // warning C4201: nonstandard extension used : nameless struct/union +#endif + +namespace glm +{ + enum comp + { + X = 0, + R = 0, + S = 0, + Y = 1, + G = 1, + T = 1, + Z = 2, + B = 2, + P = 2, + W = 3, + A = 3, + Q = 3 + }; + +}//namespace glm + +namespace glm{ +namespace detail +{ + /// 4-dimensional vector implemented using SIMD SEE intrinsics. + /// \ingroup gtx_simd_vec4 + GLM_ALIGNED_STRUCT(16) fvec4SIMD + { + typedef __m128 value_type; + typedef std::size_t size_type; + static size_type value_size(); + + typedef fvec4SIMD type; + typedef tvec4<bool, highp> bool_type; + +#ifdef GLM_SIMD_ENABLE_XYZW_UNION + union + { + __m128 Data; + struct {float x, y, z, w;}; + }; +#else + __m128 Data; +#endif + + ////////////////////////////////////// + // Implicit basic constructors + + fvec4SIMD(); + fvec4SIMD(__m128 const & Data); + fvec4SIMD(fvec4SIMD const & v); + + ////////////////////////////////////// + // Explicit basic constructors + + explicit fvec4SIMD( + ctor); + explicit fvec4SIMD( + float const & s); + explicit fvec4SIMD( + float const & x, + float const & y, + float const & z, + float const & w); + explicit fvec4SIMD( + vec4 const & v); + + //////////////////////////////////////// + //// Conversion vector constructors + + fvec4SIMD(vec2 const & v, float const & s1, float const & s2); + fvec4SIMD(float const & s1, vec2 const & v, float const & s2); + fvec4SIMD(float const & s1, float const & s2, vec2 const & v); + fvec4SIMD(vec3 const & v, float const & s); + fvec4SIMD(float const & s, vec3 const & v); + fvec4SIMD(vec2 const & v1, vec2 const & v2); + //fvec4SIMD(ivec4SIMD const & v); + + ////////////////////////////////////// + // Unary arithmetic operators + + fvec4SIMD& operator= (fvec4SIMD const & v); + fvec4SIMD& operator+=(fvec4SIMD const & v); + fvec4SIMD& operator-=(fvec4SIMD const & v); + fvec4SIMD& operator*=(fvec4SIMD const & v); + fvec4SIMD& operator/=(fvec4SIMD const & v); + + fvec4SIMD& operator+=(float const & s); + fvec4SIMD& operator-=(float const & s); + fvec4SIMD& operator*=(float const & s); + fvec4SIMD& operator/=(float const & s); + + fvec4SIMD& operator++(); + fvec4SIMD& operator--(); + + ////////////////////////////////////// + // Swizzle operators + + template <comp X, comp Y, comp Z, comp W> + fvec4SIMD& swizzle(); + template <comp X, comp Y, comp Z, comp W> + fvec4SIMD swizzle() const; + template <comp X, comp Y, comp Z> + fvec4SIMD swizzle() const; + template <comp X, comp Y> + fvec4SIMD swizzle() const; + template <comp X> + fvec4SIMD swizzle() const; + }; +}//namespace detail + + typedef glm::detail::fvec4SIMD simdVec4; + + /// @addtogroup gtx_simd_vec4 + /// @{ + + //! Convert a simdVec4 to a vec4. + /// @see gtx_simd_vec4 + vec4 vec4_cast( + detail::fvec4SIMD const & x); + + //! Returns x if x >= 0; otherwise, it returns -x. + /// @see gtx_simd_vec4 + detail::fvec4SIMD abs(detail::fvec4SIMD const & x); + + //! Returns 1.0 if x > 0, 0.0 if x = 0, or -1.0 if x < 0. + /// @see gtx_simd_vec4 + detail::fvec4SIMD sign(detail::fvec4SIMD const & x); + + //! Returns a value equal to the nearest integer that is less then or equal to x. + /// @see gtx_simd_vec4 + detail::fvec4SIMD floor(detail::fvec4SIMD const & x); + + //! Returns a value equal to the nearest integer to x + //! whose absolute value is not larger than the absolute value of x. + /// @see gtx_simd_vec4 + detail::fvec4SIMD trunc(detail::fvec4SIMD const & x); + + //! Returns a value equal to the nearest integer to x. + //! The fraction 0.5 will round in a direction chosen by the + //! implementation, presumably the direction that is fastest. + //! This includes the possibility that round(x) returns the + //! same value as roundEven(x) for all values of x. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD round(detail::fvec4SIMD const & x); + + //! Returns a value equal to the nearest integer to x. + //! A fractional part of 0.5 will round toward the nearest even + //! integer. (Both 3.5 and 4.5 for x will return 4.0.) + /// + /// @see gtx_simd_vec4 + //detail::fvec4SIMD roundEven(detail::fvec4SIMD const & x); + + //! Returns a value equal to the nearest integer + //! that is greater than or equal to x. + /// @see gtx_simd_vec4 + detail::fvec4SIMD ceil(detail::fvec4SIMD const & x); + + //! Return x - floor(x). + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD fract(detail::fvec4SIMD const & x); + + //! Modulus. Returns x - y * floor(x / y) + //! for each component in x using the floating point value y. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD mod( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y); + + //! Modulus. Returns x - y * floor(x / y) + //! for each component in x using the floating point value y. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD mod( + detail::fvec4SIMD const & x, + float const & y); + + //! Returns the fractional part of x and sets i to the integer + //! part (as a whole number floating point value). Both the + //! return value and the output parameter will have the same + //! sign as x. + //! (From GLM_GTX_simd_vec4 extension, common function) + //detail::fvec4SIMD modf( + // detail::fvec4SIMD const & x, + // detail::fvec4SIMD & i); + + //! Returns y if y < x; otherwise, it returns x. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD min( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y); + + detail::fvec4SIMD min( + detail::fvec4SIMD const & x, + float const & y); + + //! Returns y if x < y; otherwise, it returns x. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD max( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y); + + detail::fvec4SIMD max( + detail::fvec4SIMD const & x, + float const & y); + + //! Returns min(max(x, minVal), maxVal) for each component in x + //! using the floating-point values minVal and maxVal. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD clamp( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & minVal, + detail::fvec4SIMD const & maxVal); + + detail::fvec4SIMD clamp( + detail::fvec4SIMD const & x, + float const & minVal, + float const & maxVal); + + //! \return If genTypeU is a floating scalar or vector: + //! Returns x * (1.0 - a) + y * a, i.e., the linear blend of + //! x and y using the floating-point value a. + //! The value for a is not restricted to the range [0, 1]. + //! + //! \return If genTypeU is a boolean scalar or vector: + //! Selects which vector each returned component comes + //! from. For a component of a that is false, the + //! corresponding component of x is returned. For a + //! component of a that is true, the corresponding + //! component of y is returned. Components of x and y that + //! are not selected are allowed to be invalid floating point + //! values and will have no effect on the results. Thus, this + //! provides different functionality than + //! genType mix(genType x, genType y, genType(a)) + //! where a is a Boolean vector. + //! + //! From GLSL 1.30.08 specification, section 8.3 + //! + //! \param[in] x Floating point scalar or vector. + //! \param[in] y Floating point scalar or vector. + //! \param[in] a Floating point or boolean scalar or vector. + //! + /// \todo Test when 'a' is a boolean. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD mix( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y, + detail::fvec4SIMD const & a); + + //! Returns 0.0 if x < edge, otherwise it returns 1.0. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD step( + detail::fvec4SIMD const & edge, + detail::fvec4SIMD const & x); + + detail::fvec4SIMD step( + float const & edge, + detail::fvec4SIMD const & x); + + //! Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and + //! performs smooth Hermite interpolation between 0 and 1 + //! when edge0 < x < edge1. This is useful in cases where + //! you would want a threshold function with a smooth + //! transition. This is equivalent to: + //! genType t; + //! t = clamp ((x - edge0) / (edge1 - edge0), 0, 1); + //! return t * t * (3 - 2 * t); + //! Results are undefined if edge0 >= edge1. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD smoothstep( + detail::fvec4SIMD const & edge0, + detail::fvec4SIMD const & edge1, + detail::fvec4SIMD const & x); + + detail::fvec4SIMD smoothstep( + float const & edge0, + float const & edge1, + detail::fvec4SIMD const & x); + + //! Returns true if x holds a NaN (not a number) + //! representation in the underlying implementation's set of + //! floating point representations. Returns false otherwise, + //! including for implementations with no NaN + //! representations. + /// + /// @see gtx_simd_vec4 + //bvec4 isnan(detail::fvec4SIMD const & x); + + //! Returns true if x holds a positive infinity or negative + //! infinity representation in the underlying implementation's + //! set of floating point representations. Returns false + //! otherwise, including for implementations with no infinity + //! representations. + /// + /// @see gtx_simd_vec4 + //bvec4 isinf(detail::fvec4SIMD const & x); + + //! Returns a signed or unsigned integer value representing + //! the encoding of a floating-point value. The floatingpoint + //! value's bit-level representation is preserved. + /// + /// @see gtx_simd_vec4 + //detail::ivec4SIMD floatBitsToInt(detail::fvec4SIMD const & value); + + //! Returns a floating-point value corresponding to a signed + //! or unsigned integer encoding of a floating-point value. + //! If an inf or NaN is passed in, it will not signal, and the + //! resulting floating point value is unspecified. Otherwise, + //! the bit-level representation is preserved. + /// + /// @see gtx_simd_vec4 + //detail::fvec4SIMD intBitsToFloat(detail::ivec4SIMD const & value); + + //! Computes and returns a * b + c. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD fma( + detail::fvec4SIMD const & a, + detail::fvec4SIMD const & b, + detail::fvec4SIMD const & c); + + //! Splits x into a floating-point significand in the range + //! [0.5, 1.0) and an integral exponent of two, such that: + //! x = significand * exp(2, exponent) + //! The significand is returned by the function and the + //! exponent is returned in the parameter exp. For a + //! floating-point value of zero, the significant and exponent + //! are both zero. For a floating-point value that is an + //! infinity or is not a number, the results are undefined. + /// + /// @see gtx_simd_vec4 + //detail::fvec4SIMD frexp(detail::fvec4SIMD const & x, detail::ivec4SIMD & exp); + + //! Builds a floating-point number from x and the + //! corresponding integral exponent of two in exp, returning: + //! significand * exp(2, exponent) + //! If this product is too large to be represented in the + //! floating-point type, the result is undefined. + /// + /// @see gtx_simd_vec4 + //detail::fvec4SIMD ldexp(detail::fvec4SIMD const & x, detail::ivec4SIMD const & exp); + + //! Returns the length of x, i.e., sqrt(x * x). + /// + /// @see gtx_simd_vec4 + float length( + detail::fvec4SIMD const & x); + + //! Returns the length of x, i.e., sqrt(x * x). + //! Less accurate but much faster than simdLength. + /// + /// @see gtx_simd_vec4 + float fastLength( + detail::fvec4SIMD const & x); + + //! Returns the length of x, i.e., sqrt(x * x). + //! Slightly more accurate but much slower than simdLength. + /// + /// @see gtx_simd_vec4 + float niceLength( + detail::fvec4SIMD const & x); + + //! Returns the length of x, i.e., sqrt(x * x). + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD length4( + detail::fvec4SIMD const & x); + + //! Returns the length of x, i.e., sqrt(x * x). + //! Less accurate but much faster than simdLength4. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD fastLength4( + detail::fvec4SIMD const & x); + + //! Returns the length of x, i.e., sqrt(x * x). + //! Slightly more accurate but much slower than simdLength4. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD niceLength4( + detail::fvec4SIMD const & x); + + //! Returns the distance betwwen p0 and p1, i.e., length(p0 - p1). + /// + /// @see gtx_simd_vec4 + float distance( + detail::fvec4SIMD const & p0, + detail::fvec4SIMD const & p1); + + //! Returns the distance betwwen p0 and p1, i.e., length(p0 - p1). + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD distance4( + detail::fvec4SIMD const & p0, + detail::fvec4SIMD const & p1); + + //! Returns the dot product of x and y, i.e., result = x * y. + /// + /// @see gtx_simd_vec4 + float simdDot( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y); + + //! Returns the dot product of x and y, i.e., result = x * y. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD dot4( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y); + + //! Returns the cross product of x and y. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD cross( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y); + + //! Returns a vector in the same direction as x but with length of 1. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD normalize( + detail::fvec4SIMD const & x); + + //! Returns a vector in the same direction as x but with length of 1. + //! Less accurate but much faster than simdNormalize. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD fastNormalize( + detail::fvec4SIMD const & x); + + //! If dot(Nref, I) < 0.0, return N, otherwise, return -N. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD simdFaceforward( + detail::fvec4SIMD const & N, + detail::fvec4SIMD const & I, + detail::fvec4SIMD const & Nref); + + //! For the incident vector I and surface orientation N, + //! returns the reflection direction : result = I - 2.0 * dot(N, I) * N. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD reflect( + detail::fvec4SIMD const & I, + detail::fvec4SIMD const & N); + + //! For the incident vector I and surface normal N, + //! and the ratio of indices of refraction eta, + //! return the refraction vector. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD refract( + detail::fvec4SIMD const & I, + detail::fvec4SIMD const & N, + float const & eta); + + //! Returns the positive square root of x. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD sqrt( + detail::fvec4SIMD const & x); + + //! Returns the positive square root of x with the nicest quality but very slow. + //! Slightly more accurate but much slower than simdSqrt. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD niceSqrt( + detail::fvec4SIMD const & x); + + //! Returns the positive square root of x + //! Less accurate but much faster than sqrt. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD fastSqrt( + detail::fvec4SIMD const & x); + + //! Returns the reciprocal of the positive square root of x. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD inversesqrt( + detail::fvec4SIMD const & x); + + //! Returns the reciprocal of the positive square root of x. + //! Faster than inversesqrt but less accurate. + /// + /// @see gtx_simd_vec4 + detail::fvec4SIMD fastInversesqrt( + detail::fvec4SIMD const & x); + + /// @} +}//namespace glm + +#include "simd_vec4.inl" + +#if (GLM_COMPILER & GLM_COMPILER_VC) +# pragma warning(pop) +#endif + +#endif//(GLM_ARCH != GLM_ARCH_PURE) diff --git a/extensions/common/glm/gtx/simd_vec4.inl b/extensions/common/glm/gtx/simd_vec4.inl new file mode 100644 index 0000000000..35b826c565 --- /dev/null +++ b/extensions/common/glm/gtx/simd_vec4.inl @@ -0,0 +1,727 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// OpenGL Mathematics Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Created : 2009-05-07 +// Updated : 2009-05-07 +// Licence : This source is under MIT License +// File : glm/gtx/simd_vec4.inl +/////////////////////////////////////////////////////////////////////////////////////////////////// + +namespace glm{ +namespace detail{ + +template <int Value> +struct shuffle_mask +{ + enum{value = Value}; +}; + +////////////////////////////////////// +// Implicit basic constructors + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD() +# ifdef GLM_FORCE_NO_CTOR_INIT + : Data(_mm_set_ps(0.0f, 0.0f, 0.0f, 0.0f)) +# endif +{} + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(__m128 const & Data) : + Data(Data) +{} + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(fvec4SIMD const & v) : + Data(v.Data) +{} + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(vec4 const & v) : + Data(_mm_set_ps(v.w, v.z, v.y, v.x)) +{} + +////////////////////////////////////// +// Explicit basic constructors + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const & s) : + Data(_mm_set1_ps(s)) +{} + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const & x, float const & y, float const & z, float const & w) : +// Data(_mm_setr_ps(x, y, z, w)) + Data(_mm_set_ps(w, z, y, x)) +{} +/* +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const v[4]) : + Data(_mm_load_ps(v)) +{} +*/ +////////////////////////////////////// +// Swizzle constructors + +//fvec4SIMD(ref4<float> const & r); + +////////////////////////////////////// +// Conversion vector constructors + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(vec2 const & v, float const & s1, float const & s2) : + Data(_mm_set_ps(s2, s1, v.y, v.x)) +{} + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const & s1, vec2 const & v, float const & s2) : + Data(_mm_set_ps(s2, v.y, v.x, s1)) +{} + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const & s1, float const & s2, vec2 const & v) : + Data(_mm_set_ps(v.y, v.x, s2, s1)) +{} + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(vec3 const & v, float const & s) : + Data(_mm_set_ps(s, v.z, v.y, v.x)) +{} + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(float const & s, vec3 const & v) : + Data(_mm_set_ps(v.z, v.y, v.x, s)) +{} + +GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(vec2 const & v1, vec2 const & v2) : + Data(_mm_set_ps(v2.y, v2.x, v1.y, v1.x)) +{} + +//GLM_FUNC_QUALIFIER fvec4SIMD::fvec4SIMD(ivec4SIMD const & v) : +// Data(_mm_cvtepi32_ps(v.Data)) +//{} + +////////////////////////////////////// +// Unary arithmetic operators + +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator=(fvec4SIMD const & v) +{ + this->Data = v.Data; + return *this; +} + +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator+=(float const & s) +{ + this->Data = _mm_add_ps(Data, _mm_set_ps1(s)); + return *this; +} + +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator+=(fvec4SIMD const & v) +{ + this->Data = _mm_add_ps(this->Data , v.Data); + return *this; +} + +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator-=(float const & s) +{ + this->Data = _mm_sub_ps(Data, _mm_set_ps1(s)); + return *this; +} + +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator-=(fvec4SIMD const & v) +{ + this->Data = _mm_sub_ps(this->Data , v.Data); + return *this; +} + +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator*=(float const & s) +{ + this->Data = _mm_mul_ps(this->Data, _mm_set_ps1(s)); + return *this; +} + +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator*=(fvec4SIMD const & v) +{ + this->Data = _mm_mul_ps(this->Data , v.Data); + return *this; +} + +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator/=(float const & s) +{ + this->Data = _mm_div_ps(Data, _mm_set1_ps(s)); + return *this; +} + +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator/=(fvec4SIMD const & v) +{ + this->Data = _mm_div_ps(this->Data , v.Data); + return *this; +} + +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator++() +{ + this->Data = _mm_add_ps(this->Data , glm::detail::one); + return *this; +} + +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::operator--() +{ + this->Data = _mm_sub_ps(this->Data, glm::detail::one); + return *this; +} + +////////////////////////////////////// +// Swizzle operators + +template <comp X, comp Y, comp Z, comp W> +GLM_FUNC_QUALIFIER fvec4SIMD fvec4SIMD::swizzle() const +{ + __m128 Data = _mm_shuffle_ps( + this->Data, this->Data, + shuffle_mask<(W << 6) | (Z << 4) | (Y << 2) | (X << 0)>::value); + return fvec4SIMD(Data); +} + +template <comp X, comp Y, comp Z, comp W> +GLM_FUNC_QUALIFIER fvec4SIMD& fvec4SIMD::swizzle() +{ + this->Data = _mm_shuffle_ps( + this->Data, this->Data, + shuffle_mask<(W << 6) | (Z << 4) | (Y << 2) | (X << 0)>::value); + return *this; +} + +// operator+ +GLM_FUNC_QUALIFIER fvec4SIMD operator+ (fvec4SIMD const & v, float s) +{ + return fvec4SIMD(_mm_add_ps(v.Data, _mm_set1_ps(s))); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator+ (float s, fvec4SIMD const & v) +{ + return fvec4SIMD(_mm_add_ps(_mm_set1_ps(s), v.Data)); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator+ (fvec4SIMD const & v1, fvec4SIMD const & v2) +{ + return fvec4SIMD(_mm_add_ps(v1.Data, v2.Data)); +} + +//operator- +GLM_FUNC_QUALIFIER fvec4SIMD operator- (fvec4SIMD const & v, float s) +{ + return fvec4SIMD(_mm_sub_ps(v.Data, _mm_set1_ps(s))); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator- (float s, fvec4SIMD const & v) +{ + return fvec4SIMD(_mm_sub_ps(_mm_set1_ps(s), v.Data)); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator- (fvec4SIMD const & v1, fvec4SIMD const & v2) +{ + return fvec4SIMD(_mm_sub_ps(v1.Data, v2.Data)); +} + +//operator* +GLM_FUNC_QUALIFIER fvec4SIMD operator* (fvec4SIMD const & v, float s) +{ + __m128 par0 = v.Data; + __m128 par1 = _mm_set1_ps(s); + return fvec4SIMD(_mm_mul_ps(par0, par1)); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator* (float s, fvec4SIMD const & v) +{ + __m128 par0 = _mm_set1_ps(s); + __m128 par1 = v.Data; + return fvec4SIMD(_mm_mul_ps(par0, par1)); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator* (fvec4SIMD const & v1, fvec4SIMD const & v2) +{ + return fvec4SIMD(_mm_mul_ps(v1.Data, v2.Data)); +} + +//operator/ +GLM_FUNC_QUALIFIER fvec4SIMD operator/ (fvec4SIMD const & v, float s) +{ + __m128 par0 = v.Data; + __m128 par1 = _mm_set1_ps(s); + return fvec4SIMD(_mm_div_ps(par0, par1)); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator/ (float s, fvec4SIMD const & v) +{ + __m128 par0 = _mm_set1_ps(s); + __m128 par1 = v.Data; + return fvec4SIMD(_mm_div_ps(par0, par1)); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator/ (fvec4SIMD const & v1, fvec4SIMD const & v2) +{ + return fvec4SIMD(_mm_div_ps(v1.Data, v2.Data)); +} + +// Unary constant operators +GLM_FUNC_QUALIFIER fvec4SIMD operator- (fvec4SIMD const & v) +{ + return fvec4SIMD(_mm_sub_ps(_mm_setzero_ps(), v.Data)); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator++ (fvec4SIMD const & v, int) +{ + return fvec4SIMD(_mm_add_ps(v.Data, glm::detail::one)); +} + +GLM_FUNC_QUALIFIER fvec4SIMD operator-- (fvec4SIMD const & v, int) +{ + return fvec4SIMD(_mm_sub_ps(v.Data, glm::detail::one)); +} + +}//namespace detail + +GLM_FUNC_QUALIFIER vec4 vec4_cast +( + detail::fvec4SIMD const & x +) +{ + GLM_ALIGN(16) vec4 Result; + _mm_store_ps(&Result[0], x.Data); + return Result; +} + +// Other possible implementation +//float abs(float a) +//{ +// return max(-a, a); +//} +GLM_FUNC_QUALIFIER detail::fvec4SIMD abs +( + detail::fvec4SIMD const & x +) +{ + return detail::sse_abs_ps(x.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD sign +( + detail::fvec4SIMD const & x +) +{ + return detail::sse_sgn_ps(x.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD floor +( + detail::fvec4SIMD const & x +) +{ + return detail::sse_flr_ps(x.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD trunc +( + detail::fvec4SIMD const & x +) +{ + //return x < 0 ? -floor(-x) : floor(x); + + __m128 Flr0 = detail::sse_flr_ps(_mm_sub_ps(_mm_setzero_ps(), x.Data)); + __m128 Sub0 = _mm_sub_ps(Flr0, x.Data); + __m128 Flr1 = detail::sse_flr_ps(x.Data); + + __m128 Cmp0 = _mm_cmplt_ps(x.Data, glm::detail::zero); + __m128 Cmp1 = _mm_cmpnlt_ps(x.Data, glm::detail::zero); + + __m128 And0 = _mm_and_ps(Sub0, Cmp0); + __m128 And1 = _mm_and_ps(Flr1, Cmp1); + + return _mm_or_ps(And0, And1); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD round +( + detail::fvec4SIMD const & x +) +{ + return detail::sse_rnd_ps(x.Data); +} + +//GLM_FUNC_QUALIFIER detail::fvec4SIMD roundEven +//( +// detail::fvec4SIMD const & x +//) +//{ + +//} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD ceil +( + detail::fvec4SIMD const & x +) +{ + return detail::sse_ceil_ps(x.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD fract +( + detail::fvec4SIMD const & x +) +{ + return detail::sse_frc_ps(x.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD mod +( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y +) +{ + return detail::sse_mod_ps(x.Data, y.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD mod +( + detail::fvec4SIMD const & x, + float const & y +) +{ + return detail::sse_mod_ps(x.Data, _mm_set1_ps(y)); +} + +//GLM_FUNC_QUALIFIER detail::fvec4SIMD modf +//( +// detail::fvec4SIMD const & x, +// detail::fvec4SIMD & i +//) +//{ + +//} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD min +( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y +) +{ + return _mm_min_ps(x.Data, y.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD min +( + detail::fvec4SIMD const & x, + float const & y +) +{ + return _mm_min_ps(x.Data, _mm_set1_ps(y)); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD max +( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y +) +{ + return _mm_max_ps(x.Data, y.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD max +( + detail::fvec4SIMD const & x, + float const & y +) +{ + return _mm_max_ps(x.Data, _mm_set1_ps(y)); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD clamp +( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & minVal, + detail::fvec4SIMD const & maxVal +) +{ + return detail::sse_clp_ps(x.Data, minVal.Data, maxVal.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD clamp +( + detail::fvec4SIMD const & x, + float const & minVal, + float const & maxVal +) +{ + return detail::sse_clp_ps(x.Data, _mm_set1_ps(minVal), _mm_set1_ps(maxVal)); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD mix +( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y, + detail::fvec4SIMD const & a +) +{ + __m128 Sub0 = _mm_sub_ps(y.Data, x.Data); + __m128 Mul0 = _mm_mul_ps(a.Data, Sub0); + return _mm_add_ps(x.Data, Mul0); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD step +( + detail::fvec4SIMD const & edge, + detail::fvec4SIMD const & x +) +{ + __m128 cmp0 = _mm_cmpngt_ps(x.Data, edge.Data); + return _mm_max_ps(_mm_min_ps(cmp0, _mm_setzero_ps()), detail::one); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD step +( + float const & edge, + detail::fvec4SIMD const & x +) +{ + __m128 cmp0 = _mm_cmpngt_ps(x.Data, _mm_set1_ps(edge)); + return _mm_max_ps(_mm_min_ps(cmp0, _mm_setzero_ps()), detail::one); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD smoothstep +( + detail::fvec4SIMD const & edge0, + detail::fvec4SIMD const & edge1, + detail::fvec4SIMD const & x +) +{ + return detail::sse_ssp_ps(edge0.Data, edge1.Data, x.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD smoothstep +( + float const & edge0, + float const & edge1, + detail::fvec4SIMD const & x +) +{ + return detail::sse_ssp_ps(_mm_set1_ps(edge0), _mm_set1_ps(edge1), x.Data); +} + +//GLM_FUNC_QUALIFIER bvec4 isnan(detail::fvec4SIMD const & x) +//{ + +//} + +//GLM_FUNC_QUALIFIER bvec4 isinf(detail::fvec4SIMD const & x) +//{ + +//} + +//GLM_FUNC_QUALIFIER detail::ivec4SIMD floatBitsToInt +//( +// detail::fvec4SIMD const & value +//) +//{ + +//} + +//GLM_FUNC_QUALIFIER detail::fvec4SIMD intBitsToFloat +//( +// detail::ivec4SIMD const & value +//) +//{ + +//} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD fma +( + detail::fvec4SIMD const & a, + detail::fvec4SIMD const & b, + detail::fvec4SIMD const & c +) +{ + return _mm_add_ps(_mm_mul_ps(a.Data, b.Data), c.Data); +} + +GLM_FUNC_QUALIFIER float length +( + detail::fvec4SIMD const & x +) +{ + detail::fvec4SIMD dot0 = detail::sse_dot_ss(x.Data, x.Data); + detail::fvec4SIMD sqt0 = sqrt(dot0); + float Result = 0; + _mm_store_ss(&Result, sqt0.Data); + return Result; +} + +GLM_FUNC_QUALIFIER float fastLength +( + detail::fvec4SIMD const & x +) +{ + detail::fvec4SIMD dot0 = detail::sse_dot_ss(x.Data, x.Data); + detail::fvec4SIMD sqt0 = fastSqrt(dot0); + float Result = 0; + _mm_store_ss(&Result, sqt0.Data); + return Result; +} + +GLM_FUNC_QUALIFIER float niceLength +( + detail::fvec4SIMD const & x +) +{ + detail::fvec4SIMD dot0 = detail::sse_dot_ss(x.Data, x.Data); + detail::fvec4SIMD sqt0 = niceSqrt(dot0); + float Result = 0; + _mm_store_ss(&Result, sqt0.Data); + return Result; +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD length4 +( + detail::fvec4SIMD const & x +) +{ + return sqrt(dot4(x, x)); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD fastLength4 +( + detail::fvec4SIMD const & x +) +{ + return fastSqrt(dot4(x, x)); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD niceLength4 +( + detail::fvec4SIMD const & x +) +{ + return niceSqrt(dot4(x, x)); +} + +GLM_FUNC_QUALIFIER float distance +( + detail::fvec4SIMD const & p0, + detail::fvec4SIMD const & p1 +) +{ + float Result = 0; + _mm_store_ss(&Result, detail::sse_dst_ps(p0.Data, p1.Data)); + return Result; +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD distance4 +( + detail::fvec4SIMD const & p0, + detail::fvec4SIMD const & p1 +) +{ + return detail::sse_dst_ps(p0.Data, p1.Data); +} + +GLM_FUNC_QUALIFIER float dot +( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y +) +{ + float Result = 0; + _mm_store_ss(&Result, detail::sse_dot_ss(x.Data, y.Data)); + return Result; +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD dot4 +( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y +) +{ + return detail::sse_dot_ps(x.Data, y.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD cross +( + detail::fvec4SIMD const & x, + detail::fvec4SIMD const & y +) +{ + return detail::sse_xpd_ps(x.Data, y.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD normalize +( + detail::fvec4SIMD const & x +) +{ + __m128 dot0 = detail::sse_dot_ps(x.Data, x.Data); + __m128 isr0 = inversesqrt(detail::fvec4SIMD(dot0)).Data; + __m128 mul0 = _mm_mul_ps(x.Data, isr0); + return mul0; +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD fastNormalize +( + detail::fvec4SIMD const & x +) +{ + __m128 dot0 = detail::sse_dot_ps(x.Data, x.Data); + __m128 isr0 = fastInversesqrt(dot0).Data; + __m128 mul0 = _mm_mul_ps(x.Data, isr0); + return mul0; +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD faceforward +( + detail::fvec4SIMD const & N, + detail::fvec4SIMD const & I, + detail::fvec4SIMD const & Nref +) +{ + return detail::sse_ffd_ps(N.Data, I.Data, Nref.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD reflect +( + detail::fvec4SIMD const & I, + detail::fvec4SIMD const & N +) +{ + return detail::sse_rfe_ps(I.Data, N.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD refract +( + detail::fvec4SIMD const & I, + detail::fvec4SIMD const & N, + float const & eta +) +{ + return detail::sse_rfa_ps(I.Data, N.Data, _mm_set1_ps(eta)); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD sqrt(detail::fvec4SIMD const & x) +{ + return _mm_mul_ps(inversesqrt(x).Data, x.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD niceSqrt(detail::fvec4SIMD const & x) +{ + return _mm_sqrt_ps(x.Data); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD fastSqrt(detail::fvec4SIMD const & x) +{ + return _mm_mul_ps(fastInversesqrt(x.Data).Data, x.Data); +} + +// SSE scalar reciprocal sqrt using rsqrt op, plus one Newton-Rhaphson iteration +// By Elan Ruskin, http://assemblyrequired.crashworks.org/ +GLM_FUNC_QUALIFIER detail::fvec4SIMD inversesqrt(detail::fvec4SIMD const & x) +{ + GLM_ALIGN(4) static const __m128 three = {3, 3, 3, 3}; // aligned consts for fast load + GLM_ALIGN(4) static const __m128 half = {0.5,0.5,0.5,0.5}; + + __m128 recip = _mm_rsqrt_ps(x.Data); // "estimate" opcode + __m128 halfrecip = _mm_mul_ps(half, recip); + __m128 threeminus_xrr = _mm_sub_ps(three, _mm_mul_ps(x.Data, _mm_mul_ps(recip, recip))); + return _mm_mul_ps(halfrecip, threeminus_xrr); +} + +GLM_FUNC_QUALIFIER detail::fvec4SIMD fastInversesqrt(detail::fvec4SIMD const & x) +{ + return _mm_rsqrt_ps(x.Data); +} + +}//namespace glm diff --git a/extensions/common/glm/gtx/spline.hpp b/extensions/common/glm/gtx/spline.hpp new file mode 100644 index 0000000000..198e752ff6 --- /dev/null +++ b/extensions/common/glm/gtx/spline.hpp @@ -0,0 +1,90 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_spline +/// @file glm/gtx/spline.hpp +/// @date 2007-01-25 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_spline GLM_GTX_spline +/// @ingroup gtx +/// +/// @brief Spline functions +/// +/// <glm/gtx/spline.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/optimum_pow.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_spline extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_spline + /// @{ + + /// Return a point from a catmull rom curve. + /// @see gtx_spline extension. + template <typename genType> + GLM_FUNC_DECL genType catmullRom( + genType const & v1, + genType const & v2, + genType const & v3, + genType const & v4, + typename genType::value_type const & s); + + /// Return a point from a hermite curve. + /// @see gtx_spline extension. + template <typename genType> + GLM_FUNC_DECL genType hermite( + genType const & v1, + genType const & t1, + genType const & v2, + genType const & t2, + typename genType::value_type const & s); + + /// Return a point from a cubic curve. + /// @see gtx_spline extension. + template <typename genType> + GLM_FUNC_DECL genType cubic( + genType const & v1, + genType const & v2, + genType const & v3, + genType const & v4, + typename genType::value_type const & s); + + /// @} +}//namespace glm + +#include "spline.inl" diff --git a/extensions/common/glm/gtx/spline.inl b/extensions/common/glm/gtx/spline.inl new file mode 100644 index 0000000000..d368292d9d --- /dev/null +++ b/extensions/common/glm/gtx/spline.inl @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_spline +/// @file glm/gtx/spline.inl +/// @date 2007-01-25 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename genType> + GLM_FUNC_QUALIFIER genType catmullRom + ( + genType const & v1, + genType const & v2, + genType const & v3, + genType const & v4, + typename genType::value_type const & s + ) + { + typename genType::value_type s1 = s; + typename genType::value_type s2 = pow2(s); + typename genType::value_type s3 = pow3(s); + + typename genType::value_type f1 = -s3 + typename genType::value_type(2) * s2 - s; + typename genType::value_type f2 = typename genType::value_type(3) * s3 - typename genType::value_type(5) * s2 + typename genType::value_type(2); + typename genType::value_type f3 = typename genType::value_type(-3) * s3 + typename genType::value_type(4) * s2 + s; + typename genType::value_type f4 = s3 - s2; + + return (f1 * v1 + f2 * v2 + f3 * v3 + f4 * v4) / typename genType::value_type(2); + + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType hermite + ( + genType const & v1, + genType const & t1, + genType const & v2, + genType const & t2, + typename genType::value_type const & s + ) + { + typename genType::value_type s1 = s; + typename genType::value_type s2 = pow2(s); + typename genType::value_type s3 = pow3(s); + + typename genType::value_type f1 = typename genType::value_type(2) * s3 - typename genType::value_type(3) * s2 + typename genType::value_type(1); + typename genType::value_type f2 = typename genType::value_type(-2) * s3 + typename genType::value_type(3) * s2; + typename genType::value_type f3 = s3 - typename genType::value_type(2) * s2 + s; + typename genType::value_type f4 = s3 - s2; + + return f1 * v1 + f2 * v2 + f3 * t1 + f4 * t2; + } + + template <typename genType> + GLM_FUNC_QUALIFIER genType cubic + ( + genType const & v1, + genType const & v2, + genType const & v3, + genType const & v4, + typename genType::value_type const & s + ) + { + return ((v1 * s + v2) * s + v3) * s + v4; + } +}//namespace glm diff --git a/extensions/common/glm/gtx/std_based_type.hpp b/extensions/common/glm/gtx/std_based_type.hpp new file mode 100644 index 0000000000..6eaf944202 --- /dev/null +++ b/extensions/common/glm/gtx/std_based_type.hpp @@ -0,0 +1,92 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_std_based_type +/// @file glm/gtx/std_based_type.hpp +/// @date 2008-06-08 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_extented_min_max (dependence) +/// +/// @defgroup gtx_std_based_type GLM_GTX_std_based_type +/// @ingroup gtx +/// +/// @brief Adds vector types based on STL value types. +/// <glm/gtx/std_based_type.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include <cstdlib> + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_std_based_type extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_std_based_type + /// @{ + + /// Vector type based of one std::size_t component. + /// @see GLM_GTX_std_based_type + typedef tvec1<std::size_t, defaultp> size1; + + /// Vector type based of two std::size_t components. + /// @see GLM_GTX_std_based_type + typedef tvec2<std::size_t, defaultp> size2; + + /// Vector type based of three std::size_t components. + /// @see GLM_GTX_std_based_type + typedef tvec3<std::size_t, defaultp> size3; + + /// Vector type based of four std::size_t components. + /// @see GLM_GTX_std_based_type + typedef tvec4<std::size_t, defaultp> size4; + + /// Vector type based of one std::size_t component. + /// @see GLM_GTX_std_based_type + typedef tvec1<std::size_t, defaultp> size1_t; + + /// Vector type based of two std::size_t components. + /// @see GLM_GTX_std_based_type + typedef tvec2<std::size_t, defaultp> size2_t; + + /// Vector type based of three std::size_t components. + /// @see GLM_GTX_std_based_type + typedef tvec3<std::size_t, defaultp> size3_t; + + /// Vector type based of four std::size_t components. + /// @see GLM_GTX_std_based_type + typedef tvec4<std::size_t, defaultp> size4_t; + + /// @} +}//namespace glm + +#include "std_based_type.inl" diff --git a/extensions/common/glm/gtx/std_based_type.inl b/extensions/common/glm/gtx/std_based_type.inl new file mode 100644 index 0000000000..52817e82e7 --- /dev/null +++ b/extensions/common/glm/gtx/std_based_type.inl @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_std_based_type +/// @file glm/gtx/std_based_type.inl +/// @date 2008-06-08 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + +} diff --git a/extensions/common/glm/gtx/string_cast.hpp b/extensions/common/glm/gtx/string_cast.hpp new file mode 100644 index 0000000000..e06c9018a5 --- /dev/null +++ b/extensions/common/glm/gtx/string_cast.hpp @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_string_cast +/// @file glm/gtx/string_cast.hpp +/// @date 2008-04-26 / 2014-05-10 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_half_float (dependence) +/// @see gtx_integer (dependence) +/// @see gtx_quaternion (dependence) +/// +/// @defgroup gtx_string_cast GLM_GTX_string_cast +/// @ingroup gtx +/// +/// @brief Setup strings for GLM type values +/// +/// <glm/gtx/string_cast.hpp> need to be included to use these functionalities. +/// This extension is not supported with CUDA +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/type_precision.hpp" +#include <string> + +#if(GLM_COMPILER & GLM_COMPILER_CUDA) +# error "GLM_GTX_string_cast is not supported on CUDA compiler" +#endif + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_string_cast extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_string_cast + /// @{ + + /// Create a string from a GLM vector or matrix typed variable. + /// @see gtx_string_cast extension. + template <template <typename, precision> class matType, typename T, precision P> + GLM_FUNC_DECL std::string to_string(matType<T, P> const & x); + + /// @} +}//namespace glm + +#include "string_cast.inl" diff --git a/extensions/common/glm/gtx/string_cast.inl b/extensions/common/glm/gtx/string_cast.inl new file mode 100644 index 0000000000..48f4391cab --- /dev/null +++ b/extensions/common/glm/gtx/string_cast.inl @@ -0,0 +1,455 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_string_cast +/// @file glm/gtx/string_cast.inl +/// @date 2008-04-26 / 2014-05-10 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include <cstdarg> +#include <cstdio> + +namespace glm{ +namespace detail +{ + GLM_FUNC_QUALIFIER std::string format(const char* msg, ...) + { + std::size_t const STRING_BUFFER(4096); + char text[STRING_BUFFER]; + va_list list; + + if(msg == 0) + return std::string(); + + va_start(list, msg); +# if(GLM_COMPILER & GLM_COMPILER_VC) + vsprintf_s(text, STRING_BUFFER, msg, list); +# else// + vsprintf(text, msg, list); +# endif// + va_end(list); + + return std::string(text); + } + + static const char* LabelTrue = "true"; + static const char* LabelFalse = "false"; + + template <typename T, bool isFloat = false> + struct literal + { + GLM_FUNC_QUALIFIER static char const * value() {return "%d";}; + }; + + template <typename T> + struct literal<T, true> + { + GLM_FUNC_QUALIFIER static char const * value() {return "%f";}; + }; + +# if GLM_MODEL == GLM_MODEL_32 && GLM_COMPILER && GLM_COMPILER_VC + template <> + struct literal<uint64_t, false> + { + GLM_FUNC_QUALIFIER static char const * value() {return "%lld";}; + }; + + template <> + struct literal<int64_t, false> + { + GLM_FUNC_QUALIFIER static char const * value() {return "%lld";}; + }; +# endif//GLM_MODEL == GLM_MODEL_32 && GLM_COMPILER && GLM_COMPILER_VC + + template <typename T> + struct prefix{}; + + template <> + struct prefix<float> + { + GLM_FUNC_QUALIFIER static char const * value() {return "";}; + }; + + template <> + struct prefix<double> + { + GLM_FUNC_QUALIFIER static char const * value() {return "d";}; + }; + + template <> + struct prefix<bool> + { + GLM_FUNC_QUALIFIER static char const * value() {return "b";}; + }; + + template <> + struct prefix<uint8_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "u8";}; + }; + + template <> + struct prefix<int8_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "i8";}; + }; + + template <> + struct prefix<uint16_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "u16";}; + }; + + template <> + struct prefix<int16_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "i16";}; + }; + + template <> + struct prefix<uint32_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "u";}; + }; + + template <> + struct prefix<int32_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "i";}; + }; + + template <> + struct prefix<uint64_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "u64";}; + }; + + template <> + struct prefix<int64_t> + { + GLM_FUNC_QUALIFIER static char const * value() {return "i64";}; + }; + + template <template <typename, precision> class matType, typename T, precision P> + struct compute_to_string + {}; + + template <precision P> + struct compute_to_string<tvec1, bool, P> + { + GLM_FUNC_QUALIFIER static std::string call(tvec1<bool, P> const & x) + { + return detail::format("bvec1(%s)", + x[0] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template <precision P> + struct compute_to_string<tvec2, bool, P> + { + GLM_FUNC_QUALIFIER static std::string call(tvec2<bool, P> const & x) + { + return detail::format("bvec2(%s, %s)", + x[0] ? detail::LabelTrue : detail::LabelFalse, + x[1] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template <precision P> + struct compute_to_string<tvec3, bool, P> + { + GLM_FUNC_QUALIFIER static std::string call(tvec3<bool, P> const & x) + { + return detail::format("bvec3(%s, %s, %s)", + x[0] ? detail::LabelTrue : detail::LabelFalse, + x[1] ? detail::LabelTrue : detail::LabelFalse, + x[2] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template <precision P> + struct compute_to_string<tvec4, bool, P> + { + GLM_FUNC_QUALIFIER static std::string call(tvec4<bool, P> const & x) + { + return detail::format("bvec4(%s, %s, %s, %s)", + x[0] ? detail::LabelTrue : detail::LabelFalse, + x[1] ? detail::LabelTrue : detail::LabelFalse, + x[2] ? detail::LabelTrue : detail::LabelFalse, + x[3] ? detail::LabelTrue : detail::LabelFalse); + } + }; + + template <typename T, precision P> + struct compute_to_string<tvec1, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tvec1<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%svec1(%s)", + PrefixStr, + LiteralStr)); + + return detail::format(FormatStr.c_str(), x[0]); + } + }; + + template <typename T, precision P> + struct compute_to_string<tvec2, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tvec2<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%svec2(%s, %s)", + PrefixStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), x[0], x[1]); + } + }; + + template <typename T, precision P> + struct compute_to_string<tvec3, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tvec3<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%svec3(%s, %s, %s)", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), x[0], x[1], x[2]); + } + }; + + template <typename T, precision P> + struct compute_to_string<tvec4, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tvec4<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%svec4(%s, %s, %s, %s)", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), x[0], x[1], x[2], x[3]); + } + }; + + + template <typename T, precision P> + struct compute_to_string<tmat2x2, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tmat2x2<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%smat2x2((%s, %s), (%s, %s))", + PrefixStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + x[0][0], x[0][1], + x[1][0], x[1][1]); + } + }; + + template <typename T, precision P> + struct compute_to_string<tmat2x3, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tmat2x3<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%smat2x3((%s, %s, %s), (%s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + x[0][0], x[0][1], x[0][2], + x[1][0], x[1][1], x[1][2]); + } + }; + + template <typename T, precision P> + struct compute_to_string<tmat2x4, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tmat2x4<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%smat2x4((%s, %s, %s, %s), (%s, %s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + x[0][0], x[0][1], x[0][2], x[0][3], + x[1][0], x[1][1], x[1][2], x[1][3]); + } + }; + + template <typename T, precision P> + struct compute_to_string<tmat3x2, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tmat3x2<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%smat3x2((%s, %s), (%s, %s), (%s, %s))", + PrefixStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + x[0][0], x[0][1], + x[1][0], x[1][1], + x[2][0], x[2][1]); + } + }; + + template <typename T, precision P> + struct compute_to_string<tmat3x3, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tmat3x3<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%smat3x3((%s, %s, %s), (%s, %s, %s), (%s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + x[0][0], x[0][1], x[0][2], + x[1][0], x[1][1], x[1][2], + x[2][0], x[2][1], x[2][2]); + } + }; + + template <typename T, precision P> + struct compute_to_string<tmat3x4, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tmat3x4<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%smat3x4((%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + x[0][0], x[0][1], x[0][2], x[0][3], + x[1][0], x[1][1], x[1][2], x[1][3], + x[2][0], x[2][1], x[2][2], x[2][3]); + } + }; + + template <typename T, precision P> + struct compute_to_string<tmat4x2, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tmat4x2<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%smat4x2((%s, %s), (%s, %s), (%s, %s), (%s, %s))", + PrefixStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr, + LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + x[0][0], x[0][1], + x[1][0], x[1][1], + x[2][0], x[2][1], + x[3][0], x[3][1]); + } + }; + + template <typename T, precision P> + struct compute_to_string<tmat4x3, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tmat4x3<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%smat4x3((%s, %s, %s), (%s, %s, %s), (%s, %s, %s), (%s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + x[0][0], x[0][1], x[0][2], + x[1][0], x[1][1], x[1][2], + x[2][0], x[2][1], x[2][2], + x[3][0], x[3][1], x[3][2]); + } + }; + + template <typename T, precision P> + struct compute_to_string<tmat4x4, T, P> + { + GLM_FUNC_QUALIFIER static std::string call(tmat4x4<T, P> const & x) + { + char const * PrefixStr = prefix<T>::value(); + char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value(); + std::string FormatStr(detail::format("%smat4x4((%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s))", + PrefixStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr, + LiteralStr, LiteralStr, LiteralStr, LiteralStr)); + + return detail::format(FormatStr.c_str(), + x[0][0], x[0][1], x[0][2], x[0][3], + x[1][0], x[1][1], x[1][2], x[1][3], + x[2][0], x[2][1], x[2][2], x[2][3], + x[3][0], x[3][1], x[3][2], x[3][3]); + } + }; +}//namespace detail + +template <template <typename, precision> class matType, typename T, precision P> +GLM_FUNC_DECL std::string to_string(matType<T, P> const & x) +{ + return detail::compute_to_string<matType, T, P>::call(x); +} + +}//namespace glm diff --git a/extensions/common/glm/gtx/transform.hpp b/extensions/common/glm/gtx/transform.hpp new file mode 100644 index 0000000000..22e42d7e86 --- /dev/null +++ b/extensions/common/glm/gtx/transform.hpp @@ -0,0 +1,85 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_transform +/// @file glm/gtx/transform.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_matrix_transform (dependence) +/// @see gtx_transform +/// @see gtx_transform2 +/// +/// @defgroup gtx_transform GLM_GTX_transform +/// @ingroup gtx +/// +/// @brief Add transformation matrices +/// +/// <glm/gtx/transform.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/matrix_transform.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_transform extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_transform + /// @{ + + /// Transforms a matrix with a translation 4 * 4 matrix created from 3 scalars. + /// @see gtc_matrix_transform + /// @see gtx_transform + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> translate( + tvec3<T, P> const & v); + + /// Builds a rotation 4 * 4 matrix created from an axis of 3 scalars and an angle expressed in degrees. + /// @see gtc_matrix_transform + /// @see gtx_transform + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> rotate( + T angle, + tvec3<T, P> const & v); + + /// Transforms a matrix with a scale 4 * 4 matrix created from a vector of 3 components. + /// @see gtc_matrix_transform + /// @see gtx_transform + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> scale( + tvec3<T, P> const & v); + + /// @} +}// namespace glm + +#include "transform.inl" diff --git a/extensions/common/glm/gtx/transform.inl b/extensions/common/glm/gtx/transform.inl new file mode 100644 index 0000000000..a4f511029d --- /dev/null +++ b/extensions/common/glm/gtx/transform.inl @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_transform +/// @file glm/gtx/transform.inl +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> translate( + tvec3<T, P> const & v) + { + return translate( + tmat4x4<T, P>(1.0f), v); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> rotate( + T angle, + tvec3<T, P> const & v) + { + return rotate( + tmat4x4<T, P>(1), angle, v); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> scale( + tvec3<T, P> const & v) + { + return scale( + tmat4x4<T, P>(1.0f), v); + } + +}//namespace glm diff --git a/extensions/common/glm/gtx/transform2.hpp b/extensions/common/glm/gtx/transform2.hpp new file mode 100644 index 0000000000..956026d495 --- /dev/null +++ b/extensions/common/glm/gtx/transform2.hpp @@ -0,0 +1,136 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_transform2 +/// @file glm/gtx/transform2.hpp +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_transform (dependence) +/// +/// @defgroup gtx_transform2 GLM_GTX_transform2 +/// @ingroup gtx +/// +/// @brief Add extra transformation matrices +/// +/// <glm/gtx/transform2.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtx/transform.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_transform2 extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_transform2 + /// @{ + + //! Transforms a matrix with a shearing on X axis. + //! From GLM_GTX_transform2 extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> shearX2D( + tmat3x3<T, P> const & m, + T y); + + //! Transforms a matrix with a shearing on Y axis. + //! From GLM_GTX_transform2 extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> shearY2D( + tmat3x3<T, P> const & m, + T x); + + //! Transforms a matrix with a shearing on X axis + //! From GLM_GTX_transform2 extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> shearX3D( + const tmat4x4<T, P> & m, + T y, + T z); + + //! Transforms a matrix with a shearing on Y axis. + //! From GLM_GTX_transform2 extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> shearY3D( + const tmat4x4<T, P> & m, + T x, + T z); + + //! Transforms a matrix with a shearing on Z axis. + //! From GLM_GTX_transform2 extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> shearZ3D( + const tmat4x4<T, P> & m, + T x, + T y); + + //template <typename T> GLM_FUNC_QUALIFIER tmat4x4<T, P> shear(const tmat4x4<T, P> & m, shearPlane, planePoint, angle) + // Identity + tan(angle) * cross(Normal, OnPlaneVector) 0 + // - dot(PointOnPlane, normal) * OnPlaneVector 1 + + // Reflect functions seem to don't work + //template <typename T> tmat3x3<T, P> reflect2D(const tmat3x3<T, P> & m, const tvec3<T, P>& normal){return reflect2DGTX(m, normal);} //!< \brief Build a reflection matrix (from GLM_GTX_transform2 extension) + //template <typename T> tmat4x4<T, P> reflect3D(const tmat4x4<T, P> & m, const tvec3<T, P>& normal){return reflect3DGTX(m, normal);} //!< \brief Build a reflection matrix (from GLM_GTX_transform2 extension) + + //! Build planar projection matrix along normal axis. + //! From GLM_GTX_transform2 extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat3x3<T, P> proj2D( + const tmat3x3<T, P> & m, + const tvec3<T, P>& normal); + + //! Build planar projection matrix along normal axis. + //! From GLM_GTX_transform2 extension. + template <typename T, precision P> + GLM_FUNC_DECL tmat4x4<T, P> proj3D( + const tmat4x4<T, P> & m, + const tvec3<T, P>& normal); + + //! Build a scale bias matrix. + //! From GLM_GTX_transform2 extension. + template <typename valType, precision P> + GLM_FUNC_DECL tmat4x4<valType, P> scaleBias( + valType scale, + valType bias); + + //! Build a scale bias matrix. + //! From GLM_GTX_transform2 extension. + template <typename valType, precision P> + GLM_FUNC_DECL tmat4x4<valType, P> scaleBias( + tmat4x4<valType, P> const & m, + valType scale, + valType bias); + + /// @} +}// namespace glm + +#include "transform2.inl" diff --git a/extensions/common/glm/gtx/transform2.inl b/extensions/common/glm/gtx/transform2.inl new file mode 100644 index 0000000000..4213b131cf --- /dev/null +++ b/extensions/common/glm/gtx/transform2.inl @@ -0,0 +1,177 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_transform2 +/// @file glm/gtx/transform2.inl +/// @date 2005-12-21 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> shearX2D( + const tmat3x3<T, P>& m, + T s) + { + tmat3x3<T, P> r(1); + r[0][1] = s; + return m * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> shearY2D( + const tmat3x3<T, P>& m, + T s) + { + tmat3x3<T, P> r(1); + r[1][0] = s; + return m * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> shearX3D( + const tmat4x4<T, P>& m, + T s, + T t) + { + tmat4x4<T, P> r(1); + r[1][0] = s; + r[2][0] = t; + return m * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> shearY3D( + const tmat4x4<T, P>& m, + T s, + T t) + { + tmat4x4<T, P> r(1); + r[0][1] = s; + r[2][1] = t; + return m * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> shearZ3D( + const tmat4x4<T, P>& m, + T s, + T t) + { + tmat4x4<T, P> r(1); + r[0][2] = s; + r[1][2] = t; + return m * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> reflect2D( + const tmat3x3<T, P>& m, + const tvec3<T, P>& normal) + { + tmat3x3<T, P> r(1); + r[0][0] = 1 - 2 * normal.x * normal.x; + r[0][1] = -2 * normal.x * normal.y; + r[1][0] = -2 * normal.x * normal.y; + r[1][1] = 1 - 2 * normal.y * normal.y; + return m * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> reflect3D( + const tmat4x4<T, P>& m, + const tvec3<T, P>& normal) + { + tmat4x4<T, P> r(1); + r[0][0] = 1 - 2 * normal.x * normal.x; + r[0][1] = -2 * normal.x * normal.y; + r[0][2] = -2 * normal.x * normal.z; + + r[1][0] = -2 * normal.x * normal.y; + r[1][1] = 1 - 2 * normal.y * normal.y; + r[1][2] = -2 * normal.y * normal.z; + + r[2][0] = -2 * normal.x * normal.z; + r[2][1] = -2 * normal.y * normal.z; + r[2][2] = 1 - 2 * normal.z * normal.z; + return m * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat3x3<T, P> proj2D( + const tmat3x3<T, P>& m, + const tvec3<T, P>& normal) + { + tmat3x3<T, P> r(1); + r[0][0] = 1 - normal.x * normal.x; + r[0][1] = - normal.x * normal.y; + r[1][0] = - normal.x * normal.y; + r[1][1] = 1 - normal.y * normal.y; + return m * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> proj3D( + const tmat4x4<T, P>& m, + const tvec3<T, P>& normal) + { + tmat4x4<T, P> r(1); + r[0][0] = 1 - normal.x * normal.x; + r[0][1] = - normal.x * normal.y; + r[0][2] = - normal.x * normal.z; + r[1][0] = - normal.x * normal.y; + r[1][1] = 1 - normal.y * normal.y; + r[1][2] = - normal.y * normal.z; + r[2][0] = - normal.x * normal.z; + r[2][1] = - normal.y * normal.z; + r[2][2] = 1 - normal.z * normal.z; + return m * r; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> scaleBias( + T scale, + T bias) + { + tmat4x4<T, P> result; + result[3] = tvec4<T, P>(tvec3<T, P>(bias), T(1)); + result[0][0] = scale; + result[1][1] = scale; + result[2][2] = scale; + return result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tmat4x4<T, P> scaleBias( + const tmat4x4<T, P>& m, + T scale, + T bias) + { + return m * scaleBias(scale, bias); + } +}//namespace glm + diff --git a/extensions/common/glm/gtx/type_aligned.hpp b/extensions/common/glm/gtx/type_aligned.hpp new file mode 100644 index 0000000000..ed3e68edc7 --- /dev/null +++ b/extensions/common/glm/gtx/type_aligned.hpp @@ -0,0 +1,995 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_type_aligned +/// @file glm/gtx/type_aligned.hpp +/// @date 2014-11-23 / 2014-12-23 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtc_quaternion (dependence) +/// +/// @defgroup gtx_type_aligned GLM_GTX_type_aligned +/// @ingroup gtx +/// +/// @brief Defines aligned types. +/// +/// @ref core_precision defines aligned types. +/// +/// <glm/gtx/type_aligned.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../gtc/type_precision.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_type_aligned extension included") +#endif + +namespace glm +{ + /////////////////////////// + // Signed int vector types + + /// @addtogroup gtx_type_aligned + /// @{ + + /// Low precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int8, aligned_lowp_int8, 1); + + /// Low precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int16, aligned_lowp_int16, 2); + + /// Low precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int32, aligned_lowp_int32, 4); + + /// Low precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int64, aligned_lowp_int64, 8); + + + /// Low precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int8_t, aligned_lowp_int8_t, 1); + + /// Low precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int16_t, aligned_lowp_int16_t, 2); + + /// Low precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int32_t, aligned_lowp_int32_t, 4); + + /// Low precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_int64_t, aligned_lowp_int64_t, 8); + + + /// Low precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i8, aligned_lowp_i8, 1); + + /// Low precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i16, aligned_lowp_i16, 2); + + /// Low precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i32, aligned_lowp_i32, 4); + + /// Low precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_i64, aligned_lowp_i64, 8); + + + /// Medium precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int8, aligned_mediump_int8, 1); + + /// Medium precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int16, aligned_mediump_int16, 2); + + /// Medium precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int32, aligned_mediump_int32, 4); + + /// Medium precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int64, aligned_mediump_int64, 8); + + + /// Medium precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int8_t, aligned_mediump_int8_t, 1); + + /// Medium precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int16_t, aligned_mediump_int16_t, 2); + + /// Medium precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int32_t, aligned_mediump_int32_t, 4); + + /// Medium precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_int64_t, aligned_mediump_int64_t, 8); + + + /// Medium precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i8, aligned_mediump_i8, 1); + + /// Medium precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i16, aligned_mediump_i16, 2); + + /// Medium precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i32, aligned_mediump_i32, 4); + + /// Medium precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_i64, aligned_mediump_i64, 8); + + + /// High precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int8, aligned_highp_int8, 1); + + /// High precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int16, aligned_highp_int16, 2); + + /// High precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int32, aligned_highp_int32, 4); + + /// High precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int64, aligned_highp_int64, 8); + + + /// High precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int8_t, aligned_highp_int8_t, 1); + + /// High precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int16_t, aligned_highp_int16_t, 2); + + /// High precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int32_t, aligned_highp_int32_t, 4); + + /// High precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_int64_t, aligned_highp_int64_t, 8); + + + /// High precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i8, aligned_highp_i8, 1); + + /// High precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i16, aligned_highp_i16, 2); + + /// High precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i32, aligned_highp_i32, 4); + + /// High precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_i64, aligned_highp_i64, 8); + + + /// Default precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int8, aligned_int8, 1); + + /// Default precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int16, aligned_int16, 2); + + /// Default precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int32, aligned_int32, 4); + + /// Default precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int64, aligned_int64, 8); + + + /// Default precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int8_t, aligned_int8_t, 1); + + /// Default precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int16_t, aligned_int16_t, 2); + + /// Default precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int32_t, aligned_int32_t, 4); + + /// Default precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(int64_t, aligned_int64_t, 8); + + + /// Default precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8, aligned_i8, 1); + + /// Default precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16, aligned_i16, 2); + + /// Default precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32, aligned_i32, 4); + + /// Default precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64, aligned_i64, 8); + + + /// Default precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec1, aligned_ivec1, 4); + + /// Default precision 32 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec2, aligned_ivec2, 8); + + /// Default precision 32 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec3, aligned_ivec3, 16); + + /// Default precision 32 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(ivec4, aligned_ivec4, 16); + + + /// Default precision 8 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec1, aligned_i8vec1, 1); + + /// Default precision 8 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec2, aligned_i8vec2, 2); + + /// Default precision 8 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec3, aligned_i8vec3, 4); + + /// Default precision 8 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i8vec4, aligned_i8vec4, 4); + + + /// Default precision 16 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec1, aligned_i16vec1, 2); + + /// Default precision 16 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec2, aligned_i16vec2, 4); + + /// Default precision 16 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec3, aligned_i16vec3, 8); + + /// Default precision 16 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i16vec4, aligned_i16vec4, 8); + + + /// Default precision 32 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec1, aligned_i32vec1, 4); + + /// Default precision 32 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec2, aligned_i32vec2, 8); + + /// Default precision 32 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec3, aligned_i32vec3, 16); + + /// Default precision 32 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i32vec4, aligned_i32vec4, 16); + + + /// Default precision 64 bit signed integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec1, aligned_i64vec1, 8); + + /// Default precision 64 bit signed integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec2, aligned_i64vec2, 16); + + /// Default precision 64 bit signed integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec3, aligned_i64vec3, 32); + + /// Default precision 64 bit signed integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(i64vec4, aligned_i64vec4, 32); + + + ///////////////////////////// + // Unsigned int vector types + + /// Low precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint8, aligned_lowp_uint8, 1); + + /// Low precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint16, aligned_lowp_uint16, 2); + + /// Low precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint32, aligned_lowp_uint32, 4); + + /// Low precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint64, aligned_lowp_uint64, 8); + + + /// Low precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint8_t, aligned_lowp_uint8_t, 1); + + /// Low precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint16_t, aligned_lowp_uint16_t, 2); + + /// Low precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint32_t, aligned_lowp_uint32_t, 4); + + /// Low precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_uint64_t, aligned_lowp_uint64_t, 8); + + + /// Low precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u8, aligned_lowp_u8, 1); + + /// Low precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u16, aligned_lowp_u16, 2); + + /// Low precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u32, aligned_lowp_u32, 4); + + /// Low precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(lowp_u64, aligned_lowp_u64, 8); + + + /// Medium precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint8, aligned_mediump_uint8, 1); + + /// Medium precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint16, aligned_mediump_uint16, 2); + + /// Medium precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint32, aligned_mediump_uint32, 4); + + /// Medium precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint64, aligned_mediump_uint64, 8); + + + /// Medium precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint8_t, aligned_mediump_uint8_t, 1); + + /// Medium precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint16_t, aligned_mediump_uint16_t, 2); + + /// Medium precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint32_t, aligned_mediump_uint32_t, 4); + + /// Medium precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_uint64_t, aligned_mediump_uint64_t, 8); + + + /// Medium precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u8, aligned_mediump_u8, 1); + + /// Medium precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u16, aligned_mediump_u16, 2); + + /// Medium precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u32, aligned_mediump_u32, 4); + + /// Medium precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mediump_u64, aligned_mediump_u64, 8); + + + /// High precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint8, aligned_highp_uint8, 1); + + /// High precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint16, aligned_highp_uint16, 2); + + /// High precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint32, aligned_highp_uint32, 4); + + /// High precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint64, aligned_highp_uint64, 8); + + + /// High precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint8_t, aligned_highp_uint8_t, 1); + + /// High precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint16_t, aligned_highp_uint16_t, 2); + + /// High precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint32_t, aligned_highp_uint32_t, 4); + + /// High precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_uint64_t, aligned_highp_uint64_t, 8); + + + /// High precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u8, aligned_highp_u8, 1); + + /// High precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u16, aligned_highp_u16, 2); + + /// High precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u32, aligned_highp_u32, 4); + + /// High precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(highp_u64, aligned_highp_u64, 8); + + + /// Default precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint8, aligned_uint8, 1); + + /// Default precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint16, aligned_uint16, 2); + + /// Default precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint32, aligned_uint32, 4); + + /// Default precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint64, aligned_uint64, 8); + + + /// Default precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint8_t, aligned_uint8_t, 1); + + /// Default precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint16_t, aligned_uint16_t, 2); + + /// Default precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint32_t, aligned_uint32_t, 4); + + /// Default precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uint64_t, aligned_uint64_t, 8); + + + /// Default precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8, aligned_u8, 1); + + /// Default precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16, aligned_u16, 2); + + /// Default precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32, aligned_u32, 4); + + /// Default precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64, aligned_u64, 8); + + + /// Default precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec1, aligned_uvec1, 4); + + /// Default precision 32 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec2, aligned_uvec2, 8); + + /// Default precision 32 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec3, aligned_uvec3, 16); + + /// Default precision 32 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(uvec4, aligned_uvec4, 16); + + + /// Default precision 8 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec1, aligned_u8vec1, 1); + + /// Default precision 8 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec2, aligned_u8vec2, 2); + + /// Default precision 8 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec3, aligned_u8vec3, 4); + + /// Default precision 8 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u8vec4, aligned_u8vec4, 4); + + + /// Default precision 16 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec1, aligned_u16vec1, 2); + + /// Default precision 16 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec2, aligned_u16vec2, 4); + + /// Default precision 16 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec3, aligned_u16vec3, 8); + + /// Default precision 16 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u16vec4, aligned_u16vec4, 8); + + + /// Default precision 32 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec1, aligned_u32vec1, 4); + + /// Default precision 32 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec2, aligned_u32vec2, 8); + + /// Default precision 32 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec3, aligned_u32vec3, 16); + + /// Default precision 32 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u32vec4, aligned_u32vec4, 16); + + + /// Default precision 64 bit unsigned integer aligned scalar type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec1, aligned_u64vec1, 8); + + /// Default precision 64 bit unsigned integer aligned vector of 2 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec2, aligned_u64vec2, 16); + + /// Default precision 64 bit unsigned integer aligned vector of 3 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec3, aligned_u64vec3, 32); + + /// Default precision 64 bit unsigned integer aligned vector of 4 components type. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(u64vec4, aligned_u64vec4, 32); + + + ////////////////////// + // Float vector types + + /// 32 bit single-precision floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float32, aligned_float32, 4); + + /// 64 bit double-precision floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float64, aligned_float64, 8); + + + /// 32 bit single-precision floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float32_t, aligned_float32_t, 4); + + /// 64 bit double-precision floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float64_t, aligned_float64_t, 8); + + + /// 32 bit single-precision floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float32, aligned_f32, 4); + + /// 64 bit double-precision floating-point aligned scalar. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(float64, aligned_f64, 8); + + + /// Single-precision floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec1, aligned_vec1, 4); + + /// Single-precision floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec2, aligned_vec2, 8); + + /// Single-precision floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec3, aligned_vec3, 16); + + /// Single-precision floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(vec4, aligned_vec4, 16); + + + /// Single-precision floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec1, aligned_fvec1, 4); + + /// Single-precision floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec2, aligned_fvec2, 8); + + /// Single-precision floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec3, aligned_fvec3, 16); + + /// Single-precision floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fvec4, aligned_fvec4, 16); + + + /// Single-precision floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec1, aligned_f32vec1, 4); + + /// Single-precision floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec2, aligned_f32vec2, 8); + + /// Single-precision floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec3, aligned_f32vec3, 16); + + /// Single-precision floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32vec4, aligned_f32vec4, 16); + + + /// Double-precision floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec1, aligned_dvec1, 8); + + /// Double-precision floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec2, aligned_dvec2, 16); + + /// Double-precision floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec3, aligned_dvec3, 32); + + /// Double-precision floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dvec4, aligned_dvec4, 32); + + + /// Double-precision floating-point aligned vector of 1 component. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec1, aligned_f64vec1, 8); + + /// Double-precision floating-point aligned vector of 2 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec2, aligned_f64vec2, 16); + + /// Double-precision floating-point aligned vector of 3 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec3, aligned_f64vec3, 32); + + /// Double-precision floating-point aligned vector of 4 components. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64vec4, aligned_f64vec4, 32); + + + ////////////////////// + // Float matrix types + + /// Single-precision floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1<f32> mat1; + + /// Single-precision floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat2, aligned_mat2, 16); + + /// Single-precision floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat3, aligned_mat3, 16); + + /// Single-precision floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat4, aligned_mat4, 16); + + + /// Single-precision floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1<f32> mat1; + + /// Single-precision floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat2x2, aligned_mat2x2, 16); + + /// Single-precision floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat3x3, aligned_mat3x3, 16); + + /// Single-precision floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(mat4x4, aligned_mat4x4, 16); + + + /// Single-precision floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1<f32> fmat1; + + /// Single-precision floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x2, aligned_fmat2, 16); + + /// Single-precision floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x3, aligned_fmat3, 16); + + /// Single-precision floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x4, aligned_fmat4, 16); + + + /// Single-precision floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef f32 fmat1x1; + + /// Single-precision floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x2, aligned_fmat2x2, 16); + + /// Single-precision floating-point aligned 2x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x3, aligned_fmat2x3, 16); + + /// Single-precision floating-point aligned 2x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat2x4, aligned_fmat2x4, 16); + + /// Single-precision floating-point aligned 3x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x2, aligned_fmat3x2, 16); + + /// Single-precision floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x3, aligned_fmat3x3, 16); + + /// Single-precision floating-point aligned 3x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat3x4, aligned_fmat3x4, 16); + + /// Single-precision floating-point aligned 4x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x2, aligned_fmat4x2, 16); + + /// Single-precision floating-point aligned 4x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x3, aligned_fmat4x3, 16); + + /// Single-precision floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fmat4x4, aligned_fmat4x4, 16); + + + /// Single-precision floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1<f32, defaultp> f32mat1; + + /// Single-precision floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x2, aligned_f32mat2, 16); + + /// Single-precision floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x3, aligned_f32mat3, 16); + + /// Single-precision floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x4, aligned_f32mat4, 16); + + + /// Single-precision floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef f32 f32mat1x1; + + /// Single-precision floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x2, aligned_f32mat2x2, 16); + + /// Single-precision floating-point aligned 2x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x3, aligned_f32mat2x3, 16); + + /// Single-precision floating-point aligned 2x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat2x4, aligned_f32mat2x4, 16); + + /// Single-precision floating-point aligned 3x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x2, aligned_f32mat3x2, 16); + + /// Single-precision floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x3, aligned_f32mat3x3, 16); + + /// Single-precision floating-point aligned 3x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat3x4, aligned_f32mat3x4, 16); + + /// Single-precision floating-point aligned 4x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x2, aligned_f32mat4x2, 16); + + /// Single-precision floating-point aligned 4x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x3, aligned_f32mat4x3, 16); + + /// Single-precision floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32mat4x4, aligned_f32mat4x4, 16); + + + /// Double-precision floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef detail::tmat1x1<f64, defaultp> f64mat1; + + /// Double-precision floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x2, aligned_f64mat2, 32); + + /// Double-precision floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x3, aligned_f64mat3, 32); + + /// Double-precision floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x4, aligned_f64mat4, 32); + + + /// Double-precision floating-point aligned 1x1 matrix. + /// @see gtx_type_aligned + //typedef f64 f64mat1x1; + + /// Double-precision floating-point aligned 2x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x2, aligned_f64mat2x2, 32); + + /// Double-precision floating-point aligned 2x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x3, aligned_f64mat2x3, 32); + + /// Double-precision floating-point aligned 2x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat2x4, aligned_f64mat2x4, 32); + + /// Double-precision floating-point aligned 3x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x2, aligned_f64mat3x2, 32); + + /// Double-precision floating-point aligned 3x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x3, aligned_f64mat3x3, 32); + + /// Double-precision floating-point aligned 3x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat3x4, aligned_f64mat3x4, 32); + + /// Double-precision floating-point aligned 4x2 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x2, aligned_f64mat4x2, 32); + + /// Double-precision floating-point aligned 4x3 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x3, aligned_f64mat4x3, 32); + + /// Double-precision floating-point aligned 4x4 matrix. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64mat4x4, aligned_f64mat4x4, 32); + + + ////////////////////////// + // Quaternion types + + /// Single-precision floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(quat, aligned_quat, 16); + + /// Single-precision floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(fquat, aligned_fquat, 16); + + /// Double-precision floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(dquat, aligned_dquat, 32); + + /// Single-precision floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f32quat, aligned_f32quat, 16); + + /// Double-precision floating-point aligned quaternion. + /// @see gtx_type_aligned + GLM_ALIGNED_TYPEDEF(f64quat, aligned_f64quat, 32); + + /// @} +}//namespace glm + +#include "type_aligned.inl" diff --git a/extensions/common/glm/gtx/type_aligned.inl b/extensions/common/glm/gtx/type_aligned.inl new file mode 100644 index 0000000000..fe6544c352 --- /dev/null +++ b/extensions/common/glm/gtx/type_aligned.inl @@ -0,0 +1,36 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtc_type_aligned +/// @file glm/gtc/type_aligned.inl +/// @date 2014-11-23 / 2014-11-23 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + +} diff --git a/extensions/common/glm/gtx/vector_angle.hpp b/extensions/common/glm/gtx/vector_angle.hpp new file mode 100644 index 0000000000..47f549c6e7 --- /dev/null +++ b/extensions/common/glm/gtx/vector_angle.hpp @@ -0,0 +1,89 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_vector_angle +/// @file glm/gtx/vector_angle.hpp +/// @date 2005-12-30 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// @see gtx_quaternion (dependence) +/// @see gtx_epsilon (dependence) +/// +/// @defgroup gtx_vector_angle GLM_GTX_vector_angle +/// @ingroup gtx +/// +/// @brief Compute angle between vectors +/// +/// <glm/gtx/vector_angle.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include "../gtc/epsilon.hpp" +#include "../gtx/quaternion.hpp" +#include "../gtx/rotate_vector.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_vector_angle extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_vector_angle + /// @{ + + //! Returns the absolute angle between two vectors + //! Parameters need to be normalized. + /// @see gtx_vector_angle extension + template <typename vecType> + GLM_FUNC_DECL typename vecType::value_type angle( + vecType const & x, + vecType const & y); + + //! Returns the oriented angle between two 2d vectors + //! Parameters need to be normalized. + /// @see gtx_vector_angle extension. + template <typename T, precision P> + GLM_FUNC_DECL T orientedAngle( + tvec2<T, P> const & x, + tvec2<T, P> const & y); + + //! Returns the oriented angle between two 3d vectors based from a reference axis. + //! Parameters need to be normalized. + /// @see gtx_vector_angle extension. + template <typename T, precision P> + GLM_FUNC_DECL T orientedAngle( + tvec3<T, P> const & x, + tvec3<T, P> const & y, + tvec3<T, P> const & ref); + + /// @} +}// namespace glm + +#include "vector_angle.inl" diff --git a/extensions/common/glm/gtx/vector_angle.inl b/extensions/common/glm/gtx/vector_angle.inl new file mode 100644 index 0000000000..dd61b3dca4 --- /dev/null +++ b/extensions/common/glm/gtx/vector_angle.inl @@ -0,0 +1,87 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_vector_angle +/// @file glm/gtx/vector_angle.inl +/// @date 2005-12-30 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename genType> + GLM_FUNC_QUALIFIER genType angle + ( + genType const & x, + genType const & y + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<genType>::is_iec559, "'angle' only accept floating-point inputs"); + return acos(clamp(dot(x, y), genType(-1), genType(1))); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER T angle + ( + vecType<T, P> const & x, + vecType<T, P> const & y + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'angle' only accept floating-point inputs"); + return acos(clamp(dot(x, y), T(-1), T(1))); + } + + //! \todo epsilon is hard coded to 0.01 + template <typename T, precision P> + GLM_FUNC_QUALIFIER T orientedAngle + ( + tvec2<T, P> const & x, + tvec2<T, P> const & y + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'orientedAngle' only accept floating-point inputs"); + T const Angle(acos(clamp(dot(x, y), T(-1), T(1)))); + + if(all(epsilonEqual(y, glm::rotate(x, Angle), T(0.0001)))) + return Angle; + else + return -Angle; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER T orientedAngle + ( + tvec3<T, P> const & x, + tvec3<T, P> const & y, + tvec3<T, P> const & ref + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'orientedAngle' only accept floating-point inputs"); + + T const Angle(acos(clamp(dot(x, y), T(-1), T(1)))); + return mix(Angle, -Angle, dot(ref, cross(x, y)) < T(0)); + } +}//namespace glm diff --git a/extensions/common/glm/gtx/vector_query.hpp b/extensions/common/glm/gtx/vector_query.hpp new file mode 100644 index 0000000000..657818cdc5 --- /dev/null +++ b/extensions/common/glm/gtx/vector_query.hpp @@ -0,0 +1,91 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_vector_query +/// @file glm/gtx/vector_query.hpp +/// @date 2008-03-10 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_vector_query GLM_GTX_vector_query +/// @ingroup gtx +/// +/// @brief Query informations of vector types +/// +/// <glm/gtx/vector_query.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" +#include <cfloat> +#include <limits> + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_vector_query extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_vector_query + /// @{ + + //! Check whether two vectors are collinears. + /// @see gtx_vector_query extensions. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL bool areCollinear(vecType<T, P> const & v0, vecType<T, P> const & v1, T const & epsilon); + + //! Check whether two vectors are orthogonals. + /// @see gtx_vector_query extensions. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL bool areOrthogonal(vecType<T, P> const & v0, vecType<T, P> const & v1, T const & epsilon); + + //! Check whether a vector is normalized. + /// @see gtx_vector_query extensions. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL bool isNormalized(vecType<T, P> const & v, T const & epsilon); + + //! Check whether a vector is null. + /// @see gtx_vector_query extensions. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL bool isNull(vecType<T, P> const & v, T const & epsilon); + + //! Check whether a each component of a vector is null. + /// @see gtx_vector_query extensions. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL vecType<bool, P> isCompNull(vecType<T, P> const & v, T const & epsilon); + + //! Check whether two vectors are orthonormal. + /// @see gtx_vector_query extensions. + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_DECL bool areOrthonormal(vecType<T, P> const & v0, vecType<T, P> const & v1, T const & epsilon); + + /// @} +}// namespace glm + +#include "vector_query.inl" diff --git a/extensions/common/glm/gtx/vector_query.inl b/extensions/common/glm/gtx/vector_query.inl new file mode 100644 index 0000000000..ad6a4079a5 --- /dev/null +++ b/extensions/common/glm/gtx/vector_query.inl @@ -0,0 +1,222 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_vector_query +/// @file glm/gtx/vector_query.inl +/// @date 2008-03-10 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#include <cassert> + +namespace glm{ +namespace detail +{ + template <typename T, precision P, template <typename, precision> class vecType> + struct compute_areCollinear{}; + + template <typename T, precision P> + struct compute_areCollinear<T, P, tvec2> + { + GLM_FUNC_QUALIFIER static bool call(tvec2<T, P> const & v0, tvec2<T, P> const & v1, T const & epsilon) + { + return length(cross(tvec3<T, P>(v0, static_cast<T>(0)), tvec3<T, P>(v1, static_cast<T>(0)))) < epsilon; + } + }; + + template <typename T, precision P> + struct compute_areCollinear<T, P, tvec3> + { + GLM_FUNC_QUALIFIER static bool call(tvec3<T, P> const & v0, tvec3<T, P> const & v1, T const & epsilon) + { + return length(cross(v0, v1)) < epsilon; + } + }; + + template <typename T, precision P> + struct compute_areCollinear<T, P, tvec4> + { + GLM_FUNC_QUALIFIER static bool call(tvec4<T, P> const & v0, tvec4<T, P> const & v1, T const & epsilon) + { + return length(cross(tvec3<T, P>(v0), tvec3<T, P>(v1))) < epsilon; + } + }; + + template <typename T, precision P, template <typename, precision> class vecType> + struct compute_isCompNull{}; + + template <typename T, precision P> + struct compute_isCompNull<T, P, tvec2> + { + GLM_FUNC_QUALIFIER static tvec2<bool, P> call(tvec2<T, P> const & v, T const & epsilon) + { + return tvec2<bool, P>( + (abs(v.x) < epsilon), + (abs(v.y) < epsilon)); + } + }; + + template <typename T, precision P> + struct compute_isCompNull<T, P, tvec3> + { + GLM_FUNC_QUALIFIER static tvec3<bool, P> call(tvec3<T, P> const & v, T const & epsilon) + { + return tvec3<bool, P>( + (abs(v.x) < epsilon), + (abs(v.y) < epsilon), + (abs(v.z) < epsilon)); + } + }; + + template <typename T, precision P> + struct compute_isCompNull<T, P, tvec4> + { + GLM_FUNC_QUALIFIER static tvec4<bool, P> call(tvec4<T, P> const & v, T const & epsilon) + { + return tvec4<bool, P>( + (abs(v.x) < epsilon), + (abs(v.y) < epsilon), + (abs(v.z) < epsilon), + (abs(v.w) < epsilon)); + } + }; + +}//namespace detail + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER bool areCollinear + ( + vecType<T, P> const & v0, + vecType<T, P> const & v1, + T const & epsilon + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'areCollinear' only accept floating-point inputs"); + + return detail::compute_areCollinear<T, P, vecType>::call(v0, v1, epsilon); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER bool areOrthogonal + ( + vecType<T, P> const & v0, + vecType<T, P> const & v1, + T const & epsilon + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'areOrthogonal' only accept floating-point inputs"); + + return abs(dot(v0, v1)) <= max( + static_cast<T>(1), + length(v0)) * max(static_cast<T>(1), length(v1)) * epsilon; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER bool isNormalized + ( + vecType<T, P> const & v, + T const & epsilon + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isNormalized' only accept floating-point inputs"); + + return abs(length(v) - static_cast<T>(1)) <= static_cast<T>(2) * epsilon; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER bool isNull + ( + vecType<T, P> const & v, + T const & epsilon + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isNull' only accept floating-point inputs"); + + return length(v) <= epsilon; + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER vecType<bool, P> isCompNull + ( + vecType<T, P> const & v, + T const & epsilon + ) + { + GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'isCompNull' only accept floating-point inputs"); + + return detail::compute_isCompNull<T, P, vecType>::call(v, epsilon); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<bool, P> isCompNull + ( + tvec2<T, P> const & v, + T const & epsilon) + { + return tvec2<bool, P>( + abs(v.x) < epsilon, + abs(v.y) < epsilon); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<bool, P> isCompNull + ( + tvec3<T, P> const & v, + T const & epsilon + ) + { + return tvec3<bool, P>( + abs(v.x) < epsilon, + abs(v.y) < epsilon, + abs(v.z) < epsilon); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<bool, P> isCompNull + ( + tvec4<T, P> const & v, + T const & epsilon + ) + { + return tvec4<bool, P>( + abs(v.x) < epsilon, + abs(v.y) < epsilon, + abs(v.z) < epsilon, + abs(v.w) < epsilon); + } + + template <typename T, precision P, template <typename, precision> class vecType> + GLM_FUNC_QUALIFIER bool areOrthonormal + ( + vecType<T, P> const & v0, + vecType<T, P> const & v1, + T const & epsilon + ) + { + return isNormalized(v0, epsilon) && isNormalized(v1, epsilon) && (abs(dot(v0, v1)) <= epsilon); + } + +}//namespace glm diff --git a/extensions/common/glm/gtx/wrap.hpp b/extensions/common/glm/gtx/wrap.hpp new file mode 100644 index 0000000000..56c2e815e2 --- /dev/null +++ b/extensions/common/glm/gtx/wrap.hpp @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_wrap +/// @file glm/gtx/wrap.hpp +/// @date 2009-11-25 / 2011-06-07 +/// @author Christophe Riccio +/// +/// @see core (dependence) +/// +/// @defgroup gtx_wrap GLM_GTX_wrap +/// @ingroup gtx +/// +/// @brief Wrapping mode of texture coordinates. +/// +/// <glm/gtx/wrap.hpp> need to be included to use these functionalities. +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +// Dependency: +#include "../glm.hpp" + +#if(defined(GLM_MESSAGES) && !defined(GLM_EXT_INCLUDED)) +# pragma message("GLM: GLM_GTX_wrap extension included") +#endif + +namespace glm +{ + /// @addtogroup gtx_wrap + /// @{ + + /// Simulate GL_CLAMP OpenGL wrap mode + /// @see gtx_wrap extension. + template <typename genType> + GLM_FUNC_DECL genType clamp(genType const & Texcoord); + + /// Simulate GL_REPEAT OpenGL wrap mode + /// @see gtx_wrap extension. + template <typename genType> + GLM_FUNC_DECL genType repeat(genType const & Texcoord); + + /// Simulate GL_MIRROR_REPEAT OpenGL wrap mode + /// @see gtx_wrap extension. + template <typename genType> + GLM_FUNC_DECL genType mirrorRepeat(genType const & Texcoord); + + /// @} +}// namespace glm + +#include "wrap.inl" diff --git a/extensions/common/glm/gtx/wrap.inl b/extensions/common/glm/gtx/wrap.inl new file mode 100644 index 0000000000..6dc20ff6ab --- /dev/null +++ b/extensions/common/glm/gtx/wrap.inl @@ -0,0 +1,185 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref gtx_wrap +/// @file glm/gtx/wrap.inl +/// @date 2009-11-25 / 2011-06-07 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +namespace glm +{ + template <typename genType> + GLM_FUNC_QUALIFIER genType clamp + ( + genType const & Texcoord + ) + { + return glm::clamp(Texcoord, genType(0), genType(1)); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> clamp + ( + tvec2<T, P> const & Texcoord + ) + { + tvec2<T, P> Result; + for(typename tvec2<T, P>::size_type i = 0; i < tvec2<T, P>::value_size(); ++i) + Result[i] = clamp(Texcoord[i]); + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> clamp + ( + tvec3<T, P> const & Texcoord + ) + { + tvec3<T, P> Result; + for(typename tvec3<T, P>::size_type i = 0; i < tvec3<T, P>::value_size(); ++i) + Result[i] = clamp(Texcoord[i]); + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> clamp + ( + tvec4<T, P> const & Texcoord + ) + { + tvec4<T, P> Result; + for(typename tvec4<T, P>::size_type i = 0; i < tvec4<T, P>::value_size(); ++i) + Result[i] = clamp(Texcoord[i]); + return Result; + } + + //////////////////////// + // repeat + + template <typename genType> + GLM_FUNC_QUALIFIER genType repeat + ( + genType const & Texcoord + ) + { + return glm::fract(Texcoord); + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> repeat + ( + tvec2<T, P> const & Texcoord + ) + { + tvec2<T, P> Result; + for(typename tvec2<T, P>::size_type i = 0; i < tvec2<T, P>::value_size(); ++i) + Result[i] = repeat(Texcoord[i]); + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> repeat + ( + tvec3<T, P> const & Texcoord + ) + { + tvec3<T, P> Result; + for(typename tvec3<T, P>::size_type i = 0; i < tvec3<T, P>::value_size(); ++i) + Result[i] = repeat(Texcoord[i]); + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> repeat + ( + tvec4<T, P> const & Texcoord + ) + { + tvec4<T, P> Result; + for(typename tvec4<T, P>::size_type i = 0; i < tvec4<T, P>::value_size(); ++i) + Result[i] = repeat(Texcoord[i]); + return Result; + } + + //////////////////////// + // mirrorRepeat + + template <typename genType, precision P> + GLM_FUNC_QUALIFIER genType mirrorRepeat + ( + genType const & Texcoord + ) + { + genType const Clamp = genType(int(glm::floor(Texcoord)) % 2); + genType const Floor = glm::floor(Texcoord); + genType const Rest = Texcoord - Floor; + genType const Mirror = Clamp + Rest; + + genType Out; + if(Mirror >= genType(1)) + Out = genType(1) - Rest; + else + Out = Rest; + return Out; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec2<T, P> mirrorRepeat + ( + tvec2<T, P> const & Texcoord + ) + { + tvec2<T, P> Result; + for(typename tvec2<T, P>::size_type i = 0; i < tvec2<T, P>::value_size(); ++i) + Result[i] = mirrorRepeat(Texcoord[i]); + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec3<T, P> mirrorRepeat + ( + tvec3<T, P> const & Texcoord + ) + { + tvec3<T, P> Result; + for(typename tvec3<T, P>::size_type i = 0; i < tvec3<T, P>::value_size(); ++i) + Result[i] = mirrorRepeat(Texcoord[i]); + return Result; + } + + template <typename T, precision P> + GLM_FUNC_QUALIFIER tvec4<T, P> mirrorRepeat + ( + tvec4<T, P> const & Texcoord + ) + { + tvec4<T, P> Result; + for(typename tvec4<T, P>::size_type i = 0; i < tvec4<T, P>::value_size(); ++i) + Result[i] = mirrorRepeat(Texcoord[i]); + return Result; + } +}//namespace glm diff --git a/extensions/common/glm/integer.hpp b/extensions/common/glm/integer.hpp new file mode 100644 index 0000000000..54819f524d --- /dev/null +++ b/extensions/common/glm/integer.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/integer.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/func_integer.hpp" diff --git a/extensions/common/glm/mat2x2.hpp b/extensions/common/glm/mat2x2.hpp new file mode 100644 index 0000000000..e02700123b --- /dev/null +++ b/extensions/common/glm/mat2x2.hpp @@ -0,0 +1,81 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/mat2x2.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_mat2x2.hpp" + +namespace glm +{ + /// 2 columns of 2 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, lowp> lowp_mat2; + + /// 2 columns of 2 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, mediump> mediump_mat2; + + /// 2 columns of 2 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, highp> highp_mat2; + + /// 2 columns of 2 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, lowp> lowp_mat2x2; + + /// 2 columns of 2 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, mediump> mediump_mat2x2; + + /// 2 columns of 2 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x2<float, highp> highp_mat2x2; + +}//namespace glm diff --git a/extensions/common/glm/mat2x3.hpp b/extensions/common/glm/mat2x3.hpp new file mode 100644 index 0000000000..ecfe30b9ec --- /dev/null +++ b/extensions/common/glm/mat2x3.hpp @@ -0,0 +1,61 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/mat2x3.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_mat2x3.hpp" + +namespace glm +{ + /// 2 columns of 3 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x3<float, lowp> lowp_mat2x3; + + /// 2 columns of 3 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x3<float, mediump> mediump_mat2x3; + + /// 2 columns of 3 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x3<float, highp> highp_mat2x3; + +}//namespace glm + diff --git a/extensions/common/glm/mat2x4.hpp b/extensions/common/glm/mat2x4.hpp new file mode 100644 index 0000000000..40696ecd75 --- /dev/null +++ b/extensions/common/glm/mat2x4.hpp @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/mat2x4.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_mat2x4.hpp" + +namespace glm +{ + /// 2 columns of 4 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x4<float, lowp> lowp_mat2x4; + + /// 2 columns of 4 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x4<float, mediump> mediump_mat2x4; + + /// 2 columns of 4 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat2x4<float, highp> highp_mat2x4; + +}//namespace glm diff --git a/extensions/common/glm/mat3x2.hpp b/extensions/common/glm/mat3x2.hpp new file mode 100644 index 0000000000..206a22f19a --- /dev/null +++ b/extensions/common/glm/mat3x2.hpp @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/mat3x2.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_mat3x2.hpp" + +namespace glm +{ + /// 3 columns of 2 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x2<float, lowp> lowp_mat3x2; + + /// 3 columns of 2 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x2<float, mediump> mediump_mat3x2; + + /// 3 columns of 2 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x2<float, highp> highp_mat3x2; + +}//namespace diff --git a/extensions/common/glm/mat3x3.hpp b/extensions/common/glm/mat3x3.hpp new file mode 100644 index 0000000000..c7d35e60f9 --- /dev/null +++ b/extensions/common/glm/mat3x3.hpp @@ -0,0 +1,81 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/mat3x3.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_mat3x3.hpp" + +namespace glm +{ + /// 3 columns of 3 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, lowp> lowp_mat3; + + /// 3 columns of 3 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, mediump> mediump_mat3; + + /// 3 columns of 3 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, highp> highp_mat3; + + /// 3 columns of 3 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, lowp> lowp_mat3x3; + + /// 3 columns of 3 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, mediump> mediump_mat3x3; + + /// 3 columns of 3 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x3<float, highp> highp_mat3x3; + +}//namespace glm diff --git a/extensions/common/glm/mat3x4.hpp b/extensions/common/glm/mat3x4.hpp new file mode 100644 index 0000000000..cbf2f56970 --- /dev/null +++ b/extensions/common/glm/mat3x4.hpp @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/mat3x4.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_mat3x4.hpp" + +namespace glm +{ + /// 3 columns of 4 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x4<float, lowp> lowp_mat3x4; + + /// 3 columns of 4 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x4<float, mediump> mediump_mat3x4; + + /// 3 columns of 4 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat3x4<float, highp> highp_mat3x4; + +}//namespace glm diff --git a/extensions/common/glm/mat4x2.hpp b/extensions/common/glm/mat4x2.hpp new file mode 100644 index 0000000000..bd0ccd201c --- /dev/null +++ b/extensions/common/glm/mat4x2.hpp @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/mat4x2.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_mat4x2.hpp" + +namespace glm +{ + /// 4 columns of 2 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x2<float, lowp> lowp_mat4x2; + + /// 4 columns of 2 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x2<float, mediump> mediump_mat4x2; + + /// 4 columns of 2 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x2<float, highp> highp_mat4x2; + +}//namespace glm diff --git a/extensions/common/glm/mat4x3.hpp b/extensions/common/glm/mat4x3.hpp new file mode 100644 index 0000000000..637df866d8 --- /dev/null +++ b/extensions/common/glm/mat4x3.hpp @@ -0,0 +1,60 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/mat4x4.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_mat4x3.hpp" + +namespace glm +{ + /// 4 columns of 3 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x3<float, lowp> lowp_mat4x3; + + /// 4 columns of 3 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x3<float, mediump> mediump_mat4x3; + + /// 4 columns of 3 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x3<float, highp> highp_mat4x3; + +}//namespace glm diff --git a/extensions/common/glm/mat4x4.hpp b/extensions/common/glm/mat4x4.hpp new file mode 100644 index 0000000000..f8107d4960 --- /dev/null +++ b/extensions/common/glm/mat4x4.hpp @@ -0,0 +1,81 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/mat4x4.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_mat4x4.hpp" + +namespace glm +{ + /// 4 columns of 4 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, lowp> lowp_mat4; + + /// 4 columns of 4 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, mediump> mediump_mat4; + + /// 4 columns of 4 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, highp> highp_mat4; + + /// 4 columns of 4 components matrix of low precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, lowp> lowp_mat4x4; + + /// 4 columns of 4 components matrix of medium precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, mediump> mediump_mat4x4; + + /// 4 columns of 4 components matrix of high precision floating-point numbers. + /// There is no guarantee on the actual precision. + /// + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.1.6 Matrices</a> + /// @see <a href="http://www.opengl.org/registry/doc/GLSLangSpec.4.20.8.pdf">GLSL 4.20.8 specification, section 4.7.2 Precision Qualifier</a> + typedef tmat4x4<float, highp> highp_mat4x4; + +}//namespace glm diff --git a/extensions/common/glm/matrix.hpp b/extensions/common/glm/matrix.hpp new file mode 100644 index 0000000000..c08b2ce046 --- /dev/null +++ b/extensions/common/glm/matrix.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/matrix.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/func_matrix.hpp" diff --git a/extensions/common/glm/packing.hpp b/extensions/common/glm/packing.hpp new file mode 100644 index 0000000000..716ae8c7b2 --- /dev/null +++ b/extensions/common/glm/packing.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/packing.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/func_packing.hpp" diff --git a/extensions/common/glm/trigonometric.hpp b/extensions/common/glm/trigonometric.hpp new file mode 100644 index 0000000000..43c19300f9 --- /dev/null +++ b/extensions/common/glm/trigonometric.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/trigonometric.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/func_trigonometric.hpp" diff --git a/extensions/common/glm/vec2.hpp b/extensions/common/glm/vec2.hpp new file mode 100644 index 0000000000..72703a7242 --- /dev/null +++ b/extensions/common/glm/vec2.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/vec2.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_vec2.hpp" diff --git a/extensions/common/glm/vec3.hpp b/extensions/common/glm/vec3.hpp new file mode 100644 index 0000000000..e26b03c12b --- /dev/null +++ b/extensions/common/glm/vec3.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/vec3.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_vec3.hpp" diff --git a/extensions/common/glm/vec4.hpp b/extensions/common/glm/vec4.hpp new file mode 100644 index 0000000000..e0bccb42bd --- /dev/null +++ b/extensions/common/glm/vec4.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/vec4.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/type_vec4.hpp" diff --git a/extensions/common/glm/vector_relational.hpp b/extensions/common/glm/vector_relational.hpp new file mode 100644 index 0000000000..42f26495d8 --- /dev/null +++ b/extensions/common/glm/vector_relational.hpp @@ -0,0 +1,35 @@ +/////////////////////////////////////////////////////////////////////////////////// +/// OpenGL Mathematics (glm.g-truc.net) +/// +/// Copyright (c) 2005 - 2015 G-Truc Creation (www.g-truc.net) +/// Permission is hereby granted, free of charge, to any person obtaining a copy +/// of this software and associated documentation files (the "Software"), to deal +/// in the Software without restriction, including without limitation the rights +/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +/// copies of the Software, and to permit persons to whom the Software is +/// furnished to do so, subject to the following conditions: +/// +/// The above copyright notice and this permission notice shall be included in +/// all copies or substantial portions of the Software. +/// +/// Restrictions: +/// By making use of the Software for military purposes, you choose to make +/// a Bunny unhappy. +/// +/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +/// THE SOFTWARE. +/// +/// @ref core +/// @file glm/vector_relational.hpp +/// @date 2013-12-24 / 2013-12-24 +/// @author Christophe Riccio +/////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "detail/func_vector_relational.hpp" diff --git a/extensions/common/logging.hpp b/extensions/common/logging.hpp new file mode 100644 index 0000000000..5a23d6d357 --- /dev/null +++ b/extensions/common/logging.hpp @@ -0,0 +1,6 @@ +#pragma once +#define _ELPP_THREAD_SAFE +#define _ELPP_FORCE_USE_STD_THREAD +#define _ELPP_NO_DEFAULT_LOG_FILE +#define _ELPP_DISABLE_DEFAULT_CRASH_HANDLING +#include "easyloggingc++.hpp" \ No newline at end of file diff --git a/extensions/common/lzoconf.h b/extensions/common/lzoconf.h new file mode 100644 index 0000000000..64ef27934b --- /dev/null +++ b/extensions/common/lzoconf.h @@ -0,0 +1,453 @@ +/* lzoconf.h -- configuration of the LZO data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2015 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + <markus@oberhumer.com> + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H_INCLUDED +#define __LZOCONF_H_INCLUDED 1 + +#define LZO_VERSION 0x2090 +#define LZO_VERSION_STRING "2.09" +#define LZO_VERSION_DATE "Feb 04 2015" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include <config.h> +#endif +#include <limits.h> +#include <stddef.h> + + +/*********************************************************************** +// LZO requires a conforming <limits.h> +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(USHRT_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* get OS and architecture defines */ +#ifndef __LZODEFS_H_INCLUDED +#include <lzo/lzodefs.h> +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// some core defines +************************************************************************/ + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER 1 +# elif defined(__CHECKER__) +# define __LZO_CHECKER 1 +# elif defined(__INSURE__) +# define __LZO_CHECKER 1 +# elif defined(__PURIFY__) +# define __LZO_CHECKER 1 +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* lzo_uint must match size_t */ +#if !defined(LZO_UINT_MAX) +# if (LZO_ABI_LLP64) +# if (LZO_OS_WIN64) + typedef unsigned __int64 lzo_uint; + typedef __int64 lzo_int; +# define LZO_TYPEOF_LZO_INT LZO_TYPEOF___INT64 +# else + typedef lzo_ullong_t lzo_uint; + typedef lzo_llong_t lzo_int; +# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG_LONG +# endif +# define LZO_SIZEOF_LZO_INT 8 +# define LZO_UINT_MAX 0xffffffffffffffffull +# define LZO_INT_MAX 9223372036854775807LL +# define LZO_INT_MIN (-1LL - LZO_INT_MAX) +# elif (LZO_ABI_IP32L64) /* MIPS R5900 */ + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_SIZEOF_LZO_INT LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_INT +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_SIZEOF_LZO_INT LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +/* The larger type of lzo_uint and lzo_uint32_t. */ +#if (LZO_SIZEOF_LZO_INT >= 4) +# define lzo_xint lzo_uint +#else +# define lzo_xint lzo_uint32_t +#endif + +typedef int lzo_bool; + +/* sanity checks */ +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int) == LZO_SIZEOF_LZO_INT) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_INT) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t)) + +#ifndef __LZO_MMODEL +#define __LZO_MMODEL /*empty*/ +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_xintp lzo_xint __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * + +#define lzo_int8_tp lzo_int8_t __LZO_MMODEL * +#define lzo_uint8_tp lzo_uint8_t __LZO_MMODEL * +#define lzo_int16_tp lzo_int16_t __LZO_MMODEL * +#define lzo_uint16_tp lzo_uint16_t __LZO_MMODEL * +#define lzo_int32_tp lzo_int32_t __LZO_MMODEL * +#define lzo_uint32_tp lzo_uint32_t __LZO_MMODEL * +#if defined(lzo_int64_t) +#define lzo_int64_tp lzo_int64_t __LZO_MMODEL * +#define lzo_uint64_tp lzo_uint64_t __LZO_MMODEL * +#endif + +/* Older LZO versions used to support ancient systems and memory models + * such as 16-bit MSDOS with __huge pointers or Cray PVP, but these + * obsolete configurations are not supported any longer. + */ +#if defined(__LZO_MMODEL_HUGE) +#error "__LZO_MMODEL_HUGE memory model is unsupported" +#endif +#if (LZO_MM_PVP) +#error "LZO_MM_PVP memory model is unsupported" +#endif +#if (LZO_SIZEOF_INT < 4) +#error "LZO_SIZEOF_INT < 4 is unsupported" +#endif +#if (__LZO_UINTPTR_T_IS_POINTER) +#error "__LZO_UINTPTR_T_IS_POINTER is unsupported" +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) >= 4) +/* Strange configurations where sizeof(lzo_uint) != sizeof(size_t) should + * work but have not received much testing lately, so be strict here. + */ +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(size_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(ptrdiff_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_voidp)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_bytep)) + + +/*********************************************************************** +// function types +************************************************************************/ + +/* name mangling */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# define __LZO_CDECL __lzo_cdecl +#endif + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 /*empty*/ +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 /*empty*/ +#endif + +/* __cdecl calling convention for public C and assembly functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(r) __LZO_EXPORT1 r __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(r) __LZO_EXTERN_C LZO_PUBLIC(r) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(r) static r __LZO_CDECL +#endif + +/* function types */ +typedef int +(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + +typedef int +(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + + +/* Callback interface. Currently only the progress indicator ("nprogress") + * is used, but this may change in a future release. */ + +struct lzo_callback_t; +typedef struct lzo_callback_t lzo_callback_t; +#define lzo_callback_p lzo_callback_t __LZO_MMODEL * + +/* malloc & free function types */ +typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t) + (lzo_callback_p self, lzo_uint items, lzo_uint size); +typedef void (__LZO_CDECL *lzo_free_func_t) + (lzo_callback_p self, lzo_voidp ptr); + +/* a progress indicator callback function */ +typedef void (__LZO_CDECL *lzo_progress_func_t) + (lzo_callback_p, lzo_uint, lzo_uint, int); + +struct lzo_callback_t +{ + /* custom allocators (set to 0 to disable) */ + lzo_alloc_func_t nalloc; /* [not used right now] */ + lzo_free_func_t nfree; /* [not used right now] */ + + /* a progress indicator callback function (set to 0 to disable) */ + lzo_progress_func_t nprogress; + + /* INFO: the first parameter "self" of the nalloc/nfree/nprogress + * callbacks points back to this struct, so you are free to store + * some extra info in the following variables. */ + lzo_voidp user1; + lzo_xint user2; + lzo_xint user3; +}; + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) +#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ +#define LZO_E_INVALID_ARGUMENT (-10) +#define LZO_E_INVALID_ALIGNMENT (-11) /* pointer argument is not properly aligned */ +#define LZO_E_OUTPUT_NOT_CONSUMED (-12) +#define LZO_E_INTERNAL_ERROR (-99) + + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep)) +#endif + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32_t),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_callback_t)) +LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) + lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memset(lzo_voidp buf, int c, lzo_uint len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32_t) + lzo_adler32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); +LZO_EXTERN(lzo_uint32_t) + lzo_crc32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); +LZO_EXTERN(const lzo_uint32_tp) + lzo_get_crc32_table(void); + +/* misc. */ +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { + lzo_voidp a00; lzo_bytep a01; lzo_uint a02; lzo_xint a03; lzo_uintptr_t a04; + void *a05; unsigned char *a06; unsigned long a07; size_t a08; ptrdiff_t a09; +#if defined(lzo_int64_t) + lzo_uint64_t a10; +#endif +} lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of 'size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size); +#define LZO_PTR_ALIGN_UP(p,size) \ + ((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size))) + + +/*********************************************************************** +// deprecated macros - only for backward compatibility +************************************************************************/ + +/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */ +#define lzo_byte unsigned char +/* deprecated type names */ +#define lzo_int32 lzo_int32_t +#define lzo_uint32 lzo_uint32_t +#define lzo_int32p lzo_int32_t __LZO_MMODEL * +#define lzo_uint32p lzo_uint32_t __LZO_MMODEL * +#define LZO_INT32_MAX LZO_INT32_C(2147483647) +#define LZO_UINT32_MAX LZO_UINT32_C(4294967295) +#if defined(lzo_int64_t) +#define lzo_int64 lzo_int64_t +#define lzo_uint64 lzo_uint64_t +#define lzo_int64p lzo_int64_t __LZO_MMODEL * +#define lzo_uint64p lzo_uint64_t __LZO_MMODEL * +#define LZO_INT64_MAX LZO_INT64_C(9223372036854775807) +#define LZO_UINT64_MAX LZO_UINT64_C(18446744073709551615) +#endif +/* deprecated types */ +typedef union { lzo_bytep a; lzo_uint b; } __lzo_pu_u; +typedef union { lzo_bytep a; lzo_uint32_t b; } __lzo_pu32_u; +/* deprecated defines */ +#if !defined(LZO_SIZEOF_LZO_UINT) +# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LZO_INT +#endif + +#if defined(LZO_CFG_COMPAT) + +#define __LZOCONF_H 1 + +#if defined(LZO_ARCH_I086) +# define __LZO_i386 1 +#elif defined(LZO_ARCH_I386) +# define __LZO_i386 1 +#endif + +#if defined(LZO_OS_DOS16) +# define __LZO_DOS 1 +# define __LZO_DOS16 1 +#elif defined(LZO_OS_DOS32) +# define __LZO_DOS 1 +#elif defined(LZO_OS_WIN16) +# define __LZO_WIN 1 +# define __LZO_WIN16 1 +#elif defined(LZO_OS_WIN32) +# define __LZO_WIN 1 +#endif + +#define __LZO_CMODEL /*empty*/ +#define __LZO_DMODEL /*empty*/ +#define __LZO_ENTRY __LZO_CDECL +#define LZO_EXTERN_CDECL LZO_EXTERN +#define LZO_ALIGN LZO_PTR_ALIGN_UP + +#define lzo_compress_asm_t lzo_compress_t +#define lzo_decompress_asm_t lzo_decompress_t + +#endif /* LZO_CFG_COMPAT */ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + + +/* vim:set ts=4 sw=4 et: */ diff --git a/extensions/common/lzodefs.h b/extensions/common/lzodefs.h new file mode 100644 index 0000000000..1535c1e205 --- /dev/null +++ b/extensions/common/lzodefs.h @@ -0,0 +1,3134 @@ +/* lzodefs.h -- architecture, OS and compiler specific defines + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2015 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + <markus@oberhumer.com> + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if !defined(LZO_CFG_NO_DISABLE_WUNDEF) +#if defined(__ARMCC_VERSION) +# pragma diag_suppress 193 +#elif defined(__clang__) && defined(__clang_minor__) +# pragma clang diagnostic ignored "-Wundef" +#elif defined(__INTEL_COMPILER) +# pragma warning(disable: 193) +#elif defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) +# if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) +# pragma GCC diagnostic ignored "-Wundef" +# endif +#elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if ((_MSC_VER-0) >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#endif +#if 0 && defined(__POCC__) && defined(_WIN32) +# if (__POCC__ >= 400) +# pragma warn(disable: 2216) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#ifndef _CRT_NONSTDC_NO_WARNINGS +#define _CRT_NONSTDC_NO_WARNINGS 1 +#endif +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif +#endif +#if 0 +#define LZO_0xffffUL 0xfffful +#define LZO_0xffffffffUL 0xfffffffful +#else +#define LZO_0xffffUL 65535ul +#define LZO_0xffffffffUL 4294967295ul +#endif +#define LZO_0xffffL LZO_0xffffUL +#define LZO_0xffffffffL LZO_0xffffffffUL +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if defined(__COUNTER__) +# ifndef LZO_CFG_USE_COUNTER +# define LZO_CFG_USE_COUNTER 1 +# endif +#else +# undef LZO_CFG_USE_COUNTER +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED 1 +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT0() /*empty*/ +#define LZO_PP_CONCAT1(a) a +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() +#define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) +#define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) +#define LZO_PP_EMPTY /*empty*/ +#define LZO_PP_EMPTY0() /*empty*/ +#define LZO_PP_EMPTY1(a) /*empty*/ +#define LZO_PP_EMPTY2(a,b) /*empty*/ +#define LZO_PP_EMPTY3(a,b,c) /*empty*/ +#define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ +#define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ +#define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ +#define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) +#define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-!!(b))) - (o)) << 1) + (o)*!!(b)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +# define LZO_EXTERN_C_BEGIN extern "C" { +# define LZO_EXTERN_C_END } +#else +# define LZO_EXTERN_C extern +# define LZO_EXTERN_C_BEGIN /*empty*/ +# define LZO_EXTERN_C_END /*empty*/ +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if (LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif (LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__arm__) && !defined(__i386__) && !defined(__ppc__) && !defined(__x64_64__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif defined(__mips__) && defined(__psp__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) && defined(__MACH__) +# if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) +# define LZO_OS_POSIX_DARWIN 1040 +# define LZO_INFO_OS_POSIX "darwin_iphone" +# elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) +# define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +# define LZO_INFO_OS_POSIX "darwin" +# else +# define LZO_OS_POSIX_DARWIN 1 +# define LZO_INFO_OS_POSIX "darwin" +# endif +# define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) +# define LZO_CC_INTELC __INTEL_COMPILER +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_INTELC_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) +# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) +# else +# define LZO_CC_CLANG 0x010000L +# endif +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_CLANG_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +# define LZO_INFO_CC "clang" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_LLVM LZO_CC_LLVM_GNUC +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__ARMCC_VERSION) && !defined(__GNUC__) +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__CODEGEARC__) +# define LZO_CC_CODEGEARC 1 +# define LZO_INFO_CC "CodeGear C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) +# define LZO_CC_GHS 1 +# define LZO_INFO_CC "Green Hills C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_GHS_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) +# define LZO_CC_HPACC __HP_aCC +# define LZO_INFO_CC "HP aCC" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) && ((__IBMC__-0) > 0) +# define LZO_CC_IBMC __IBMC__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) +# define LZO_CC_IBMC __IBMCPP__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) +# define LZO_CC_MWERKS __MWERKS__ +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) +# else +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" +# endif +# define LZO_INFO_CC "Portland Group PGI C" +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if ((__ZTC__-0) == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_MSC _MSC_VER +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if (LZO_CC_GNUC) && defined(__OPEN64__) +# if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) +# define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) +# define LZO_CC_OPEN64_GNUC LZO_CC_GNUC +# endif +#endif +#if (LZO_CC_GNUC) && defined(__PCC__) +# if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) +# define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) +# define LZO_CC_PCC_GNUC LZO_CC_GNUC +# endif +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if (LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__aarch64__) +# define LZO_ARCH_ARM64 1 +# define LZO_INFO_ARCH "arm64" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__avr32__) || defined(__AVR32__) +# define LZO_ARCH_AVR32 1 +# define LZO_INFO_ARCH "avr32" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if !defined(LZO_ARCH_ARM_THUMB2) +#if (LZO_ARCH_ARM) +# if defined(__ARM_ARCH_ISA_THUMB) +# if ((__ARM_ARCH_ISA_THUMB)+0 >= 2) +# define LZO_ARCH_ARM_THUMB2 1 +# endif +# elif 1 && defined(__thumb2__) +# define LZO_ARCH_ARM_THUMB2 1 +# elif 1 && defined(__TARGET_ARCH_THUMB) && ((__TARGET_ARCH_THUMB)+0 >= 4) +# define LZO_ARCH_ARM_THUMB2 1 +# endif +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) +# define LZO_ARCH_X64 1 +#elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_AMD64 1 +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) +# define LZO_ARCH_AARCH64 1 +#elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_ARM64 1 +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) +# define LZO_ARCH_X86 1 +#elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_I386 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086PM && !LZO_ARCH_I086) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# if !defined(LZO_TARGET_FEATURE_SSE2) +# if defined(__SSE2__) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif defined(_MSC_VER) && (defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif (LZO_CC_INTELC_MSC || LZO_CC_MSC) && defined(_M_AMD64) +# define LZO_TARGET_FEATURE_SSE2 1 +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSSE3) +# if (LZO_TARGET_FEATURE_SSE2) +# if defined(__SSSE3__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# elif defined(_MSC_VER) && defined(__AVX__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSE4_2) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__SSE4_2__) +# define LZO_TARGET_FEATURE_SSE4_2 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__AVX__) +# define LZO_TARGET_FEATURE_AVX 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX2) +# if (LZO_TARGET_FEATURE_AVX) +# if defined(__AVX2__) +# define LZO_TARGET_FEATURE_AVX2 1 +# endif +# endif +# endif +#endif +#if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if defined(__ARM_NEON) && ((__ARM_NEON)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# elif 1 && defined(__ARM_NEON__) && ((__ARM_NEON__)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# elif 1 && defined(__TARGET_FEATURE_NEON) && ((__TARGET_FEATURE_NEON)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if 1 +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#endif +#if 0 +#elif !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown LZO_ARCH_I086 memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "unexpected configuration - check your compiler defines" +# elif (LZO_CC_ZORTECHC) +# else +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_gnuc_extension__ __extension__ +#else +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#if !defined(lzo_has_builtin) +#if (LZO_CC_CLANG) && defined(__has_builtin) +# define lzo_has_builtin __has_builtin +#endif +#endif +#if !defined(lzo_has_builtin) +# define lzo_has_builtin(x) 0 +#endif +#if !defined(lzo_has_attribute) +#if (LZO_CC_CLANG) && defined(__has_attribute) +# define lzo_has_attribute __has_attribute +#endif +#endif +#if !defined(lzo_has_attribute) +# define lzo_has_attribute(x) 0 +#endif +#if !defined(lzo_has_declspec_attribute) +#if (LZO_CC_CLANG) && defined(__has_declspec_attribute) +# define lzo_has_declspec_attribute __has_declspec_attribute +#endif +#endif +#if !defined(lzo_has_declspec_attribute) +# define lzo_has_declspec_attribute(x) 0 +#endif +#if !defined(lzo_has_feature) +#if (LZO_CC_CLANG) && defined(__has_feature) +# define lzo_has_feature __has_feature +#endif +#endif +#if !defined(lzo_has_feature) +# define lzo_has_feature(x) 0 +#endif +#if !defined(lzo_has_extension) +#if (LZO_CC_CLANG) && defined(__has_extension) +# define lzo_has_extension __has_extension +#elif (LZO_CC_CLANG) && defined(__has_feature) +# define lzo_has_extension __has_feature +#endif +#endif +#if !defined(lzo_has_extension) +# define lzo_has_extension 0 +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# else +# define LZO_CFG_USE_NEW_STYLE_CASTS 1 +# endif +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(__cplusplus) +# if defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# undef LZO_CFG_USE_NEW_STYLE_CASTS +# endif +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(LZO_REINTERPRET_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast<t> (e)) +# endif +#endif +#if !defined(LZO_REINTERPRET_CAST) +# define LZO_REINTERPRET_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_STATIC_CAST(t,e) (static_cast<t> (e)) +# endif +#endif +#if !defined(LZO_STATIC_CAST) +# define LZO_STATIC_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST2) +# define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) +#endif +#if !defined(LZO_UNCONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_PCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_PCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_PCAST) +# define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) +#endif +#if !defined(LZO_CCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_CCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_CCAST) +# define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) +#endif +#if !defined(LZO_ICONV) +# define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ICAST) +# define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ITRUNC) +# define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(__lzo_cte) +# if (LZO_CC_MSC || LZO_CC_WATCOMC) +# define __lzo_cte(e) ((void)0,(e)) +# elif 1 +# define __lzo_cte(e) ((void)0,(e)) +# endif +#endif +#if !defined(__lzo_cte) +# define __lzo_cte(e) (e) +#endif +#if !defined(LZO_BLOCK_BEGIN) +# define LZO_BLOCK_BEGIN do { +# define LZO_BLOCK_END } while __lzo_cte(0) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int lzo_unused__[1-2*!(sizeof(var)>0)]; (void)lzo_unused__;} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int lzo_unused__[1-2*!(sizeof((int)func)>0)]; (void)lzo_unused__;} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_CLANG >= 0x020800ul) +# define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) +# elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_GHS) +# define __lzo_inline __inline__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_inline __inline__ +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_inline __inline__ +#endif +#endif +#if defined(__lzo_inline) +# ifndef __lzo_HAVE_inline +# define __lzo_HAVE_inline 1 +# endif +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# ifndef __lzo_HAVE_forceinline +# define __lzo_HAVE_forceinline 1 +# endif +#else +# define __lzo_forceinline __lzo_inline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# ifndef __lzo_HAVE_noinline +# define __lzo_HAVE_noinline 1 +# endif +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_static_inline) +#if (LZO_CC_IBMC) +# define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline +#endif +#endif +#if !defined(__lzo_static_inline) +# define __lzo_static_inline static __lzo_inline +#endif +#if !defined(__lzo_static_forceinline) +#if (LZO_CC_IBMC) +# define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline +#endif +#endif +#if !defined(__lzo_static_forceinline) +# define __lzo_static_forceinline static __lzo_forceinline +#endif +#if !defined(__lzo_static_noinline) +#if (LZO_CC_IBMC) +# define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline +#endif +#endif +#if !defined(__lzo_static_noinline) +# define __lzo_static_noinline static __lzo_noinline +#endif +#if !defined(__lzo_c99_extern_inline) +#if defined(__GNUC_GNU_INLINE__) +# define __lzo_c99_extern_inline __lzo_inline +#elif defined(__GNUC_STDC_INLINE__) +# define __lzo_c99_extern_inline extern __lzo_inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_c99_extern_inline extern __lzo_inline +#endif +#if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) +# define __lzo_c99_extern_inline __lzo_inline +#endif +#endif +#if defined(__lzo_c99_extern_inline) +# ifndef __lzo_HAVE_c99_extern_inline +# define __lzo_HAVE_c99_extern_inline 1 +# endif +#else +# define __lzo_c99_extern_inline /*empty*/ +#endif +#if !defined(__lzo_may_alias) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_CLANG >= 0x020900ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#endif +#endif +#if defined(__lzo_may_alias) +# ifndef __lzo_HAVE_may_alias +# define __lzo_HAVE_may_alias 1 +# endif +#else +# define __lzo_may_alias /*empty*/ +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#endif +#endif +#if defined(__lzo_noreturn) +# ifndef __lzo_HAVE_noreturn +# define __lzo_HAVE_noreturn 1 +# endif +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# ifndef __lzo_HAVE_nothrow +# define __lzo_HAVE_nothrow 1 +# endif +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 1210) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_restrict __restrict__ +#endif +#endif +#if defined(__lzo_restrict) +# ifndef __lzo_HAVE_restrict +# define __lzo_HAVE_restrict 1 +# endif +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_GHS) && !defined(__cplusplus) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_IBMC >= 600) +# define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# ifndef __lzo_HAVE_alignof +# define __lzo_HAVE_alignof 1 +# endif +#endif +#if !defined(__lzo_struct_packed) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { +# define __lzo_struct_packed_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_struct_packed(s) _Packed struct s { +# define __lzo_struct_packed_end() }; +#endif +#endif +#if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) +# define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) +#endif +#if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) +# define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() +#endif +#if !defined(__lzo_byte_struct) +#if defined(__lzo_struct_packed) +# define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() +# define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); +# define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); +#endif +#endif +#if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) +# define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) +#endif +#if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) +#if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) +#elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_CILLY || LZO_CC_PCC) +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_align16(s) struct __declspec(align(16)) s { +# define __lzo_struct_align16_end() }; +# define __lzo_struct_align32(s) struct __declspec(align(32)) s { +# define __lzo_struct_align32_end() }; +# define __lzo_struct_align64(s) struct __declspec(align(64)) s { +# define __lzo_struct_align64_end() }; +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_struct_align16(s) struct s { +# define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); +# define __lzo_struct_align32(s) struct s { +# define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); +# define __lzo_struct_align64(s) struct s { +# define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); +#endif +#endif +#if !defined(__lzo_union_um) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_union_am(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_union_um(s) __pragma(pack(push,1)) union s { +# define __lzo_union_um_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_union_um(s) _Packed union s { +# define __lzo_union_um_end() }; +#endif +#endif +#if !defined(__lzo_union_am) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() }; +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# ifndef __lzo_HAVE_constructor +# define __lzo_HAVE_constructor 1 +# endif +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# ifndef __lzo_HAVE_destructor +# define __lzo_HAVE_destructor 1 +# endif +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_IBMC >= 1010) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# ifndef __lzo_HAVE_likely +# define __lzo_HAVE_likely 1 +# endif +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_very_likely) +# ifndef __lzo_HAVE_very_likely +# define __lzo_HAVE_very_likely 1 +# endif +#else +# define __lzo_very_likely(e) __lzo_likely(e) +#endif +#if defined(__lzo_unlikely) +# ifndef __lzo_HAVE_unlikely +# define __lzo_HAVE_unlikely 1 +# endif +#else +# define __lzo_unlikely(e) (e) +#endif +#if defined(__lzo_very_unlikely) +# ifndef __lzo_HAVE_very_unlikely +# define __lzo_HAVE_very_unlikely 1 +# endif +#else +# define __lzo_very_unlikely(e) __lzo_unlikely(e) +#endif +#if !defined(__lzo_loop_forever) +# if (LZO_CC_IBMC) +# define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END +# else +# define __lzo_loop_forever() do { ; } while __lzo_cte(1) +# endif +#endif +#if !defined(__lzo_unreachable) +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) && lzo_has_builtin(__builtin_unreachable) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_GNUC >= 0x040500ul) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 +# define __lzo_unreachable() __builtin_unreachable(); +#endif +#endif +#if defined(__lzo_unreachable) +# ifndef __lzo_HAVE_unreachable +# define __lzo_HAVE_unreachable 1 +# endif +#else +# if 0 +# define __lzo_unreachable() ((void)0); +# else +# define __lzo_unreachable() __lzo_loop_forever(); +# endif +#endif +#if !defined(lzo_unused_funcs_impl) +# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define lzo_unused_funcs_impl(r,f) static r __attribute__((__unused__)) f +# elif 1 && (LZO_CC_BORLANDC || LZO_CC_GNUC) +# define lzo_unused_funcs_impl(r,f) static r f +# else +# define lzo_unused_funcs_impl(r,f) __lzo_static_forceinline r f +# endif +#endif +#ifndef __LZO_CTA_NAME +#if (LZO_CFG_USE_COUNTER) +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) +#else +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) +#endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030000ul)) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} +# elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} +# elif (LZO_CC_GNUC >= 0x040700ul) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) +#if defined(__cplusplus) +extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if !defined(LZO_HAVE_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif ((LZO_OS_WIN32 && defined(__PW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul))) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#endif +#ifndef LZO_SIZEOF_SHORT +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#elif defined(__SIZEOF_SHORT__) +# define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) +#endif +#endif +#ifndef LZO_SIZEOF_INT +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#elif defined(__SIZEOF_INT__) +# define LZO_SIZEOF_INT (__SIZEOF_INT__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#elif defined(__SIZEOF_LONG__) +# define LZO_SIZEOF_LONG (__SIZEOF_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG_LONG +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#elif defined(__SIZEOF_LONG_LONG__) +# define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF___INT16 +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#endif +#ifndef LZO_SIZEOF___INT32 +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#endif +#ifndef LZO_SIZEOF___INT64 +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#endif +#ifndef LZO_SIZEOF_VOID_P +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#elif defined(__SIZEOF_POINTER__) +# define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) +#endif +#endif +#ifndef LZO_SIZEOF_SIZE_T +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#elif defined(__SIZEOF_SIZE_T__) +# define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) +#endif +#endif +#ifndef LZO_SIZEOF_PTRDIFF_T +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#elif defined(__SIZEOF_PTRDIFF_T__) +# define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) +#endif +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,39) == 1) +# define LZO_SIZEOF_LONG 5 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && (LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if (LZO_CFG_NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(_NO_LONGLONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_WORDSIZE) +#if (LZO_ARCH_ALPHA) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AMD64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AVR) +# define LZO_WORDSIZE 1 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define LZO_WORDSIZE 4 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_WORDSIZE 4 +# else +# define LZO_WORDSIZE 2 +# endif +#elif (LZO_ARCH_I086) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_IA64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_M16C) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_SPU) +# define LZO_WORDSIZE 4 +#elif (LZO_ARCH_Z80) +# define LZO_WORDSIZE 1 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_WORDSIZE 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define LZO_WORDSIZE 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_WORDSIZE 8 +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LP64__) || defined(__LP64) || defined(_LP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_ARCH_AVR) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#elif (LZO_ARCH_M16C) +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_ARCH_SPU) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_ARCH_Z80) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# if defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# else +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# endif +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) +#endif +#if !defined(LZO_WORDSIZE) +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) +# if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +# elif defined(__BIG_ENDIAN) +# define LZO_ABI_BIG_ENDIAN 1 +# else +# define LZO_ABI_LITTLE_ENDIAN 1 +# endif +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif (LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif (LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_LP32 1 +# define LZO_INFO_ABI_PM "lp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if 0 +#elif !defined(__LZO_LIBC_OVERRIDE) +#if (LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif (LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif (LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif (LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif (LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uc" "libc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_CC_GNUC) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) +# define __LZO_ASM_CLOBBER "memory" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_CC : "cc" +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_ARM) +# if defined(__ARM_FEATURE_UNALIGNED) +# if ((__ARM_FEATURE_UNALIGNED)+0) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +# elif 1 && (LZO_ARCH_ARM_THUMB2) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 6) && (defined(__TARGET_PROFILE_A) || defined(__TARGET_PROFILE_R)) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_CRIS) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_I386) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if (LZO_ABI_BIG_ENDIAN) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +# endif +#elif (LZO_ARCH_S390) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#ifndef LZO_CFG_NO_INLINE_ASM +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_INLINE_ASM 1 +#elif (LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#if (LZO_CFG_NO_INLINE_ASM) +# undef LZO_ASM_SYNTAX_MSC +# undef LZO_ASM_SYNTAX_GNUC +# undef __LZO_ASM_CLOBBER +# undef __LZO_ASM_CLOBBER_LIST_CC +# undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY +# undef __LZO_ASM_CLOBBER_LIST_EMPTY +#endif +#ifndef LZO_CFG_NO_UNALIGNED +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER +#if !(LZO_CFG_SKIP_LZO_TYPES) +#if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) +# error "missing defines for sizes" +#endif +#if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) +# error "missing defines for sizes" +#endif +#define LZO_TYPEOF_CHAR 1u +#define LZO_TYPEOF_SHORT 2u +#define LZO_TYPEOF_INT 3u +#define LZO_TYPEOF_LONG 4u +#define LZO_TYPEOF_LONG_LONG 5u +#define LZO_TYPEOF___INT8 17u +#define LZO_TYPEOF___INT16 18u +#define LZO_TYPEOF___INT32 19u +#define LZO_TYPEOF___INT64 20u +#define LZO_TYPEOF___INT128 21u +#define LZO_TYPEOF___INT256 22u +#define LZO_TYPEOF___MODE_QI 33u +#define LZO_TYPEOF___MODE_HI 34u +#define LZO_TYPEOF___MODE_SI 35u +#define LZO_TYPEOF___MODE_DI 36u +#define LZO_TYPEOF___MODE_TI 37u +#define LZO_TYPEOF_CHAR_P 129u +#if !defined(lzo_llong_t) +#if (LZO_SIZEOF_LONG_LONG+0 > 0) +__lzo_gnuc_extension__ typedef long long lzo_llong_t__; +__lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; +# define lzo_llong_t lzo_llong_t__ +# define lzo_ullong_t lzo_ullong_t__ +#endif +#endif +#if !defined(lzo_int16e_t) +#if (LZO_SIZEOF_LONG == 2) +# define lzo_int16e_t long +# define lzo_uint16e_t unsigned long +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_INT == 2) +# define lzo_int16e_t int +# define lzo_uint16e_t unsigned int +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == 2) +# define lzo_int16e_t short int +# define lzo_uint16e_t unsigned short int +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_SHORT +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) + typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); + typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); +# define lzo_int16e_t lzo_int16e_hi_t__ +# define lzo_uint16e_t lzo_uint16e_hi_t__ +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___MODE_HI +#elif (LZO_SIZEOF___INT16 == 2) +# define lzo_int16e_t __int16 +# define lzo_uint16e_t unsigned __int16 +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___INT16 +#else +#endif +#endif +#if defined(lzo_int16e_t) +# define LZO_SIZEOF_LZO_INT16E_T 2 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) +#endif +#if !defined(lzo_int32e_t) +#if (LZO_SIZEOF_LONG == 4) +# define lzo_int32e_t long int +# define lzo_uint32e_t unsigned long int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_INT == 4) +# define lzo_int32e_t int +# define lzo_uint32e_t unsigned int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == 4) +# define lzo_int32e_t short int +# define lzo_uint32e_t unsigned short int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_SHORT +#elif (LZO_SIZEOF_LONG_LONG == 4) +# define lzo_int32e_t lzo_llong_t +# define lzo_uint32e_t lzo_ullong_t +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG_LONG +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI +#elif (LZO_SIZEOF___INT32 == 4) +# define lzo_int32e_t __int32 +# define lzo_uint32e_t unsigned __int32 +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___INT32 +#else +#endif +#endif +#if defined(lzo_int32e_t) +# define LZO_SIZEOF_LZO_INT32E_T 4 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) +#endif +#if !defined(lzo_int64e_t) +#if (LZO_SIZEOF___INT64 == 8) +# if (LZO_CC_BORLANDC) && !(LZO_CFG_TYPE_PREFER___INT64) +# define LZO_CFG_TYPE_PREFER___INT64 1 +# endif +#endif +#if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int64e_t int +# define lzo_uint64e_t unsigned int +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_LONG == 8) +# define lzo_int64e_t long int +# define lzo_uint64e_t unsigned long int +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_TYPE_PREFER___INT64) +# define lzo_int64e_t lzo_llong_t +# define lzo_uint64e_t lzo_ullong_t +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG_LONG +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0ll) +# define LZO_UINT64_C(c) ((c) + 0ull) +# elif 0 +# define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) +# define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) +# else +# define LZO_INT64_C(c) (c##LL) +# define LZO_UINT64_C(c) (c##ULL) +# endif +#elif (LZO_SIZEOF___INT64 == 8) +# define lzo_int64e_t __int64 +# define lzo_uint64e_t unsigned __int64 +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF___INT64 +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0i64) +# define LZO_UINT64_C(c) ((c) + 0ui64) +# else +# define LZO_INT64_C(c) (c##i64) +# define LZO_UINT64_C(c) (c##ui64) +# endif +#else +#endif +#endif +#if defined(lzo_int64e_t) +# define LZO_SIZEOF_LZO_INT64E_T 8 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) +#endif +#if !defined(lzo_int32l_t) +#if defined(lzo_int32e_t) +# define lzo_int32l_t lzo_int32e_t +# define lzo_uint32l_t lzo_uint32e_t +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T +# define LZO_TYPEOF_LZO_INT32L_T LZO_TYPEOF_LZO_INT32E_T +#elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int32l_t int +# define lzo_uint32l_t unsigned int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= 4) +# define lzo_int32l_t long int +# define lzo_uint32l_t unsigned long int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_LONG +#else +# error "lzo_int32l_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) +#endif +#if !defined(lzo_int64l_t) +#if defined(lzo_int64e_t) +# define lzo_int64l_t lzo_int64e_t +# define lzo_uint64l_t lzo_uint64e_t +# define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T +# define LZO_TYPEOF_LZO_INT64L_T LZO_TYPEOF_LZO_INT64E_T +#else +#endif +#endif +#if defined(lzo_int64l_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) +#endif +#if !defined(lzo_int32f_t) +#if (LZO_SIZEOF_SIZE_T >= 8) +# define lzo_int32f_t lzo_int64l_t +# define lzo_uint32f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT64L_T +#else +# define lzo_int32f_t lzo_int32l_t +# define lzo_uint32f_t lzo_uint32l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T +# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT32L_T +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) +#endif +#if !defined(lzo_int64f_t) +#if defined(lzo_int64l_t) +# define lzo_int64f_t lzo_int64l_t +# define lzo_uint64f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INT64F_T LZO_TYPEOF_LZO_INT64L_T +#else +#endif +#endif +#if defined(lzo_int64f_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) +#endif +#if !defined(lzo_intptr_t) +#if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) +# define __LZO_INTPTR_T_IS_POINTER 1 + typedef char * lzo_intptr_t; + typedef char * lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_CHAR_P +#elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) + typedef __w64 int lzo_intptr_t; + typedef __w64 unsigned int lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) +# define lzo_intptr_t short +# define lzo_uintptr_t unsigned short +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_SHORT +#elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_intptr_t int +# define lzo_uintptr_t unsigned int +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t long +# define lzo_uintptr_t unsigned long +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t lzo_int64l_t +# define lzo_uintptr_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LZO_INT64L_T +#else +# error "lzo_intptr_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) +#endif +#if !defined(lzo_word_t) +#if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) +#if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) +# define lzo_word_t lzo_uintptr_t +# define lzo_sword_t lzo_intptr_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LZO_INTPTR_T +#elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) +# define lzo_word_t unsigned long +# define lzo_sword_t long +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LONG +#elif (LZO_WORDSIZE == LZO_SIZEOF_INT) +# define lzo_word_t unsigned int +# define lzo_sword_t int +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_INT +#elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) +# define lzo_word_t unsigned short +# define lzo_sword_t short +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_SHORT +#elif (LZO_WORDSIZE == 1) +# define lzo_word_t unsigned char +# define lzo_sword_t signed char +# define LZO_SIZEOF_LZO_WORD_T 1 +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_CHAR +#elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) +# define lzo_word_t lzo_uint64l_t +# define lzo_sword_t lzo_int64l_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +#elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) +#if 0 + typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); + typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); +# define lzo_word_t lzo_word_t +# define lzo_sword_t lzo_sword_t +# define LZO_SIZEOF_LZO_WORD_T 16 +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF___MODE_V16QI +#endif +#else +# error "lzo_word_t" +#endif +#endif +#endif +#if 1 && defined(lzo_word_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) +#endif +#if 1 +#define lzo_int8_t signed char +#define lzo_uint8_t unsigned char +#define LZO_SIZEOF_LZO_INT8_T 1 +#define LZO_TYPEOF_LZO_INT8_T LZO_TYPEOF_CHAR +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) +#endif +#if defined(lzo_int16e_t) +#define lzo_int16_t lzo_int16e_t +#define lzo_uint16_t lzo_uint16e_t +#define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T +#define LZO_TYPEOF_LZO_INT16_T LZO_TYPEOF_LZO_INT16E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) +#endif +#if defined(lzo_int32e_t) +#define lzo_int32_t lzo_int32e_t +#define lzo_uint32_t lzo_uint32e_t +#define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T +#define LZO_TYPEOF_LZO_INT32_T LZO_TYPEOF_LZO_INT32E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) +#endif +#if defined(lzo_int64e_t) +#define lzo_int64_t lzo_int64e_t +#define lzo_uint64_t lzo_uint64e_t +#define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T +#define LZO_TYPEOF_LZO_INT64_T LZO_TYPEOF_LZO_INT64E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) +#endif +#if 1 +#define lzo_int_least32_t lzo_int32l_t +#define lzo_uint_least32_t lzo_uint32l_t +#define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T +#define LZO_TYPEOF_LZO_INT_LEAST32_T LZO_TYPEOF_LZO_INT32L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) +#endif +#if defined(lzo_int64l_t) +#define lzo_int_least64_t lzo_int64l_t +#define lzo_uint_least64_t lzo_uint64l_t +#define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T +#define LZO_TYPEOF_LZO_INT_LEAST64_T LZO_TYPEOF_LZO_INT64L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) +#endif +#if 1 +#define lzo_int_fast32_t lzo_int32f_t +#define lzo_uint_fast32_t lzo_uint32f_t +#define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T +#define LZO_TYPEOF_LZO_INT_FAST32_T LZO_TYPEOF_LZO_INT32F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) +#endif +#if defined(lzo_int64f_t) +#define lzo_int_fast64_t lzo_int64f_t +#define lzo_uint_fast64_t lzo_uint64f_t +#define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T +#define LZO_TYPEOF_LZO_INT_FAST64_T LZO_TYPEOF_LZO_INT64F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) +#endif +#if !defined(LZO_INT16_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) ((c) + 0) +# define LZO_UINT16_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) ((c) + 0L) +# define LZO_UINT16_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) (c) +# define LZO_UINT16_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) (c##L) +# define LZO_UINT16_C(c) (c##UL) +# else +# error "LZO_INT16_C" +# endif +#endif +#if !defined(LZO_INT32_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) ((c) + 0) +# define LZO_UINT32_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) ((c) + 0L) +# define LZO_UINT32_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) (c) +# define LZO_UINT32_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) (c##L) +# define LZO_UINT32_C(c) (c##UL) +# elif (LZO_SIZEOF_LONG_LONG >= 4) +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# else +# error "LZO_INT32_C" +# endif +#endif +#if !defined(LZO_INT64_C) && defined(lzo_int64l_t) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) ((c) + 0) +# define LZO_UINT64_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) ((c) + 0L) +# define LZO_UINT64_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) (c) +# define LZO_UINT64_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) (c##L) +# define LZO_UINT64_C(c) (c##UL) +# else +# error "LZO_INT64_C" +# endif +#endif +#endif + +#endif /* already included */ + +/* vim:set ts=4 sw=4 et: */ diff --git a/extensions/common/membuf.hpp b/extensions/common/membuf.hpp new file mode 100644 index 0000000000..ab7507cc10 --- /dev/null +++ b/extensions/common/membuf.hpp @@ -0,0 +1,56 @@ +#pragma once + +#include <streambuf> + +namespace ace { + class membuf : public std::streambuf + { + public: + membuf(char* mem, size_t length) { + + setg(mem, mem, mem + length); + setp(mem, mem + length); + } + + int_type underflow() { + if (gptr() >= egptr()) { + return traits_type::eof(); + } + return traits_type::to_int_type(*gptr()); + } + + std::streampos seekpos(std::streampos pos, std::ios_base::openmode) { + char *p = eback() + pos; + if (p >= eback() && p <= egptr()) { + setg(eback(), p, egptr()); + return pos; + } else { + return -1; + } + } + + std::streampos seekoff(std::streamoff off, std::ios_base::seekdir dir, std::ios_base::openmode) { + char *p; + switch (dir) { + case std::ios_base::beg: + p = eback() + off; + break; + case std::ios_base::cur: + p = gptr() + off; + break; + case std::ios_base::end: + p = egptr() - off; + break; + default: + p = 0; + break; + } + if (p >= eback() && p <= egptr()) { + setg(eback(), p, egptr()); + return std::streampos(p - eback()); + } else { + return -1; + } + } + }; +} \ No newline at end of file diff --git a/extensions/common/minilzo.c b/extensions/common/minilzo.c new file mode 100644 index 0000000000..801f53001d --- /dev/null +++ b/extensions/common/minilzo.c @@ -0,0 +1,6231 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2015 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + <markus@oberhumer.com> + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO 1 + +#if defined(LZO_CFG_FREESTANDING) +# undef MINILZO_HAVE_CONFIG_H +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# include <config.h> +#endif +#include <limits.h> +#include <stddef.h> +#if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS) + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if !defined(LZO_CFG_NO_DISABLE_WUNDEF) +#if defined(__ARMCC_VERSION) +# pragma diag_suppress 193 +#elif defined(__clang__) && defined(__clang_minor__) +# pragma clang diagnostic ignored "-Wundef" +#elif defined(__INTEL_COMPILER) +# pragma warning(disable: 193) +#elif defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) +# if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) +# pragma GCC diagnostic ignored "-Wundef" +# endif +#elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if ((_MSC_VER-0) >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#endif +#if 0 && defined(__POCC__) && defined(_WIN32) +# if (__POCC__ >= 400) +# pragma warn(disable: 2216) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#ifndef _CRT_NONSTDC_NO_WARNINGS +#define _CRT_NONSTDC_NO_WARNINGS 1 +#endif +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif +#endif +#if 0 +#define LZO_0xffffUL 0xfffful +#define LZO_0xffffffffUL 0xfffffffful +#else +#define LZO_0xffffUL 65535ul +#define LZO_0xffffffffUL 4294967295ul +#endif +#define LZO_0xffffL LZO_0xffffUL +#define LZO_0xffffffffL LZO_0xffffffffUL +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if defined(__COUNTER__) +# ifndef LZO_CFG_USE_COUNTER +# define LZO_CFG_USE_COUNTER 1 +# endif +#else +# undef LZO_CFG_USE_COUNTER +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if defined(_MSC_VER) && defined(M_I86HM) && (UINT_MAX == LZO_0xffffL) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED 1 +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT0() /*empty*/ +#define LZO_PP_CONCAT1(a) a +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() +#define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) +#define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) +#define LZO_PP_EMPTY /*empty*/ +#define LZO_PP_EMPTY0() /*empty*/ +#define LZO_PP_EMPTY1(a) /*empty*/ +#define LZO_PP_EMPTY2(a,b) /*empty*/ +#define LZO_PP_EMPTY3(a,b,c) /*empty*/ +#define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ +#define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ +#define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ +#define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) +#define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-!!(b))) - (o)) << 1) + (o)*!!(b)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +# define LZO_EXTERN_C_BEGIN extern "C" { +# define LZO_EXTERN_C_END } +#else +# define LZO_EXTERN_C extern +# define LZO_EXTERN_C_BEGIN /*empty*/ +# define LZO_EXTERN_C_END /*empty*/ +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if (LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif (LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__arm__) && !defined(__i386__) && !defined(__ppc__) && !defined(__x64_64__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif defined(__mips__) && defined(__psp__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) && defined(__MACH__) +# if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) +# define LZO_OS_POSIX_DARWIN 1040 +# define LZO_INFO_OS_POSIX "darwin_iphone" +# elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) +# define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +# define LZO_INFO_OS_POSIX "darwin" +# else +# define LZO_OS_POSIX_DARWIN 1 +# define LZO_INFO_OS_POSIX "darwin" +# endif +# define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) +# define LZO_CC_INTELC __INTEL_COMPILER +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_INTELC_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) +# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) +# else +# define LZO_CC_CLANG 0x010000L +# endif +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_CLANG_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +# define LZO_INFO_CC "clang" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_LLVM LZO_CC_LLVM_GNUC +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__ARMCC_VERSION) && !defined(__GNUC__) +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__CODEGEARC__) +# define LZO_CC_CODEGEARC 1 +# define LZO_INFO_CC "CodeGear C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) +# define LZO_CC_GHS 1 +# define LZO_INFO_CC "Green Hills C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_GHS_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) +# define LZO_CC_HPACC __HP_aCC +# define LZO_INFO_CC "HP aCC" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) && ((__IBMC__-0) > 0) +# define LZO_CC_IBMC __IBMC__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) +# define LZO_CC_IBMC __IBMCPP__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) +# define LZO_CC_MWERKS __MWERKS__ +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) +# else +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" +# endif +# define LZO_INFO_CC "Portland Group PGI C" +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if ((__ZTC__-0) == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_MSC _MSC_VER +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if (LZO_CC_GNUC) && defined(__OPEN64__) +# if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) +# define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) +# define LZO_CC_OPEN64_GNUC LZO_CC_GNUC +# endif +#endif +#if (LZO_CC_GNUC) && defined(__PCC__) +# if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) +# define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) +# define LZO_CC_PCC_GNUC LZO_CC_GNUC +# endif +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if (LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__aarch64__) +# define LZO_ARCH_ARM64 1 +# define LZO_INFO_ARCH "arm64" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__avr32__) || defined(__AVR32__) +# define LZO_ARCH_AVR32 1 +# define LZO_INFO_ARCH "avr32" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if !defined(LZO_ARCH_ARM_THUMB2) +#if (LZO_ARCH_ARM) +# if defined(__ARM_ARCH_ISA_THUMB) +# if ((__ARM_ARCH_ISA_THUMB)+0 >= 2) +# define LZO_ARCH_ARM_THUMB2 1 +# endif +# elif 1 && defined(__thumb2__) +# define LZO_ARCH_ARM_THUMB2 1 +# elif 1 && defined(__TARGET_ARCH_THUMB) && ((__TARGET_ARCH_THUMB)+0 >= 4) +# define LZO_ARCH_ARM_THUMB2 1 +# endif +#endif +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) +# define LZO_ARCH_X64 1 +#elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_AMD64 1 +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) +# define LZO_ARCH_AARCH64 1 +#elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_ARM64 1 +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) +# define LZO_ARCH_X86 1 +#elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_I386 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086PM && !LZO_ARCH_I086) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# if !defined(LZO_TARGET_FEATURE_SSE2) +# if defined(__SSE2__) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif defined(_MSC_VER) && (defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif (LZO_CC_INTELC_MSC || LZO_CC_MSC) && defined(_M_AMD64) +# define LZO_TARGET_FEATURE_SSE2 1 +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSSE3) +# if (LZO_TARGET_FEATURE_SSE2) +# if defined(__SSSE3__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# elif defined(_MSC_VER) && defined(__AVX__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSE4_2) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__SSE4_2__) +# define LZO_TARGET_FEATURE_SSE4_2 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__AVX__) +# define LZO_TARGET_FEATURE_AVX 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX2) +# if (LZO_TARGET_FEATURE_AVX) +# if defined(__AVX2__) +# define LZO_TARGET_FEATURE_AVX2 1 +# endif +# endif +# endif +#endif +#if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if defined(__ARM_NEON) && ((__ARM_NEON)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# elif 1 && defined(__ARM_NEON__) && ((__ARM_NEON__)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# elif 1 && defined(__TARGET_FEATURE_NEON) && ((__TARGET_FEATURE_NEON)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if 1 +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#endif +#if 0 +#elif !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown LZO_ARCH_I086 memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "unexpected configuration - check your compiler defines" +# elif (LZO_CC_ZORTECHC) +# else +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#ifdef __cplusplus +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#ifdef __cplusplus +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_gnuc_extension__ __extension__ +#else +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#if !defined(lzo_has_builtin) +#if (LZO_CC_CLANG) && defined(__has_builtin) +# define lzo_has_builtin __has_builtin +#endif +#endif +#if !defined(lzo_has_builtin) +# define lzo_has_builtin(x) 0 +#endif +#if !defined(lzo_has_attribute) +#if (LZO_CC_CLANG) && defined(__has_attribute) +# define lzo_has_attribute __has_attribute +#endif +#endif +#if !defined(lzo_has_attribute) +# define lzo_has_attribute(x) 0 +#endif +#if !defined(lzo_has_declspec_attribute) +#if (LZO_CC_CLANG) && defined(__has_declspec_attribute) +# define lzo_has_declspec_attribute __has_declspec_attribute +#endif +#endif +#if !defined(lzo_has_declspec_attribute) +# define lzo_has_declspec_attribute(x) 0 +#endif +#if !defined(lzo_has_feature) +#if (LZO_CC_CLANG) && defined(__has_feature) +# define lzo_has_feature __has_feature +#endif +#endif +#if !defined(lzo_has_feature) +# define lzo_has_feature(x) 0 +#endif +#if !defined(lzo_has_extension) +#if (LZO_CC_CLANG) && defined(__has_extension) +# define lzo_has_extension __has_extension +#elif (LZO_CC_CLANG) && defined(__has_feature) +# define lzo_has_extension __has_feature +#endif +#endif +#if !defined(lzo_has_extension) +# define lzo_has_extension 0 +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# else +# define LZO_CFG_USE_NEW_STYLE_CASTS 1 +# endif +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(__cplusplus) +# if defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# undef LZO_CFG_USE_NEW_STYLE_CASTS +# endif +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(LZO_REINTERPRET_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast<t> (e)) +# endif +#endif +#if !defined(LZO_REINTERPRET_CAST) +# define LZO_REINTERPRET_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_STATIC_CAST(t,e) (static_cast<t> (e)) +# endif +#endif +#if !defined(LZO_STATIC_CAST) +# define LZO_STATIC_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST2) +# define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) +#endif +#if !defined(LZO_UNCONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast<t> (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_PCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_PCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_PCAST) +# define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) +#endif +#if !defined(LZO_CCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_CCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_CCAST) +# define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) +#endif +#if !defined(LZO_ICONV) +# define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ICAST) +# define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ITRUNC) +# define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(__lzo_cte) +# if (LZO_CC_MSC || LZO_CC_WATCOMC) +# define __lzo_cte(e) ((void)0,(e)) +# elif 1 +# define __lzo_cte(e) ((void)0,(e)) +# endif +#endif +#if !defined(__lzo_cte) +# define __lzo_cte(e) (e) +#endif +#if !defined(LZO_BLOCK_BEGIN) +# define LZO_BLOCK_BEGIN do { +# define LZO_BLOCK_END } while __lzo_cte(0) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int lzo_unused__[1-2*!(sizeof(var)>0)]; (void)lzo_unused__;} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int lzo_unused__[1-2*!(sizeof((int)func)>0)]; (void)lzo_unused__;} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_CLANG >= 0x020800ul) +# define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) +# elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_GHS) +# define __lzo_inline __inline__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_inline __inline__ +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_inline __inline__ +#endif +#endif +#if defined(__lzo_inline) +# ifndef __lzo_HAVE_inline +# define __lzo_HAVE_inline 1 +# endif +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# ifndef __lzo_HAVE_forceinline +# define __lzo_HAVE_forceinline 1 +# endif +#else +# define __lzo_forceinline __lzo_inline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# ifndef __lzo_HAVE_noinline +# define __lzo_HAVE_noinline 1 +# endif +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_static_inline) +#if (LZO_CC_IBMC) +# define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline +#endif +#endif +#if !defined(__lzo_static_inline) +# define __lzo_static_inline static __lzo_inline +#endif +#if !defined(__lzo_static_forceinline) +#if (LZO_CC_IBMC) +# define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline +#endif +#endif +#if !defined(__lzo_static_forceinline) +# define __lzo_static_forceinline static __lzo_forceinline +#endif +#if !defined(__lzo_static_noinline) +#if (LZO_CC_IBMC) +# define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline +#endif +#endif +#if !defined(__lzo_static_noinline) +# define __lzo_static_noinline static __lzo_noinline +#endif +#if !defined(__lzo_c99_extern_inline) +#if defined(__GNUC_GNU_INLINE__) +# define __lzo_c99_extern_inline __lzo_inline +#elif defined(__GNUC_STDC_INLINE__) +# define __lzo_c99_extern_inline extern __lzo_inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_c99_extern_inline extern __lzo_inline +#endif +#if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) +# define __lzo_c99_extern_inline __lzo_inline +#endif +#endif +#if defined(__lzo_c99_extern_inline) +# ifndef __lzo_HAVE_c99_extern_inline +# define __lzo_HAVE_c99_extern_inline 1 +# endif +#else +# define __lzo_c99_extern_inline /*empty*/ +#endif +#if !defined(__lzo_may_alias) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_CLANG >= 0x020900ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#endif +#endif +#if defined(__lzo_may_alias) +# ifndef __lzo_HAVE_may_alias +# define __lzo_HAVE_may_alias 1 +# endif +#else +# define __lzo_may_alias /*empty*/ +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#endif +#endif +#if defined(__lzo_noreturn) +# ifndef __lzo_HAVE_noreturn +# define __lzo_HAVE_noreturn 1 +# endif +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# ifndef __lzo_HAVE_nothrow +# define __lzo_HAVE_nothrow 1 +# endif +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 1210) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_restrict __restrict__ +#endif +#endif +#if defined(__lzo_restrict) +# ifndef __lzo_HAVE_restrict +# define __lzo_HAVE_restrict 1 +# endif +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_GHS) && !defined(__cplusplus) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_IBMC >= 600) +# define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# ifndef __lzo_HAVE_alignof +# define __lzo_HAVE_alignof 1 +# endif +#endif +#if !defined(__lzo_struct_packed) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { +# define __lzo_struct_packed_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_struct_packed(s) _Packed struct s { +# define __lzo_struct_packed_end() }; +#endif +#endif +#if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) +# define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) +#endif +#if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) +# define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() +#endif +#if !defined(__lzo_byte_struct) +#if defined(__lzo_struct_packed) +# define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() +# define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); +# define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); +#endif +#endif +#if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) +# define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) +#endif +#if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) +#if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) +#elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_CILLY || LZO_CC_PCC) +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_align16(s) struct __declspec(align(16)) s { +# define __lzo_struct_align16_end() }; +# define __lzo_struct_align32(s) struct __declspec(align(32)) s { +# define __lzo_struct_align32_end() }; +# define __lzo_struct_align64(s) struct __declspec(align(64)) s { +# define __lzo_struct_align64_end() }; +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_struct_align16(s) struct s { +# define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); +# define __lzo_struct_align32(s) struct s { +# define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); +# define __lzo_struct_align64(s) struct s { +# define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); +#endif +#endif +#if !defined(__lzo_union_um) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_union_am(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_union_um(s) __pragma(pack(push,1)) union s { +# define __lzo_union_um_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_union_um(s) _Packed union s { +# define __lzo_union_um_end() }; +#endif +#endif +#if !defined(__lzo_union_am) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() }; +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# ifndef __lzo_HAVE_constructor +# define __lzo_HAVE_constructor 1 +# endif +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# ifndef __lzo_HAVE_destructor +# define __lzo_HAVE_destructor 1 +# endif +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_IBMC >= 1010) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# ifndef __lzo_HAVE_likely +# define __lzo_HAVE_likely 1 +# endif +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_very_likely) +# ifndef __lzo_HAVE_very_likely +# define __lzo_HAVE_very_likely 1 +# endif +#else +# define __lzo_very_likely(e) __lzo_likely(e) +#endif +#if defined(__lzo_unlikely) +# ifndef __lzo_HAVE_unlikely +# define __lzo_HAVE_unlikely 1 +# endif +#else +# define __lzo_unlikely(e) (e) +#endif +#if defined(__lzo_very_unlikely) +# ifndef __lzo_HAVE_very_unlikely +# define __lzo_HAVE_very_unlikely 1 +# endif +#else +# define __lzo_very_unlikely(e) __lzo_unlikely(e) +#endif +#if !defined(__lzo_loop_forever) +# if (LZO_CC_IBMC) +# define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END +# else +# define __lzo_loop_forever() do { ; } while __lzo_cte(1) +# endif +#endif +#if !defined(__lzo_unreachable) +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) && lzo_has_builtin(__builtin_unreachable) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_GNUC >= 0x040500ul) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 +# define __lzo_unreachable() __builtin_unreachable(); +#endif +#endif +#if defined(__lzo_unreachable) +# ifndef __lzo_HAVE_unreachable +# define __lzo_HAVE_unreachable 1 +# endif +#else +# if 0 +# define __lzo_unreachable() ((void)0); +# else +# define __lzo_unreachable() __lzo_loop_forever(); +# endif +#endif +#if !defined(lzo_unused_funcs_impl) +# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define lzo_unused_funcs_impl(r,f) static r __attribute__((__unused__)) f +# elif 1 && (LZO_CC_BORLANDC || LZO_CC_GNUC) +# define lzo_unused_funcs_impl(r,f) static r f +# else +# define lzo_unused_funcs_impl(r,f) __lzo_static_forceinline r f +# endif +#endif +#ifndef __LZO_CTA_NAME +#if (LZO_CFG_USE_COUNTER) +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) +#else +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) +#endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030000ul)) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} +# elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} +# elif (LZO_CC_GNUC >= 0x040700ul) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) +#if defined(__cplusplus) +extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if !defined(LZO_HAVE_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif ((LZO_OS_WIN32 && defined(__PW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul))) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#endif +#ifndef LZO_SIZEOF_SHORT +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#elif defined(__SIZEOF_SHORT__) +# define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) +#endif +#endif +#ifndef LZO_SIZEOF_INT +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#elif defined(__SIZEOF_INT__) +# define LZO_SIZEOF_INT (__SIZEOF_INT__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#elif defined(__SIZEOF_LONG__) +# define LZO_SIZEOF_LONG (__SIZEOF_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG_LONG +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#elif defined(__SIZEOF_LONG_LONG__) +# define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF___INT16 +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#endif +#ifndef LZO_SIZEOF___INT32 +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#endif +#ifndef LZO_SIZEOF___INT64 +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#endif +#ifndef LZO_SIZEOF_VOID_P +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#elif defined(__SIZEOF_POINTER__) +# define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) +#endif +#endif +#ifndef LZO_SIZEOF_SIZE_T +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#elif defined(__SIZEOF_SIZE_T__) +# define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) +#endif +#endif +#ifndef LZO_SIZEOF_PTRDIFF_T +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#elif defined(__SIZEOF_PTRDIFF_T__) +# define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) +#endif +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,39) == 1) +# define LZO_SIZEOF_LONG 5 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && (LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if (LZO_CFG_NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(_NO_LONGLONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_WORDSIZE) +#if (LZO_ARCH_ALPHA) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AMD64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AVR) +# define LZO_WORDSIZE 1 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define LZO_WORDSIZE 4 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_WORDSIZE 4 +# else +# define LZO_WORDSIZE 2 +# endif +#elif (LZO_ARCH_I086) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_IA64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_M16C) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_SPU) +# define LZO_WORDSIZE 4 +#elif (LZO_ARCH_Z80) +# define LZO_WORDSIZE 1 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_WORDSIZE 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define LZO_WORDSIZE 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_WORDSIZE 8 +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LP64__) || defined(__LP64) || defined(_LP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_ARCH_AVR) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__NORMAL_MODE__) +# define LZO_SIZEOF_VOID_P 2 +# elif defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#elif (LZO_ARCH_M16C) +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_ARCH_SPU) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_ARCH_Z80) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# if defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# else +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# endif +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) +#endif +#if !defined(LZO_WORDSIZE) +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) +# if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +# elif defined(__BIG_ENDIAN) +# define LZO_ABI_BIG_ENDIAN 1 +# else +# define LZO_ABI_LITTLE_ENDIAN 1 +# endif +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif (LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif (LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_LP32 1 +# define LZO_INFO_ABI_PM "lp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if 0 +#elif !defined(__LZO_LIBC_OVERRIDE) +#if (LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif (LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif (LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif (LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif (LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uc" "libc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_CC_GNUC) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) +# define __LZO_ASM_CLOBBER "memory" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_CC : "cc" +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_ARM) +# if defined(__ARM_FEATURE_UNALIGNED) +# if ((__ARM_FEATURE_UNALIGNED)+0) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +# elif 1 && (LZO_ARCH_ARM_THUMB2) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 6) && (defined(__TARGET_PROFILE_A) || defined(__TARGET_PROFILE_R)) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_CRIS) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_I386) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if (LZO_ABI_BIG_ENDIAN) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +# endif +#elif (LZO_ARCH_S390) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#ifndef LZO_CFG_NO_INLINE_ASM +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_INLINE_ASM 1 +#elif (LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#if (LZO_CFG_NO_INLINE_ASM) +# undef LZO_ASM_SYNTAX_MSC +# undef LZO_ASM_SYNTAX_GNUC +# undef __LZO_ASM_CLOBBER +# undef __LZO_ASM_CLOBBER_LIST_CC +# undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY +# undef __LZO_ASM_CLOBBER_LIST_EMPTY +#endif +#ifndef LZO_CFG_NO_UNALIGNED +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER +#if !(LZO_CFG_SKIP_LZO_TYPES) +#if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) +# error "missing defines for sizes" +#endif +#if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) +# error "missing defines for sizes" +#endif +#define LZO_TYPEOF_CHAR 1u +#define LZO_TYPEOF_SHORT 2u +#define LZO_TYPEOF_INT 3u +#define LZO_TYPEOF_LONG 4u +#define LZO_TYPEOF_LONG_LONG 5u +#define LZO_TYPEOF___INT8 17u +#define LZO_TYPEOF___INT16 18u +#define LZO_TYPEOF___INT32 19u +#define LZO_TYPEOF___INT64 20u +#define LZO_TYPEOF___INT128 21u +#define LZO_TYPEOF___INT256 22u +#define LZO_TYPEOF___MODE_QI 33u +#define LZO_TYPEOF___MODE_HI 34u +#define LZO_TYPEOF___MODE_SI 35u +#define LZO_TYPEOF___MODE_DI 36u +#define LZO_TYPEOF___MODE_TI 37u +#define LZO_TYPEOF_CHAR_P 129u +#if !defined(lzo_llong_t) +#if (LZO_SIZEOF_LONG_LONG+0 > 0) +__lzo_gnuc_extension__ typedef long long lzo_llong_t__; +__lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; +# define lzo_llong_t lzo_llong_t__ +# define lzo_ullong_t lzo_ullong_t__ +#endif +#endif +#if !defined(lzo_int16e_t) +#if (LZO_SIZEOF_LONG == 2) +# define lzo_int16e_t long +# define lzo_uint16e_t unsigned long +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_INT == 2) +# define lzo_int16e_t int +# define lzo_uint16e_t unsigned int +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == 2) +# define lzo_int16e_t short int +# define lzo_uint16e_t unsigned short int +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_SHORT +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) + typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); + typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); +# define lzo_int16e_t lzo_int16e_hi_t__ +# define lzo_uint16e_t lzo_uint16e_hi_t__ +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___MODE_HI +#elif (LZO_SIZEOF___INT16 == 2) +# define lzo_int16e_t __int16 +# define lzo_uint16e_t unsigned __int16 +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___INT16 +#else +#endif +#endif +#if defined(lzo_int16e_t) +# define LZO_SIZEOF_LZO_INT16E_T 2 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) +#endif +#if !defined(lzo_int32e_t) +#if (LZO_SIZEOF_LONG == 4) +# define lzo_int32e_t long int +# define lzo_uint32e_t unsigned long int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_INT == 4) +# define lzo_int32e_t int +# define lzo_uint32e_t unsigned int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == 4) +# define lzo_int32e_t short int +# define lzo_uint32e_t unsigned short int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_SHORT +#elif (LZO_SIZEOF_LONG_LONG == 4) +# define lzo_int32e_t lzo_llong_t +# define lzo_uint32e_t lzo_ullong_t +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG_LONG +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI +#elif (LZO_SIZEOF___INT32 == 4) +# define lzo_int32e_t __int32 +# define lzo_uint32e_t unsigned __int32 +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___INT32 +#else +#endif +#endif +#if defined(lzo_int32e_t) +# define LZO_SIZEOF_LZO_INT32E_T 4 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) +#endif +#if !defined(lzo_int64e_t) +#if (LZO_SIZEOF___INT64 == 8) +# if (LZO_CC_BORLANDC) && !(LZO_CFG_TYPE_PREFER___INT64) +# define LZO_CFG_TYPE_PREFER___INT64 1 +# endif +#endif +#if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int64e_t int +# define lzo_uint64e_t unsigned int +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_LONG == 8) +# define lzo_int64e_t long int +# define lzo_uint64e_t unsigned long int +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_TYPE_PREFER___INT64) +# define lzo_int64e_t lzo_llong_t +# define lzo_uint64e_t lzo_ullong_t +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG_LONG +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0ll) +# define LZO_UINT64_C(c) ((c) + 0ull) +# elif 0 +# define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) +# define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) +# else +# define LZO_INT64_C(c) (c##LL) +# define LZO_UINT64_C(c) (c##ULL) +# endif +#elif (LZO_SIZEOF___INT64 == 8) +# define lzo_int64e_t __int64 +# define lzo_uint64e_t unsigned __int64 +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF___INT64 +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0i64) +# define LZO_UINT64_C(c) ((c) + 0ui64) +# else +# define LZO_INT64_C(c) (c##i64) +# define LZO_UINT64_C(c) (c##ui64) +# endif +#else +#endif +#endif +#if defined(lzo_int64e_t) +# define LZO_SIZEOF_LZO_INT64E_T 8 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) +#endif +#if !defined(lzo_int32l_t) +#if defined(lzo_int32e_t) +# define lzo_int32l_t lzo_int32e_t +# define lzo_uint32l_t lzo_uint32e_t +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T +# define LZO_TYPEOF_LZO_INT32L_T LZO_TYPEOF_LZO_INT32E_T +#elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int32l_t int +# define lzo_uint32l_t unsigned int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= 4) +# define lzo_int32l_t long int +# define lzo_uint32l_t unsigned long int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_LONG +#else +# error "lzo_int32l_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) +#endif +#if !defined(lzo_int64l_t) +#if defined(lzo_int64e_t) +# define lzo_int64l_t lzo_int64e_t +# define lzo_uint64l_t lzo_uint64e_t +# define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T +# define LZO_TYPEOF_LZO_INT64L_T LZO_TYPEOF_LZO_INT64E_T +#else +#endif +#endif +#if defined(lzo_int64l_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) +#endif +#if !defined(lzo_int32f_t) +#if (LZO_SIZEOF_SIZE_T >= 8) +# define lzo_int32f_t lzo_int64l_t +# define lzo_uint32f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT64L_T +#else +# define lzo_int32f_t lzo_int32l_t +# define lzo_uint32f_t lzo_uint32l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T +# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT32L_T +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) +#endif +#if !defined(lzo_int64f_t) +#if defined(lzo_int64l_t) +# define lzo_int64f_t lzo_int64l_t +# define lzo_uint64f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INT64F_T LZO_TYPEOF_LZO_INT64L_T +#else +#endif +#endif +#if defined(lzo_int64f_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) +#endif +#if !defined(lzo_intptr_t) +#if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) +# define __LZO_INTPTR_T_IS_POINTER 1 + typedef char * lzo_intptr_t; + typedef char * lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_CHAR_P +#elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) + typedef __w64 int lzo_intptr_t; + typedef __w64 unsigned int lzo_uintptr_t; +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) +# define lzo_intptr_t short +# define lzo_uintptr_t unsigned short +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_SHORT +#elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_intptr_t int +# define lzo_uintptr_t unsigned int +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t long +# define lzo_uintptr_t unsigned long +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t lzo_int64l_t +# define lzo_uintptr_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LZO_INT64L_T +#else +# error "lzo_intptr_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) +#endif +#if !defined(lzo_word_t) +#if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) +#if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) +# define lzo_word_t lzo_uintptr_t +# define lzo_sword_t lzo_intptr_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LZO_INTPTR_T +#elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) +# define lzo_word_t unsigned long +# define lzo_sword_t long +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LONG +#elif (LZO_WORDSIZE == LZO_SIZEOF_INT) +# define lzo_word_t unsigned int +# define lzo_sword_t int +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_INT +#elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) +# define lzo_word_t unsigned short +# define lzo_sword_t short +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_SHORT +#elif (LZO_WORDSIZE == 1) +# define lzo_word_t unsigned char +# define lzo_sword_t signed char +# define LZO_SIZEOF_LZO_WORD_T 1 +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_CHAR +#elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) +# define lzo_word_t lzo_uint64l_t +# define lzo_sword_t lzo_int64l_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +#elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) +#if 0 + typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); + typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); +# define lzo_word_t lzo_word_t +# define lzo_sword_t lzo_sword_t +# define LZO_SIZEOF_LZO_WORD_T 16 +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF___MODE_V16QI +#endif +#else +# error "lzo_word_t" +#endif +#endif +#endif +#if 1 && defined(lzo_word_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) +#endif +#if 1 +#define lzo_int8_t signed char +#define lzo_uint8_t unsigned char +#define LZO_SIZEOF_LZO_INT8_T 1 +#define LZO_TYPEOF_LZO_INT8_T LZO_TYPEOF_CHAR +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) +#endif +#if defined(lzo_int16e_t) +#define lzo_int16_t lzo_int16e_t +#define lzo_uint16_t lzo_uint16e_t +#define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T +#define LZO_TYPEOF_LZO_INT16_T LZO_TYPEOF_LZO_INT16E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) +#endif +#if defined(lzo_int32e_t) +#define lzo_int32_t lzo_int32e_t +#define lzo_uint32_t lzo_uint32e_t +#define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T +#define LZO_TYPEOF_LZO_INT32_T LZO_TYPEOF_LZO_INT32E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) +#endif +#if defined(lzo_int64e_t) +#define lzo_int64_t lzo_int64e_t +#define lzo_uint64_t lzo_uint64e_t +#define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T +#define LZO_TYPEOF_LZO_INT64_T LZO_TYPEOF_LZO_INT64E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) +#endif +#if 1 +#define lzo_int_least32_t lzo_int32l_t +#define lzo_uint_least32_t lzo_uint32l_t +#define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T +#define LZO_TYPEOF_LZO_INT_LEAST32_T LZO_TYPEOF_LZO_INT32L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) +#endif +#if defined(lzo_int64l_t) +#define lzo_int_least64_t lzo_int64l_t +#define lzo_uint_least64_t lzo_uint64l_t +#define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T +#define LZO_TYPEOF_LZO_INT_LEAST64_T LZO_TYPEOF_LZO_INT64L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) +#endif +#if 1 +#define lzo_int_fast32_t lzo_int32f_t +#define lzo_uint_fast32_t lzo_uint32f_t +#define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T +#define LZO_TYPEOF_LZO_INT_FAST32_T LZO_TYPEOF_LZO_INT32F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) +#endif +#if defined(lzo_int64f_t) +#define lzo_int_fast64_t lzo_int64f_t +#define lzo_uint_fast64_t lzo_uint64f_t +#define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T +#define LZO_TYPEOF_LZO_INT_FAST64_T LZO_TYPEOF_LZO_INT64F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) +#endif +#if !defined(LZO_INT16_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) ((c) + 0) +# define LZO_UINT16_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) ((c) + 0L) +# define LZO_UINT16_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) (c) +# define LZO_UINT16_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) (c##L) +# define LZO_UINT16_C(c) (c##UL) +# else +# error "LZO_INT16_C" +# endif +#endif +#if !defined(LZO_INT32_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) ((c) + 0) +# define LZO_UINT32_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) ((c) + 0L) +# define LZO_UINT32_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) (c) +# define LZO_UINT32_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) (c##L) +# define LZO_UINT32_C(c) (c##UL) +# elif (LZO_SIZEOF_LONG_LONG >= 4) +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# else +# error "LZO_INT32_C" +# endif +#endif +#if !defined(LZO_INT64_C) && defined(lzo_int64l_t) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) ((c) + 0) +# define LZO_UINT64_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) ((c) + 0L) +# define LZO_UINT64_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) (c) +# define LZO_UINT64_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) (c##L) +# define LZO_UINT64_C(c) (c##UL) +# else +# error "LZO_INT64_C" +# endif +#endif +#endif + +#endif + +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x2090) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H 1 +#endif + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H 1 + +#if !defined(__LZO_IN_MINILZO) +#if defined(LZO_CFG_FREESTANDING) && (LZO_CFG_FREESTANDING) +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +#endif +#if defined(LZO_CFG_EXTRA_CONFIG_HEADER) +# include LZO_CFG_EXTRA_CONFIG_HEADER +#endif +#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED) +# error "include this file first" +#endif +#if defined(LZO_CFG_BUILD_DLL) && (LZO_CFG_BUILD_DLL+0) && !defined(__LZO_EXPORT1) && !defined(__LZO_EXPORT2) && 0 +#ifndef __LZODEFS_H_INCLUDED +#if defined(LZO_HAVE_CONFIG_H) +# include <config.h> +#endif +#include <limits.h> +#include <stddef.h> +#include <lzo/lzodefs.h> +#endif +#endif +#include <lzo/lzoconf.h> +#if defined(LZO_CFG_EXTRA_CONFIG_HEADER2) +# include LZO_CFG_EXTRA_CONFIG_HEADER2 +#endif +#endif + +#if !defined(__LZOCONF_H_INCLUDED) || (LZO_VERSION+0 != 0x2090) +# error "version mismatch" +#endif + +#if (LZO_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1100)) +# pragma warning(disable: 4702) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1000)) +# pragma warning(disable: 4127 4701) +# pragma warning(disable: 4514 4710 4711) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1300)) +# pragma warning(disable: 4820) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1800)) +# pragma warning(disable: 4746) +#endif +#if (LZO_CC_INTELC && (__INTEL_COMPILER >= 900)) +# pragma warning(disable: 1684) +#endif + +#if (LZO_CC_SUNPROC) +#if !defined(__cplusplus) +# pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED) +# pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP) +# pragma error_messages(off,E_STATEMENT_NOT_REACHED) +#endif +#endif + +#if !defined(__LZO_NOEXPORT1) +# define __LZO_NOEXPORT1 /*empty*/ +#endif +#if !defined(__LZO_NOEXPORT2) +# define __LZO_NOEXPORT2 /*empty*/ +#endif + +#if 1 +# define LZO_PUBLIC_DECL(r) LZO_EXTERN(r) +#endif +#if 1 +# define LZO_PUBLIC_IMPL(r) LZO_PUBLIC(r) +#endif +#if !defined(LZO_LOCAL_DECL) +# define LZO_LOCAL_DECL(r) __LZO_EXTERN_C LZO_LOCAL_IMPL(r) +#endif +#if !defined(LZO_LOCAL_IMPL) +# define LZO_LOCAL_IMPL(r) __LZO_NOEXPORT1 r __LZO_NOEXPORT2 __LZO_CDECL +#endif +#if 1 +# define LZO_STATIC_DECL(r) LZO_PRIVATE(r) +#endif +#if 1 +# define LZO_STATIC_IMPL(r) LZO_PRIVATE(r) +#endif + +#if defined(__LZO_IN_MINILZO) || (LZO_CFG_FREESTANDING) +#elif 1 +# include <string.h> +#else +# define LZO_WANT_ACC_INCD_H 1 +#endif +#if defined(LZO_HAVE_CONFIG_H) +# define LZO_CFG_NO_CONFIG_HEADER 1 +#endif + +#if 1 && !defined(LZO_CFG_FREESTANDING) +#if 1 && !defined(HAVE_STRING_H) +#define HAVE_STRING_H 1 +#endif +#if 1 && !defined(HAVE_MEMCMP) +#define HAVE_MEMCMP 1 +#endif +#if 1 && !defined(HAVE_MEMCPY) +#define HAVE_MEMCPY 1 +#endif +#if 1 && !defined(HAVE_MEMMOVE) +#define HAVE_MEMMOVE 1 +#endif +#if 1 && !defined(HAVE_MEMSET) +#define HAVE_MEMSET 1 +#endif +#endif + +#if 1 && defined(HAVE_STRING_H) +#include <string.h> +#endif + +#if 1 || defined(lzo_int8_t) || defined(lzo_uint8_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint8_t) == 1) +#endif +#if 1 || defined(lzo_int16_t) || defined(lzo_uint16_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint16_t) == 2) +#endif +#if 1 || defined(lzo_int32_t) || defined(lzo_uint32_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32_t) == 4) +#endif +#if defined(lzo_int64_t) || defined(lzo_uint64_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64_t) == 8) +#endif + +#if (LZO_CFG_FREESTANDING) +# undef HAVE_MEMCMP +# undef HAVE_MEMCPY +# undef HAVE_MEMMOVE +# undef HAVE_MEMSET +#endif + +#if !(HAVE_MEMCMP) +# undef memcmp +# define memcmp(a,b,c) lzo_memcmp(a,b,c) +#else +# undef lzo_memcmp +# define lzo_memcmp(a,b,c) memcmp(a,b,c) +#endif +#if !(HAVE_MEMCPY) +# undef memcpy +# define memcpy(a,b,c) lzo_memcpy(a,b,c) +#else +# undef lzo_memcpy +# define lzo_memcpy(a,b,c) memcpy(a,b,c) +#endif +#if !(HAVE_MEMMOVE) +# undef memmove +# define memmove(a,b,c) lzo_memmove(a,b,c) +#else +# undef lzo_memmove +# define lzo_memmove(a,b,c) memmove(a,b,c) +#endif +#if !(HAVE_MEMSET) +# undef memset +# define memset(a,b,c) lzo_memset(a,b,c) +#else +# undef lzo_memset +# define lzo_memset(a,b,c) memset(a,b,c) +#endif + +#undef NDEBUG +#if (LZO_CFG_FREESTANDING) +# undef LZO_DEBUG +# define NDEBUG 1 +# undef assert +# define assert(e) ((void)0) +#else +# if !defined(LZO_DEBUG) +# define NDEBUG 1 +# endif +# include <assert.h> +#endif + +#if 0 && defined(__BOUNDS_CHECKING_ON) +# include <unchecked.h> +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if (LZO_CFG_PGO) +# undef __lzo_likely +# undef __lzo_unlikely +# define __lzo_likely(e) (e) +# define __lzo_unlikely(e) (e) +#endif + +#undef _ +#undef __ +#undef ___ +#undef ____ +#undef _p0 +#undef _p1 +#undef _p2 +#undef _p3 +#undef _p4 +#undef _s0 +#undef _s1 +#undef _s2 +#undef _s3 +#undef _s4 +#undef _ww + +#if 1 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#if !defined(DMUL) +#if 0 + +# define DMUL(a,b) ((lzo_xint) ((lzo_uint32_t)(a) * (lzo_uint32_t)(b))) +#else +# define DMUL(a,b) ((lzo_xint) ((a) * (b))) +#endif +#endif + +#ifndef __LZO_FUNC_H +#define __LZO_FUNC_H 1 + +#if !defined(LZO_BITOPS_USE_ASM_BITSCAN) && !defined(LZO_BITOPS_USE_GNUC_BITSCAN) && !defined(LZO_BITOPS_USE_MSC_BITSCAN) +#if 1 && (LZO_ARCH_AMD64) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_ASM_SYNTAX_GNUC) +#define LZO_BITOPS_USE_ASM_BITSCAN 1 +#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul)))) +#define LZO_BITOPS_USE_GNUC_BITSCAN 1 +#elif (LZO_OS_WIN32 || LZO_OS_WIN64) && ((LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 1010)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) +#define LZO_BITOPS_USE_MSC_BITSCAN 1 +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +#include <intrin.h> +#endif +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +#pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) +#endif +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64) +#pragma intrinsic(_BitScanReverse64) +#pragma intrinsic(_BitScanForward64) +#endif +#endif +#endif + +__lzo_static_forceinline unsigned lzo_bitops_ctlz32_func(lzo_uint32_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) + unsigned long r; (void) _BitScanReverse(&r, v); return (unsigned) r ^ 31; +#define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint32_t r; + __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r ^ 31; +#define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT == 4) + unsigned r; r = (unsigned) __builtin_clz(v); return r; +#define lzo_bitops_ctlz32(v) ((unsigned) __builtin_clz(v)) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_clzl(v); return r ^ 32; +#define lzo_bitops_ctlz32(v) (((unsigned) __builtin_clzl(v)) ^ 32) +#else + LZO_UNUSED(v); return 0; +#endif +} + +#if defined(lzo_uint64_t) +__lzo_static_forceinline unsigned lzo_bitops_ctlz64_func(lzo_uint64_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) + unsigned long r; (void) _BitScanReverse64(&r, v); return (unsigned) r ^ 63; +#define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint64_t r; + __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r ^ 63; +#define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_clzl(v); return r; +#define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzl(v)) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG == 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_clzll(v); return r; +#define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzll(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} +#endif + +__lzo_static_forceinline unsigned lzo_bitops_cttz32_func(lzo_uint32_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) + unsigned long r; (void) _BitScanForward(&r, v); return (unsigned) r; +#define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint32_t r; + __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r; +#define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT >= 4) + unsigned r; r = (unsigned) __builtin_ctz(v); return r; +#define lzo_bitops_cttz32(v) ((unsigned) __builtin_ctz(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} + +#if defined(lzo_uint64_t) +__lzo_static_forceinline unsigned lzo_bitops_cttz64_func(lzo_uint64_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) + unsigned long r; (void) _BitScanForward64(&r, v); return (unsigned) r; +#define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint64_t r; + __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r; +#define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG >= 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_ctzl(v); return r; +#define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzl(v)) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG >= 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_ctzll(v); return r; +#define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzll(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} +#endif + +lzo_unused_funcs_impl(void, lzo_bitops_unused_funcs)(void) +{ + LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); + LZO_UNUSED_FUNC(lzo_bitops_ctlz32_func); + LZO_UNUSED_FUNC(lzo_bitops_cttz32_func); +#if defined(lzo_uint64_t) + LZO_UNUSED_FUNC(lzo_bitops_ctlz64_func); + LZO_UNUSED_FUNC(lzo_bitops_cttz64_func); +#endif +} + +#if defined(__lzo_alignof) && !(LZO_CFG_NO_UNALIGNED) +#if !defined(lzo_memops_tcheck__) && 0 +#define lzo_memops_tcheck__(t,a,b) ((void)0, sizeof(t) == (a) && __lzo_alignof(t) == (b)) +#endif +#endif +#ifndef lzo_memops_TU0p +#define lzo_memops_TU0p void __LZO_MMODEL * +#endif +#ifndef lzo_memops_TU1p +#define lzo_memops_TU1p unsigned char __LZO_MMODEL * +#endif +#ifndef lzo_memops_TU2p +#if (LZO_OPT_UNALIGNED16) +typedef lzo_uint16_t __lzo_may_alias lzo_memops_TU2; +#define lzo_memops_TU2p volatile lzo_memops_TU2 * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU2_struct,2) +typedef struct lzo_memops_TU2_struct lzo_memops_TU2; +#else +struct lzo_memops_TU2_struct { unsigned char a[2]; } __lzo_may_alias; +typedef struct lzo_memops_TU2_struct lzo_memops_TU2; +#endif +#ifndef lzo_memops_TU2p +#define lzo_memops_TU2p lzo_memops_TU2 * +#endif +#endif +#ifndef lzo_memops_TU4p +#if (LZO_OPT_UNALIGNED32) +typedef lzo_uint32_t __lzo_may_alias lzo_memops_TU4; +#define lzo_memops_TU4p volatile lzo_memops_TU4 __LZO_MMODEL * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU4_struct,4) +typedef struct lzo_memops_TU4_struct lzo_memops_TU4; +#else +struct lzo_memops_TU4_struct { unsigned char a[4]; } __lzo_may_alias; +typedef struct lzo_memops_TU4_struct lzo_memops_TU4; +#endif +#ifndef lzo_memops_TU4p +#define lzo_memops_TU4p lzo_memops_TU4 __LZO_MMODEL * +#endif +#endif +#ifndef lzo_memops_TU8p +#if (LZO_OPT_UNALIGNED64) +typedef lzo_uint64_t __lzo_may_alias lzo_memops_TU8; +#define lzo_memops_TU8p volatile lzo_memops_TU8 __LZO_MMODEL * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU8_struct,8) +typedef struct lzo_memops_TU8_struct lzo_memops_TU8; +#else +struct lzo_memops_TU8_struct { unsigned char a[8]; } __lzo_may_alias; +typedef struct lzo_memops_TU8_struct lzo_memops_TU8; +#endif +#ifndef lzo_memops_TU8p +#define lzo_memops_TU8p lzo_memops_TU8 __LZO_MMODEL * +#endif +#endif +#ifndef lzo_memops_set_TU1p +#define lzo_memops_set_TU1p volatile lzo_memops_TU1p +#endif +#ifndef lzo_memops_move_TU1p +#define lzo_memops_move_TU1p lzo_memops_TU1p +#endif +#define LZO_MEMOPS_SET1(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__1 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__1[0] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET2(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__2 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__2[0] = LZO_BYTE(cc); d__2[1] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET3(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__3 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__3[0] = LZO_BYTE(cc); d__3[1] = LZO_BYTE(cc); d__3[2] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET4(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__4 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__4[0] = LZO_BYTE(cc); d__4[1] = LZO_BYTE(cc); d__4[2] = LZO_BYTE(cc); d__4[3] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE1(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__1 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__1 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__1[0] = s__1[0]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE2(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__2 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__2 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__2[0] = s__2[0]; d__2[1] = s__2[1]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE3(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__3 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__3 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__3[0] = s__3[0]; d__3[1] = s__3[1]; d__3[2] = s__3[2]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE4(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__4 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__4 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__4[0] = s__4[0]; d__4[1] = s__4[1]; d__4[2] = s__4[2]; d__4[3] = s__4[3]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE8(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__8 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__8 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__8[0] = s__8[0]; d__8[1] = s__8[1]; d__8[2] = s__8[2]; d__8[3] = s__8[3]; \ + d__8[4] = s__8[4]; d__8[5] = s__8[5]; d__8[6] = s__8[6]; d__8[7] = s__8[7]; \ + LZO_BLOCK_END +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU1p)0)==1) +#define LZO_MEMOPS_COPY1(dd,ss) LZO_MEMOPS_MOVE1(dd,ss) +#if (LZO_OPT_UNALIGNED16) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2) +#define LZO_MEMOPS_COPY2(dd,ss) \ + * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss) +#elif defined(lzo_memops_tcheck__) +#define LZO_MEMOPS_COPY2(dd,ss) \ + LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU2,2,1)) { \ + * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE2(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY2(dd,ss) LZO_MEMOPS_MOVE2(dd,ss) +#endif +#if (LZO_OPT_UNALIGNED32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4) +#define LZO_MEMOPS_COPY4(dd,ss) \ + * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss) +#elif defined(lzo_memops_tcheck__) +#define LZO_MEMOPS_COPY4(dd,ss) \ + LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU4,4,1)) { \ + * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE4(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY4(dd,ss) LZO_MEMOPS_MOVE4(dd,ss) +#endif +#if (LZO_WORDSIZE != 8) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END +#else +#if (LZO_OPT_UNALIGNED64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8) +#define LZO_MEMOPS_COPY8(dd,ss) \ + * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss) +#elif (LZO_OPT_UNALIGNED32) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END +#elif defined(lzo_memops_tcheck__) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU8,8,1)) { \ + * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE8(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY8(dd,ss) LZO_MEMOPS_MOVE8(dd,ss) +#endif +#endif +#define LZO_MEMOPS_COPYN(dd,ss,nn) \ + LZO_BLOCK_BEGIN \ + lzo_memops_TU1p d__n = (lzo_memops_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_TU1p s__n = (const lzo_memops_TU1p) (const lzo_memops_TU0p) (ss); \ + lzo_uint n__n = (nn); \ + while ((void)0, n__n >= 8) { LZO_MEMOPS_COPY8(d__n, s__n); d__n += 8; s__n += 8; n__n -= 8; } \ + if ((void)0, n__n >= 4) { LZO_MEMOPS_COPY4(d__n, s__n); d__n += 4; s__n += 4; n__n -= 4; } \ + if ((void)0, n__n > 0) do { *d__n++ = *s__n++; } while (--n__n > 0); \ + LZO_BLOCK_END + +__lzo_static_forceinline lzo_uint16_t lzo_memops_get_le16(const lzo_voidp ss) +{ + lzo_uint16_t v; +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY2(&v, ss); +#elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + const lzo_memops_TU2p s = (const lzo_memops_TU2p) ss; + unsigned long vv; + __asm__("lhbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); + v = (lzo_uint16_t) vv; +#else + const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; + v = (lzo_uint16_t) (((lzo_uint16_t)s[0]) | ((lzo_uint16_t)s[1] << 8)); +#endif + return v; +} +#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE16(ss) (* (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)) +#else +#define LZO_MEMOPS_GET_LE16(ss) lzo_memops_get_le16(ss) +#endif + +__lzo_static_forceinline lzo_uint32_t lzo_memops_get_le32(const lzo_voidp ss) +{ + lzo_uint32_t v; +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY4(&v, ss); +#elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + const lzo_memops_TU4p s = (const lzo_memops_TU4p) ss; + unsigned long vv; + __asm__("lwbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); + v = (lzo_uint32_t) vv; +#else + const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; + v = (lzo_uint32_t) (((lzo_uint32_t)s[0]) | ((lzo_uint32_t)s[1] << 8) | ((lzo_uint32_t)s[2] << 16) | ((lzo_uint32_t)s[3] << 24)); +#endif + return v; +} +#if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE32(ss) (* (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)) +#else +#define LZO_MEMOPS_GET_LE32(ss) lzo_memops_get_le32(ss) +#endif + +#if (LZO_OPT_UNALIGNED64) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE64(ss) (* (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)) +#endif + +__lzo_static_forceinline lzo_uint16_t lzo_memops_get_ne16(const lzo_voidp ss) +{ + lzo_uint16_t v; + LZO_MEMOPS_COPY2(&v, ss); + return v; +} +#if (LZO_OPT_UNALIGNED16) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2) +#define LZO_MEMOPS_GET_NE16(ss) (* (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)) +#else +#define LZO_MEMOPS_GET_NE16(ss) lzo_memops_get_ne16(ss) +#endif + +__lzo_static_forceinline lzo_uint32_t lzo_memops_get_ne32(const lzo_voidp ss) +{ + lzo_uint32_t v; + LZO_MEMOPS_COPY4(&v, ss); + return v; +} +#if (LZO_OPT_UNALIGNED32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4) +#define LZO_MEMOPS_GET_NE32(ss) (* (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)) +#else +#define LZO_MEMOPS_GET_NE32(ss) lzo_memops_get_ne32(ss) +#endif + +#if (LZO_OPT_UNALIGNED64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8) +#define LZO_MEMOPS_GET_NE64(ss) (* (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)) +#endif + +__lzo_static_forceinline void lzo_memops_put_le16(lzo_voidp dd, lzo_uint16_t vv) +{ +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY2(dd, &vv); +#elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + lzo_memops_TU2p d = (lzo_memops_TU2p) dd; + unsigned long v = vv; + __asm__("sthbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); +#else + lzo_memops_TU1p d = (lzo_memops_TU1p) dd; + d[0] = LZO_BYTE((vv ) & 0xff); + d[1] = LZO_BYTE((vv >> 8) & 0xff); +#endif +} +#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_PUT_LE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_LE16(dd,vv) lzo_memops_put_le16(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_le32(lzo_voidp dd, lzo_uint32_t vv) +{ +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY4(dd, &vv); +#elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + lzo_memops_TU4p d = (lzo_memops_TU4p) dd; + unsigned long v = vv; + __asm__("stwbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); +#else + lzo_memops_TU1p d = (lzo_memops_TU1p) dd; + d[0] = LZO_BYTE((vv ) & 0xff); + d[1] = LZO_BYTE((vv >> 8) & 0xff); + d[2] = LZO_BYTE((vv >> 16) & 0xff); + d[3] = LZO_BYTE((vv >> 24) & 0xff); +#endif +} +#if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_PUT_LE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_LE32(dd,vv) lzo_memops_put_le32(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_ne16(lzo_voidp dd, lzo_uint16_t vv) +{ + LZO_MEMOPS_COPY2(dd, &vv); +} +#if (LZO_OPT_UNALIGNED16) +#define LZO_MEMOPS_PUT_NE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_NE16(dd,vv) lzo_memops_put_ne16(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_ne32(lzo_voidp dd, lzo_uint32_t vv) +{ + LZO_MEMOPS_COPY4(dd, &vv); +} +#if (LZO_OPT_UNALIGNED32) +#define LZO_MEMOPS_PUT_NE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_NE32(dd,vv) lzo_memops_put_ne32(dd,vv) +#endif + +lzo_unused_funcs_impl(void, lzo_memops_unused_funcs)(void) +{ + LZO_UNUSED_FUNC(lzo_memops_unused_funcs); + LZO_UNUSED_FUNC(lzo_memops_get_le16); + LZO_UNUSED_FUNC(lzo_memops_get_le32); + LZO_UNUSED_FUNC(lzo_memops_get_ne16); + LZO_UNUSED_FUNC(lzo_memops_get_ne32); + LZO_UNUSED_FUNC(lzo_memops_put_le16); + LZO_UNUSED_FUNC(lzo_memops_put_le32); + LZO_UNUSED_FUNC(lzo_memops_put_ne16); + LZO_UNUSED_FUNC(lzo_memops_put_ne32); +} + +#endif + +#ifndef UA_SET1 +#define UA_SET1 LZO_MEMOPS_SET1 +#endif +#ifndef UA_SET2 +#define UA_SET2 LZO_MEMOPS_SET2 +#endif +#ifndef UA_SET3 +#define UA_SET3 LZO_MEMOPS_SET3 +#endif +#ifndef UA_SET4 +#define UA_SET4 LZO_MEMOPS_SET4 +#endif +#ifndef UA_MOVE1 +#define UA_MOVE1 LZO_MEMOPS_MOVE1 +#endif +#ifndef UA_MOVE2 +#define UA_MOVE2 LZO_MEMOPS_MOVE2 +#endif +#ifndef UA_MOVE3 +#define UA_MOVE3 LZO_MEMOPS_MOVE3 +#endif +#ifndef UA_MOVE4 +#define UA_MOVE4 LZO_MEMOPS_MOVE4 +#endif +#ifndef UA_MOVE8 +#define UA_MOVE8 LZO_MEMOPS_MOVE8 +#endif +#ifndef UA_COPY1 +#define UA_COPY1 LZO_MEMOPS_COPY1 +#endif +#ifndef UA_COPY2 +#define UA_COPY2 LZO_MEMOPS_COPY2 +#endif +#ifndef UA_COPY3 +#define UA_COPY3 LZO_MEMOPS_COPY3 +#endif +#ifndef UA_COPY4 +#define UA_COPY4 LZO_MEMOPS_COPY4 +#endif +#ifndef UA_COPY8 +#define UA_COPY8 LZO_MEMOPS_COPY8 +#endif +#ifndef UA_COPYN +#define UA_COPYN LZO_MEMOPS_COPYN +#endif +#ifndef UA_COPYN_X +#define UA_COPYN_X LZO_MEMOPS_COPYN +#endif +#ifndef UA_GET_LE16 +#define UA_GET_LE16 LZO_MEMOPS_GET_LE16 +#endif +#ifndef UA_GET_LE32 +#define UA_GET_LE32 LZO_MEMOPS_GET_LE32 +#endif +#ifdef LZO_MEMOPS_GET_LE64 +#ifndef UA_GET_LE64 +#define UA_GET_LE64 LZO_MEMOPS_GET_LE64 +#endif +#endif +#ifndef UA_GET_NE16 +#define UA_GET_NE16 LZO_MEMOPS_GET_NE16 +#endif +#ifndef UA_GET_NE32 +#define UA_GET_NE32 LZO_MEMOPS_GET_NE32 +#endif +#ifdef LZO_MEMOPS_GET_NE64 +#ifndef UA_GET_NE64 +#define UA_GET_NE64 LZO_MEMOPS_GET_NE64 +#endif +#endif +#ifndef UA_PUT_LE16 +#define UA_PUT_LE16 LZO_MEMOPS_PUT_LE16 +#endif +#ifndef UA_PUT_LE32 +#define UA_PUT_LE32 LZO_MEMOPS_PUT_LE32 +#endif +#ifndef UA_PUT_NE16 +#define UA_PUT_NE16 LZO_MEMOPS_PUT_NE16 +#endif +#ifndef UA_PUT_NE32 +#define UA_PUT_NE32 LZO_MEMOPS_PUT_NE32 +#endif + +#define MEMCPY8_DS(dest,src,len) \ + lzo_memcpy(dest,src,len); dest += len; src += len + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; while (--len > 0) + +LZO_EXTERN(const lzo_bytep) lzo_copyright(void); + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if (LZO_ARCH_I086) +#error "LZO_ARCH_I086 is unsupported" +#elif (LZO_MM_PVP) +#error "LZO_MM_PVP is unsupported" +#else +#define PTR(a) ((lzo_uintptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) (PTR(a) - PTR(b)) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_xint a_lzo_xint; + lzo_int16_t a_lzo_int16_t; + lzo_uint16_t a_lzo_uint16_t; + lzo_int32_t a_lzo_int32_t; + lzo_uint32_t a_lzo_uint32_t; +#if defined(lzo_uint64_t) + lzo_int64_t a_lzo_int64_t; + lzo_uint64_t a_lzo_uint64_t; +#endif + size_t a_size_t; + ptrdiff_t a_ptrdiff_t; + lzo_uintptr_t a_lzo_uintptr_t; + void * a_void_p; + char * a_char_p; + unsigned char * a_uchar_p; + const void * a_c_void_p; + const char * a_c_char_p; + const unsigned char * a_c_uchar_p; + lzo_voidp a_lzo_voidp; + lzo_bytep a_lzo_bytep; + const lzo_voidp a_c_lzo_voidp; + const lzo_bytep a_c_lzo_bytep; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#ifndef LZO_DETERMINISTIC +#define LZO_DETERMINISTIC 1 +#endif + +#ifndef LZO_DICT_USE_PTR +#define LZO_DICT_USE_PTR 1 +#endif + +#if (LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t * +#endif + +#endif + +#if !defined(MINILZO_CFG_SKIP_LZO_PTR) + +LZO_PUBLIC(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_uintptr_t p; + +#if (LZO_ARCH_I086) +#error "LZO_ARCH_I086 is unsupported" +#elif (LZO_MM_PVP) +#error "LZO_MM_PVP is unsupported" +#else + p = (lzo_uintptr_t) PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ +#if (__LZO_UINTPTR_T_IS_POINTER) +#error "__LZO_UINTPTR_T_IS_POINTER is unsupported" +#else + lzo_uintptr_t p, n; + if (size < 2) return 0; + p = __lzo_ptr_linear(ptr); +#if 0 + n = (((p + size - 1) / size) * size) - p; +#else + if ((size & (size - 1)) != 0) + return 0; + n = size; n = ((p + n - 1) & ~(n - 1)) - p; +#endif +#endif + assert((long)n >= 0); + assert(n <= size); + return (unsigned)n; +} + +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_UTIL) + +/* If you use the LZO library in a product, I would appreciate that you + * keep this copyright string in the executable of your product. + */ + +static const char lzo_copyright_[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\r\n\n" + "LZO data compression library.\n" + "$Copyright: LZO Copyright (C) 1996-2015 Markus Franz Xaver Johannes Oberhumer\n" + "<markus@oberhumer.com>\n" + "http://www.oberhumer.com $\n\n" + "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" + "$Info: " LZO_INFO_STRING " $\n"; +#endif +static const char lzo_version_string_[] = LZO_VERSION_STRING; +static const char lzo_version_date_[] = LZO_VERSION_DATE; + +LZO_PUBLIC(const lzo_bytep) +lzo_copyright(void) +{ + return (const lzo_bytep) lzo_copyright_; +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return lzo_version_string_; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return lzo_version_date_; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return lzo_version_string_; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return lzo_version_date_; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1) +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2) +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4) +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8) + +LZO_PUBLIC(lzo_uint32_t) +lzo_adler32(lzo_uint32_t adler, const lzo_bytep buf, lzo_uint len) +{ + lzo_uint32_t s1 = adler & 0xffff; + lzo_uint32_t s2 = (adler >> 16) & 0xffff; + unsigned k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +#undef LZO_DO1 +#undef LZO_DO2 +#undef LZO_DO4 +#undef LZO_DO8 +#undef LZO_DO16 + +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_STRING) +#undef lzo_memcmp +#undef lzo_memcpy +#undef lzo_memmove +#undef lzo_memset +#if !defined(__LZO_MMODEL_HUGE) +# undef LZO_HAVE_MM_HUGE_PTR +#endif +#define lzo_hsize_t lzo_uint +#define lzo_hvoid_p lzo_voidp +#define lzo_hbyte_p lzo_bytep +#define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f +#define lzo_hmemcmp lzo_memcmp +#define lzo_hmemcpy lzo_memcpy +#define lzo_hmemmove lzo_memmove +#define lzo_hmemset lzo_memset +#define __LZOLIB_HMEMCPY_CH_INCLUDED 1 +#if !defined(LZOLIB_PUBLIC) +# define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f) +#endif +LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCMP) + const lzo_hbyte_p p1 = LZO_STATIC_CAST(const lzo_hbyte_p, s1); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, s2); + if __lzo_likely(len > 0) do + { + int d = *p1 - *p2; + if (d != 0) + return d; + p1++; p2++; + } while __lzo_likely(--len > 0); + return 0; +#else + return memcmp(s1, s2, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCPY) + lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); + if (!(len > 0) || p1 == p2) + return dest; + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + return dest; +#else + return memcpy(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMMOVE) + lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); + if (!(len > 0) || p1 == p2) + return dest; + if (p1 < p2) + { + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while __lzo_likely(--len > 0); + } + return dest; +#else + return memmove(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int cc, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET) + lzo_hbyte_p p = LZO_STATIC_CAST(lzo_hbyte_p, s); + unsigned char c = LZO_ITRUNC(unsigned char, cc); + if __lzo_likely(len > 0) do + *p++ = c; + while __lzo_likely(--len > 0); + return s; +#else + return memset(s, cc, len); +#endif +} +#undef LZOLIB_PUBLIC +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_INIT) + +#if !defined(__LZO_IN_MINILZO) + +#define LZO_WANT_ACC_CHK_CH 1 +#undef LZOCHK_ASSERT + + LZOCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) + LZOCHK_ASSERT_IS_SIGNED_T(lzo_int) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) +#if !(__LZO_UINTPTR_T_IS_POINTER) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) +#endif + LZOCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) + +#endif +#undef LZOCHK_ASSERT + +union lzo_config_check_union { + lzo_uint a[2]; + unsigned char b[2*LZO_MAX(8,sizeof(lzo_uint))]; +#if defined(lzo_uint64_t) + lzo_uint64_t c[2]; +#endif +}; + +#if 0 +#define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off))) +#else +static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off) +{ + return (lzo_voidp) ((lzo_bytep) ptr + off); +} +#endif + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030100ul && LZO_CC_CLANG < 0x030300ul)) +# if 0 + volatile +# endif +#endif + union lzo_config_check_union u; + lzo_voidp p; + unsigned r = 1; + + u.a[0] = u.a[1] = 0; + p = u2p(&u, 0); + r &= ((* (lzo_bytep) p) == 0); +#if !(LZO_CFG_NO_CONFIG_CHECK) +#if (LZO_ABI_BIG_ENDIAN) + u.a[0] = u.a[1] = 0; u.b[sizeof(lzo_uint) - 1] = 128; + p = u2p(&u, 0); + r &= ((* (lzo_uintp) p) == 128); +#endif +#if (LZO_ABI_LITTLE_ENDIAN) + u.a[0] = u.a[1] = 0; u.b[0] = 128; + p = u2p(&u, 0); + r &= ((* (lzo_uintp) p) == 128); +#endif + u.a[0] = u.a[1] = 0; + u.b[0] = 1; u.b[3] = 2; + p = u2p(&u, 1); + r &= UA_GET_NE16(p) == 0; + r &= UA_GET_LE16(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE16(p) == 128; + u.b[2] = 129; + r &= UA_GET_LE16(p) == LZO_UINT16_C(0x8180); +#if (LZO_ABI_BIG_ENDIAN) + r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8081); +#endif +#if (LZO_ABI_LITTLE_ENDIAN) + r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8180); +#endif + u.a[0] = u.a[1] = 0; + u.b[0] = 3; u.b[5] = 4; + p = u2p(&u, 1); + r &= UA_GET_NE32(p) == 0; + r &= UA_GET_LE32(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE32(p) == 128; + u.b[2] = 129; u.b[3] = 130; u.b[4] = 131; + r &= UA_GET_LE32(p) == LZO_UINT32_C(0x83828180); +#if (LZO_ABI_BIG_ENDIAN) + r &= UA_GET_NE32(p) == LZO_UINT32_C(0x80818283); +#endif +#if (LZO_ABI_LITTLE_ENDIAN) + r &= UA_GET_NE32(p) == LZO_UINT32_C(0x83828180); +#endif +#if defined(UA_GET_NE64) + u.c[0] = u.c[1] = 0; + u.b[0] = 5; u.b[9] = 6; + p = u2p(&u, 1); + u.c[0] = u.c[1] = 0; + r &= UA_GET_NE64(p) == 0; +#if defined(UA_GET_LE64) + r &= UA_GET_LE64(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE64(p) == 128; +#endif +#endif +#if defined(lzo_bitops_ctlz32) + { unsigned i = 0; lzo_uint32_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_ctlz32(v) == 31 - i; + r &= lzo_bitops_ctlz32_func(v) == 31 - i; + }} +#endif +#if defined(lzo_bitops_ctlz64) + { unsigned i = 0; lzo_uint64_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_ctlz64(v) == 63 - i; + r &= lzo_bitops_ctlz64_func(v) == 63 - i; + }} +#endif +#if defined(lzo_bitops_cttz32) + { unsigned i = 0; lzo_uint32_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_cttz32(v) == i; + r &= lzo_bitops_cttz32_func(v) == i; + }} +#endif +#if defined(lzo_bitops_cttz64) + { unsigned i = 0; lzo_uint64_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_cttz64(v) == i; + r &= lzo_bitops_cttz64_func(v) == i; + }} +#endif +#endif + LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); + + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +LZO_PUBLIC(int) +__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + +#if defined(__LZO_IN_MINILZO) +#elif (LZO_CC_MSC && ((_MSC_VER) < 700)) +#else +#define LZO_WANT_ACC_CHK_CH 1 +#undef LZOCHK_ASSERT +#define LZOCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif +#undef LZOCHK_ASSERT + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32_t)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_callback_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD) + +#if 0 +BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment, + WORD wHeapSize, LPSTR lpszCmdLine ) +#else +int __far __pascal LibMain ( int a, short b, short c, long d ) +#endif +{ + LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d); + return 1; +} + +#endif + +#endif + +#endif + +#define LZO1X 1 +#define LZO_EOF_CODE 1 +#define M2_MAX_OFFSET 0x0800 + +#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) + +#if 1 && defined(UA_GET_LE32) +#undef LZO_DICT_USE_PTR +#define LZO_DICT_USE_PTR 0 +#undef lzo_dict_t +#define lzo_dict_t lzo_uint16_t +#endif + +#define LZO_NEED_DICT_H 1 +#ifndef D_BITS +#define D_BITS 14 +#endif +#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) +#if 1 +#define DINDEX(dv,p) DM(((DMUL(0x1824429d,dv)) >> (32-D_BITS))) +#else +#define DINDEX(dv,p) DM((dv) + ((dv) >> (32-D_BITS))) +#endif + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H 1 + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X 1 +#endif + +#if !defined(__LZO_IN_MINILZO) +#include <lzo/lzo1x.h> +#endif + +#ifndef LZO_EOF_CODE +#define LZO_EOF_CODE 1 +#endif +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 6 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 6 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#undef DM +#undef DX + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_xint)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_xint)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +#if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +static void __attribute__((__unused__)) +#else +static void +#endif +DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) +{ + lzo_xint df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if (LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_dict_t) pd(p, in)) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if (LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR(( \ + m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \ + PTR_LT(m_pos,in) || \ + (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) == 0 || \ + m_off > max_offset ))) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (pd(ip, in) <= m_off || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if (LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define LZO_DETERMINISTIC !(LZO_DICT_USE_PTR) + +#ifndef DO_COMPRESS +#define DO_COMPRESS lzo1x_1_compress +#endif + +#if 1 && defined(DO_COMPRESS) && !defined(do_compress) +# define do_compress LZO_PP_ECONCAT2(DO_COMPRESS,_core) +#endif + +static __lzo_noinline lzo_uint +do_compress ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_uint ti, lzo_voidp wrkmem) +{ + const lzo_bytep ip; + lzo_bytep op; + const lzo_bytep const in_end = in + in_len; + const lzo_bytep const ip_end = in + in_len - 20; + const lzo_bytep ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += ti < 4 ? 4 - ti : 0; + for (;;) + { + const lzo_bytep m_pos; +#if !(LZO_DETERMINISTIC) + LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0); + lzo_uint m_len; + lzo_uint dindex; +next: + if __lzo_unlikely(ip >= ip_end) + break; + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if (LZO_OPT_UNALIGNED32) + if (UA_GET_NE32(m_pos) != UA_GET_NE32(ip)) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3]) +#endif + { +literal: + UPDATE_I(dict,0,dindex,ip,in); + ip += 1 + ((ip - ii) >> 5); + continue; + } + UPDATE_I(dict,0,dindex,ip,in); +#else + lzo_uint m_off; + lzo_uint m_len; + { + lzo_uint32_t dv; + lzo_uint dindex; +literal: + ip += 1 + ((ip - ii) >> 5); +next: + if __lzo_unlikely(ip >= ip_end) + break; + dv = UA_GET_LE32(ip); + dindex = DINDEX(dv,ip); + GINDEX(m_off,m_pos,in+dict,dindex,in); + UPDATE_I(dict,0,dindex,ip,in); + if __lzo_unlikely(dv != UA_GET_LE32(m_pos)) + goto literal; + } +#endif + + ii -= ti; ti = 0; + { + lzo_uint t = pd(ip,ii); + if (t != 0) + { + if (t <= 3) + { + op[-2] = LZO_BYTE(op[-2] | t); +#if (LZO_OPT_UNALIGNED32) + UA_COPY4(op, ii); + op += t; +#else + { do *op++ = *ii++; while (--t > 0); } +#endif + } +#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) + else if (t <= 16) + { + *op++ = LZO_BYTE(t - 3); + UA_COPY8(op, ii); + UA_COPY8(op+8, ii+8); + op += t; + } +#endif + else + { + if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + *op++ = 0; + while __lzo_unlikely(tt > 255) + { + tt -= 255; + UA_SET1(op, 0); + op++; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } +#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) + do { + UA_COPY8(op, ii); + UA_COPY8(op+8, ii+8); + op += 16; ii += 16; t -= 16; + } while (t >= 16); if (t > 0) +#endif + { do *op++ = *ii++; while (--t > 0); } + } + } + } + m_len = 4; + { +#if (LZO_OPT_UNALIGNED64) + lzo_uint64_t v; + v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); + if __lzo_unlikely(v == 0) { + do { + m_len += 8; + v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (v == 0); + } +#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz64) + m_len += lzo_bitops_ctlz64(v) / CHAR_BIT; +#elif (LZO_ABI_BIG_ENDIAN) + if ((v >> (64 - CHAR_BIT)) == 0) do { + v <<= CHAR_BIT; + m_len += 1; + } while ((v >> (64 - CHAR_BIT)) == 0); +#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz64) + m_len += lzo_bitops_cttz64(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) + if ((v & UCHAR_MAX) == 0) do { + v >>= CHAR_BIT; + m_len += 1; + } while ((v & UCHAR_MAX) == 0); +#else + if (ip[m_len] == m_pos[m_len]) do { + m_len += 1; + } while (ip[m_len] == m_pos[m_len]); +#endif +#elif (LZO_OPT_UNALIGNED32) + lzo_uint32_t v; + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); + if __lzo_unlikely(v == 0) { + do { + m_len += 4; + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); + if (v != 0) + break; + m_len += 4; + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (v == 0); + } +#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz32) + m_len += lzo_bitops_ctlz32(v) / CHAR_BIT; +#elif (LZO_ABI_BIG_ENDIAN) + if ((v >> (32 - CHAR_BIT)) == 0) do { + v <<= CHAR_BIT; + m_len += 1; + } while ((v >> (32 - CHAR_BIT)) == 0); +#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz32) + m_len += lzo_bitops_cttz32(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) + if ((v & UCHAR_MAX) == 0) do { + v >>= CHAR_BIT; + m_len += 1; + } while ((v & UCHAR_MAX) == 0); +#else + if (ip[m_len] == m_pos[m_len]) do { + m_len += 1; + } while (ip[m_len] == m_pos[m_len]); +#endif +#else + if __lzo_unlikely(ip[m_len] == m_pos[m_len]) { + do { + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (ip[m_len] == m_pos[m_len]); + } +#endif + } +m_len_done: + m_off = pd(ip,m_pos); + ip += m_len; + ii = ip; + if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= M3_MAX_LEN) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= M3_MAX_LEN; + *op++ = M3_MARKER | 0; + while __lzo_unlikely(m_len > 255) + { + m_len -= 255; + UA_SET1(op, 0); + op++; + } + *op++ = LZO_BYTE(m_len); + } + *op++ = LZO_BYTE(m_off << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + else + { + m_off -= 0x4000; + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8)); + while __lzo_unlikely(m_len > 255) + { + m_len -= 255; + UA_SET1(op, 0); + op++; + } + *op++ = LZO_BYTE(m_len); + } + *op++ = LZO_BYTE(m_off << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + goto next; + } + + *out_len = pd(op, out); + return pd(in_end,ii-ti); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + const lzo_bytep ip = in; + lzo_bytep op = out; + lzo_uint l = in_len; + lzo_uint t = 0; + + while (l > 20) + { + lzo_uint ll = l; + lzo_uintptr_t ll_end; +#if 0 || (LZO_DETERMINISTIC) + ll = LZO_MIN(ll, 49152); +#endif + ll_end = (lzo_uintptr_t)ip + ll; + if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll) + break; +#if (LZO_DETERMINISTIC) + lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t)); +#endif + t = do_compress(ip,ll,op,out_len,t,wrkmem); + ip += ll; + op += *out_len; + l -= ll; + } + t += l; + + if (t > 0) + { + const lzo_bytep ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] = LZO_BYTE(op[-2] | t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + UA_SET1(op, 0); + op++; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + UA_COPYN(op, ii, t); + op += t; + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = pd(op, out); + return LZO_E_OK; +} + +#endif + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND 1 +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_IP_AND_TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef TEST_IV +#undef TEST_OV +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP 1 +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP 1 +#else +# define TEST_OP 1 +#endif + +#if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) +#elif defined(HAVE_TEST_IP) +# define TEST_IP_AND_TEST_OP TEST_IP +#elif defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP TEST_OP +#else +# define TEST_IP_AND_TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP 1 +#else +# define NEED_IP(x) ((void) 0) +# define TEST_IV(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP 1 +#else +# define NEED_OP(x) ((void) 0) +# define TEST_OV(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP 1 +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP 1 +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + lzo_bytep op; + const lzo_bytep ip; + lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + NEED_IP(1); + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+3); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + for (;;) + { + NEED_IP(3); + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_IV(t); + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + t += 3; + if (t >= 8) do + { + UA_COPY8(op,ip); + op += 8; ip += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } + if (t > 0) + { + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + } +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + UA_COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !(LZO_OPT_UNALIGNED32) + } + else +#endif +#endif +#if !(LZO_OPT_UNALIGNED32) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + for (;;) { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 31 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 7 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + if (op - m_pos >= 8) + { + t += (3 - 1); + if (t >= 8) do + { + UA_COPY8(op,m_pos); + op += 8; m_pos += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } + if (t > 0) + { + *op++ = m_pos[0]; + if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } + } + } + else +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } + } + +eof_found: + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +#define LZO_TEST_OVERRUN 1 +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND 1 +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_IP_AND_TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef TEST_IV +#undef TEST_OV +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP 1 +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP 1 +#else +# define TEST_OP 1 +#endif + +#if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) +#elif defined(HAVE_TEST_IP) +# define TEST_IP_AND_TEST_OP TEST_IP +#elif defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP TEST_OP +#else +# define TEST_IP_AND_TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP 1 +#else +# define NEED_IP(x) ((void) 0) +# define TEST_IV(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP 1 +#else +# define NEED_OP(x) ((void) 0) +# define TEST_OV(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP 1 +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP 1 +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + lzo_bytep op; + const lzo_bytep ip; + lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + NEED_IP(1); + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+3); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + for (;;) + { + NEED_IP(3); + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_IV(t); + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + t += 3; + if (t >= 8) do + { + UA_COPY8(op,ip); + op += 8; ip += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } + if (t > 0) + { + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + } +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + UA_COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !(LZO_OPT_UNALIGNED32) + } + else +#endif +#endif +#if !(LZO_OPT_UNALIGNED32) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + for (;;) { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 31 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 7 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + if (op - m_pos >= 8) + { + t += (3 - 1); + if (t >= 8) do + { + UA_COPY8(op,m_pos); + op += 8; m_pos += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } + if (t > 0) + { + *op++ = m_pos[0]; + if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } + } + } + else +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } + } + +eof_found: + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +/***** End of minilzo.c *****/ diff --git a/extensions/common/minilzo.h b/extensions/common/minilzo.h new file mode 100644 index 0000000000..e5adc6ed94 --- /dev/null +++ b/extensions/common/minilzo.h @@ -0,0 +1,106 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2015 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + <markus@oberhumer.com> + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H_INCLUDED +#define __MINILZO_H_INCLUDED 1 + +#define MINILZO_VERSION 0x2090 + +#if defined(__LZOCONF_H_INCLUDED) +# error "you cannot use both LZO and miniLZO" +#endif + +/* internal Autoconf configuration file - only used when building miniLZO */ +#ifdef MINILZO_HAVE_CONFIG_H +# include <config.h> +#endif +#include <limits.h> +#include <stddef.h> + +#ifndef __LZODEFS_H_INCLUDED +#include "lzodefs.h" +#endif +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32_t) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + + +/* vim:set ts=4 sw=4 et: */ diff --git a/extensions/common/p3d/animation.cpp b/extensions/common/p3d/animation.cpp new file mode 100644 index 0000000000..1c97399a1e --- /dev/null +++ b/extensions/common/p3d/animation.cpp @@ -0,0 +1,72 @@ +#pragma once + +#include "p3d/animation.hpp" +#include "read_helpers.hpp" +#include "..\simulation\object.hpp" + +namespace ace { + namespace p3d { + animation::animation() {} + animation::animation(std::istream &stream_, uint32_t version = 68) { + float tvalue = 0; + + stream_.read((char *)&type, sizeof(uint32_t)); + + READ_STRING(name); + READ_STRING(source); + + stream_.read((char *)&min_value, sizeof(float)); + stream_.read((char *)&max_value, sizeof(float)); + stream_.read((char *)&min_phase, sizeof(float)); + stream_.read((char *)&max_phase, sizeof(float)); + + stream_.read((char *)&junk, sizeof(uint32_t)); + stream_.read((char *)&junk2, sizeof(uint32_t)); + stream_.read((char *)&source_address, sizeof(uint32_t)); + + // This always adds up to 2*4 more bytes unless its direct apparently + switch (type) { + // rotations + case 0: + case 1: + case 2: + case 3: + stream_.read((char *)&angle0, sizeof(float)); + stream_.read((char *)&angle1, sizeof(float)); + break; + // translations + case 4: + case 5: + case 6: + case 7: // also do the hide here, it'll always be 0 + stream_.read((char *)&offset0, sizeof(float)); + stream_.read((char *)&offset1, sizeof(float)); + break; + case 8: + float pos[3]; + stream_.read((char *)&pos, sizeof(float) * 3); + direct_axis_pos = ace::vector3<float>(pos); + float dir[3]; + stream_.read((char *)&dir, sizeof(float) * 3); + direct_axis_dir = ace::vector3<float>(dir); + stream_.read((char *)&direct_angle, sizeof(float)); + stream_.read((char *)&direct_axis_offset, sizeof(float)); + break; + case 9: // fucking hides... + stream_.read((char *)&hide_value, sizeof(float)); + stream_.read((char *)&offset1, sizeof(float)); // this is junk throw it in offset1 for hides + break; + default: + stream_.read((char *)&offset0, sizeof(float)); + stream_.read((char *)&offset1, sizeof(float)); + break; + } + + + LOG(DEBUG) << "Animation loaded: " << name << ", source=" << source; + } + + animation::~animation() { + } + }; +}; \ No newline at end of file diff --git a/extensions/common/p3d/animation.hpp b/extensions/common/p3d/animation.hpp new file mode 100644 index 0000000000..b53bee6a68 --- /dev/null +++ b/extensions/common/p3d/animation.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include "shared.hpp" +#include "vector.hpp" + +namespace ace { + namespace p3d { + + class animate_bone { + public: + animate_bone() : index(-1) {} + int32_t index; + uint32_t lod; + ace::vector3<float> axis_direction; + ace::vector3<float> axis_position; + }; + typedef std::shared_ptr<animate_bone> animate_bone_p; + + class animation { + public: + animation(); + animation(std::istream &, uint32_t); + ~animation(); + + uint32_t type; + std::string name; // "RightDoor" + std::string source; // "rotor" + float min_value; + float max_value; + float min_phase; + float max_phase; + uint32_t junk; + + uint32_t junk2; + + uint32_t source_address; + + float offset0; + float offset1; + + float angle0; + float angle1; + + float hide_value; + + ace::vector3<float> direct_axis_pos; + ace::vector3<float> direct_axis_dir; + + float direct_angle; + float direct_axis_offset; + + + std::vector<animate_bone_p> bones; + + //uint32_t null; + //uint32_t floats_count; //always 2 + //float *floats; + + //float transforms[4]; + //float angles[2]; + //float offsets[2]; + //float hide; + + //ace::vector3<float> axis_pos; + //ace::vector3<float> axis_dir; + }; + typedef std::shared_ptr<animation> animation_p; + }; +}; \ No newline at end of file diff --git a/extensions/common/p3d/compressed.cpp b/extensions/common/p3d/compressed.cpp new file mode 100644 index 0000000000..ac9909d039 --- /dev/null +++ b/extensions/common/p3d/compressed.cpp @@ -0,0 +1,237 @@ +#include "compressed.hpp" + +#include <limits.h> +#include <stddef.h> +#include <limits.h> +#include <stddef.h> +#include <string.h> +#include <malloc.h> + +#define COMPRESS_ASSERT(val) if (!(val)) return LZO_E_ERROR +#define M2_MAX_OFFSET 0x0800 + +#define NEED_OP(x) if ((unsigned)(op_end - op) < (unsigned)(x)) return LZO_E_OUTPUT_OVERRUN; +#define TEST_LB() if (m_pos < out || m_pos >= op) return LZO_E_LOOKBEHIND_OVERRUN; + +#define COPY4(dst,src) * (unsigned *)(dst) = * (const unsigned *)(src) + +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_OUTPUT_UNDERRUN (-4) + +namespace ace { + namespace p3d { + /*lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ) */ + int _compressed_base::_decompress_safe(std::istream & in, uint32_t expected_size) { + // We read 512 bytes at a time, until we have hit the end of the compressed stream + uint8_t *buffer; + uint32_t input_size = 0; + int32_t result; + std::streampos save_pos; + + save_pos = in.tellg(); + buffer = new uint8_t[expected_size + 1024]; + + in.read((char *)buffer, expected_size + 1024); + input_size = in.gcount(); + if (in.eof()) { + in.clear(); + } + _data = std::unique_ptr<uint8_t[]>(new uint8_t[expected_size + (expected_size % 8)]); + result = _mikero_lzo1x_decompress_safe(buffer, _data.get(), expected_size); + if (result < 0) { + LOG(ERROR) << "Decompression failed"; + assert(false); + } + in.seekg(save_pos); + in.seekg(result, in.cur); + + delete[] buffer; + + return result; + } + int _compressed_base::_mikero_lzo1x_decompress_safe(const uint8_t* in, uint8_t* out, uint32_t OutLen) { + register uint8_t* op; + register const uint8_t* ip; + register size_t t; + register const uint8_t* m_pos; + + uint8_t* const op_end = out + OutLen; + + OutLen = 0; + op = out; + ip = in; + + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) goto match_next; + COMPRESS_ASSERT(t > 0);// return LZO_E_ERROR; + NEED_OP(t); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + while (1) + { + t = *ip++; + if (t >= 16) goto match; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + } + t += 15 + *ip++; + } + COMPRESS_ASSERT(t > 0); NEED_OP(t + 3); + + COPY4(op, ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + COPY4(op, ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } + + first_literal_run: + + t = *ip++; + if (t >= 16) goto match; + + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; + + TEST_LB(); + NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; + + goto match_done; + + do { + match: + if (t >= 64) + { + + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; + TEST_LB(); COMPRESS_ASSERT(t > 0); NEED_OP(t + 3 - 1); + goto copy_match; + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + } + t += 31 + *ip++; + } + + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); + + ip += 2; + } + else if (t >= 16) + { + + m_pos = op; + m_pos -= (t & 8) << 11; + + t &= 7; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + } + t += 7 + *ip++; + } + + m_pos -= (ip[0] >> 2) + (ip[1] << 6); + + ip += 2; + ////// done + if (m_pos == op) + { + COMPRESS_ASSERT(t == 1); + if (m_pos != op_end) + return LZO_E_LOOKBEHIND_OVERRUN; + return ip - in; + } + m_pos -= 0x4000; + } + else + { + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; + + TEST_LB(); + NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; + goto match_done; + } + + TEST_LB(); + COMPRESS_ASSERT(t > 0); + NEED_OP(t + 3 - 1); + + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { + COPY4(op, m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + COPY4(op, m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else + { + copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + + do *op++ = *m_pos++; while (--t > 0); + + } + match_done: + + t = ip[-2] & 3; + if (t == 0) break; + match_next: + COMPRESS_ASSERT(t > 0); COMPRESS_ASSERT(t < 4); NEED_OP(t); + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + + t = *ip++; + } while (1); + } + // return LZO_E_EOF_NOT_FOUND;/never gets here + + + } + } +} + diff --git a/extensions/common/p3d/compressed.hpp b/extensions/common/p3d/compressed.hpp new file mode 100644 index 0000000000..09113c928f --- /dev/null +++ b/extensions/common/p3d/compressed.hpp @@ -0,0 +1,166 @@ +#pragma once + +#include "shared.hpp" +#include "vector.hpp" + +#include "read_helpers.hpp" + + +namespace ace { + namespace p3d { + class _compressed_base { + protected: + int _mikero_lzo1x_decompress_safe(const uint8_t*, uint8_t*, uint32_t); + int _decompress_safe(std::istream &, uint32_t); + std::unique_ptr<uint8_t[]> _data; + }; + template<typename T> + class compressed_base : public _compressed_base { + public: + compressed_base() : fill(false), size(0), flag(0) {} + + T & operator[] (const int index) { return data[index]; } + + uint32_t size; + bool fill; + std::vector<T> data; + bool flag; + }; + + template<typename T> + class compressed : public compressed_base<T> { + public: + compressed() { } + compressed(std::istream &stream_, bool compressed_ = false, bool fill_ = false, uint32_t version = 68) + { + stream_.read((char *)&size, sizeof(uint32_t)); + + // if(version <) + if(fill_) + READ_BOOL(fill); + + assert(size < 4095 * 10); + if (size > 0) { + if (fill) { + T val; + stream_.read((char *)&val, sizeof(T)); + for (int x = 0; x < size; x++) { + data.push_back(val); + } + } else { + if (version >= 64 && compressed_) { + READ_BOOL(flag); + } + if ( (size * sizeof(T) >= 1024 && compressed_ && version < 64) || (flag && compressed_)) { + int32_t result = _decompress_safe(stream_, size * sizeof(T)); + assert(result > 0); + T * ptr = (T *)(_data.get()); + data.assign(ptr, ptr + size ); + } else { + for (int x = 0; x < size; x++) { + T val; + stream_.read((char *)&val, sizeof(T)); + data.push_back(val); + } + } + } + } + } + }; + + template<> + class compressed<vector3<float>> : public compressed_base<vector3<float>>{ + public: + compressed() {} + compressed(std::istream &stream_, bool compressed_ = false, bool fill_ = false, bool xyzCompressed = false, uint32_t version = 68) { + stream_.read((char *)&size, sizeof(uint32_t)); + + if(fill_) + READ_BOOL(fill); + + if (fill) { + ace::vector3<float> val(stream_); + for (int x = 0; x < size; x++) { + data.push_back(val); + } + } + else { + if (version >= 64) { + READ_BOOL(flag); + } + if ((size * sizeof(float)*3 >= 1024 && compressed_ && version < 64) || (flag && compressed_)) { + if (xyzCompressed) { + int32_t result = _decompress_safe(stream_, size * sizeof(float)); + uint32_t * ptr = (uint32_t *)(_data.get()); + for (int x = 0; x < size; x++) { + uint32_t value = ptr[x]; + data.push_back(decode_xyz(value)); + } + } else { + int32_t result = _decompress_safe(stream_, size * sizeof(float) * 3); + float * ptr = (float *)(_data.get()); + for (int x = 0; x < size*3; x+=3) { + data.push_back(ace::vector3<float>(ptr+x)); + } + } + } else { + for (int x = 0; x < size; x++) { + data.push_back(ace::vector3<float>(stream_)); + } + } + } + } + + ace::vector3<float> decode_xyz(uint32_t CompressedXYZ) + { + double scaleFactor = -1.0 / 511; + + int x = CompressedXYZ & 0x3FF; + int y = (CompressedXYZ >> 10) & 0x3FF; + int z = (CompressedXYZ >> 20) & 0x3FF; + if (x > 511) x -= 1024; + if (y > 511) y -= 1024; + if (z > 511) z -= 1024; + + return ace::vector3<float>(x * scaleFactor, y * scaleFactor, z * scaleFactor); + } + }; + + template<> + class compressed<pair<float>> : public compressed_base<pair<float>>{ + public: + compressed() {} + compressed(std::istream &stream_, bool compressed_ = false, bool fill_ = false, uint32_t version = 68) { + stream_.read((char *)&size, sizeof(uint32_t)); + + if (fill_) + READ_BOOL(fill); + + if (fill) { + ace::pair<float> val(stream_); + for (int x = 0; x < size; x++) { + data.push_back(val); + } + } + else { + if (version >= 64) { + READ_BOOL(flag); + } + if ((size * sizeof(float)*2 >= 1024 && compressed_ && version < 64) || (flag && compressed_)) { + + int32_t result = _decompress_safe(stream_, size * sizeof(float) * 2); + float * ptr = (float *)(_data.get()); + for (int x = 0; x < size * 2; x += 2) { + data.push_back(ace::pair<float>(ptr + x)); + } + } + else { + for (int x = 0; x < size; x++) { + data.push_back(ace::pair<float>(stream_)); + } + } + } + } + }; + } +} \ No newline at end of file diff --git a/extensions/common/p3d/lod_info.cpp b/extensions/common/p3d/lod_info.cpp new file mode 100644 index 0000000000..4b95c853b4 --- /dev/null +++ b/extensions/common/p3d/lod_info.cpp @@ -0,0 +1,289 @@ +#include "lod_info.hpp" + +#include "read_helpers.hpp" + +namespace ace { + namespace p3d { + + + lod::lod() {} + lod::lod(std::istream & stream_, uint32_t id_, uint32_t version = 68) : id(id_) { + uint32_t temp_count; + + // proxies + stream_.read((char *)&temp_count, sizeof(uint32_t)); assert(temp_count < 4096 * 10); + for (int x = 0; x < temp_count; x++) { + proxies.push_back(std::make_shared<proxy>(stream_, version)); + } + LOG(DEBUG) << "Found Proxies:"; + for (auto & proxy : proxies) { + LOG(DEBUG) << "\t" << proxy->name; + } + + compressed<uint32_t> item(stream_, false, false); + items.resize(item.data.size()); + std::copy(item.data.begin(), item.data.end(), items.begin()); + + // bone links + stream_.read((char *)&temp_count, sizeof(uint32_t)); assert(temp_count < 4096 * 10); + for (int x = 0; x < temp_count; x++) { + // @ TODO: BoneLInks + uint32_t link_count; + std::vector<uint32_t> links; + stream_.read((char *)&link_count, sizeof(uint32_t)); + for (int x = 0; x < link_count; x++) { + uint32_t val; + stream_.read((char *)&val, sizeof(uint32_t)); + links.push_back(val); + } + bone_links.push_back(links); + } + + stream_.read((char *)&point_count, sizeof(uint32_t)); + stream_.read((char *)&u_float_1, sizeof(float)); + + // Derp, this was only TOH apparently!? + //point_flags = compressed<uint32_t>(stream_, true, true, version); + + stream_.read((char *)&u_float_2, sizeof(float)); + stream_.read((char *)&u_float_3, sizeof(float)); + + min_pos = ace::vector3<float>(stream_); + max_pos = ace::vector3<float>(stream_); + autocenter_pos = ace::vector3<float>(stream_); + + stream_.read((char *)&sphere, sizeof(float)); + + // Texture strings + stream_.read((char *)&temp_count, sizeof(uint32_t)); + for (int x = 0; x < temp_count; x++) { + std::string temp; + + READ_STRING(temp); + textures.push_back(temp); + LOG(DEBUG) << "Found texture: " << temp << " pos: " << stream_.tellg(); + } + + //Materials + stream_.read((char *)&temp_count, sizeof(uint32_t)); + for (int x = 0; x < temp_count; x++) { + materials.push_back(std::make_shared<material>(stream_, version)); + } + + edges.mlod = compressed<uint16_t>(stream_, true, false, version).data; + edges.vertex = compressed<uint16_t>(stream_, true, false, version).data; + + // @TODO: THIS IS OFF WTF?! + // The first face is coming up null, so we missed something + // Faces magic + stream_.read((char *)&temp_count, sizeof(uint32_t)); + stream_.read((char *)&faces_allocation_size, sizeof(uint32_t)); + + // WTF IS GOING ON!? + stream_.seekg(2, stream_.cur); + + for (int x = 0; x < temp_count; x++) { + faces.push_back(std::make_shared<face>(stream_, version)); + } + + // Sections + stream_.read((char *)&temp_count, sizeof(uint32_t)); + for (int x = 0; x < temp_count; x++) { + sections.push_back(std::make_shared<section>(stream_, version)); + } + + stream_.read((char *)&temp_count, sizeof(uint32_t)); + for (int x = 0; x < temp_count; x++) { + selections.push_back(std::make_shared<named_selection>(stream_, version)); + } + + // named properties + LOG(DEBUG) << "Loaded properties"; + stream_.read((char *)&temp_count, sizeof(uint32_t)); + for (int x = 0; x < temp_count; x++) { + std::string key, value; + READ_STRING(key); + READ_STRING(value); + named_properties[key] = value; + LOG(DEBUG) << "\t\t" << key << "->" << value; + } + + stream_.read((char *)&temp_count, sizeof(uint32_t)); + for (int x = 0; x < temp_count; x++) { + frames.push_back(std::make_shared<frame>(stream_, version)); + } + + stream_.read((char *)&icon_color, sizeof(uint32_t)); + stream_.read((char *)&selected_color, sizeof(uint32_t)); + stream_.read((char *)&u_residue, sizeof(uint32_t)); + stream_.read((char *)&u_byte_1, sizeof(uint8_t)); + stream_.read((char *)&temp_count, sizeof(uint32_t)); + + // Vertex Table starts here + vertices = std::make_shared<c_vertex_table>(stream_, temp_count, version); + } + + lod::~lod() {} + + uv::uv() {} + uv::uv(std::istream &stream_, uint32_t version = 68) { + stream_.read((char *)&uv_scale, sizeof(float) * 4); + data = compressed<float>(stream_, true, true, version); + } + + c_vertex_table::c_vertex_table() {} + c_vertex_table::c_vertex_table(std::istream &stream_, uint32_t size_, uint32_t version = 68) : size(size_) { + uint32_t temp_count; + + point_flags = compressed<uint32_t>(stream_, true, true, version); + + uvsets.push_back(std::make_shared<uv>(stream_, version)); + + // UV optionala additional sets + stream_.read((char *)&temp_count, sizeof(uint32_t)); + for (int x = 0; x < temp_count-1; x++) { + uvsets.push_back(std::make_shared<uv>(stream_, version)); + } + + points = compressed<ace::vector3<float>>(stream_, true, false, false, version); + + size = points.size; + } + + named_selection::named_selection() {} + named_selection::named_selection(std::istream &stream_, uint32_t version = 68) { + uint32_t count; + uint32_t junk; + + READ_STRING(name); + + faces = compressed<uint16_t>(stream_, true, false, version); + + //face_weights = compressed<uint32_t>(stream_, true, false, version); // Face weights + face_weights = compressed<uint32_t>(stream_, true, false, version); + READ_BOOL(is_sectional); + + sections = compressed<uint32_t>(stream_, true, false, version); + vertex_table = compressed<uint16_t>(stream_, true, false, version); + texture_weights = compressed<uint8_t>(stream_, true, false, version); + + //stream_.read((char *)&junk, 4); + } + + + section::section() {} + section::section(std::istream &stream_, uint32_t version = 68) { + stream_.read((char *)&face_offsets, sizeof(uint32_t) * 2); + stream_.read((char *)&material_offsets, sizeof(uint32_t) * 2); + + stream_.read((char *)&common_points_user_value, sizeof(uint32_t)); + stream_.read((char *)&common_texture, sizeof(uint16_t)); + stream_.read((char *)&common_face_flags, sizeof(uint32_t)); + + stream_.read((char *)&material_index, sizeof(int32_t)); + if (material_index == -1) { + stream_.read((char *)&extra, sizeof(uint8_t)); + } + + if(version >= 68) stream_.read((char *)&u_long_2, sizeof(uint32_t)); + stream_.read((char *)&u_long_1, sizeof(uint32_t)); + stream_.read((char *)&u_float_resolution_1, sizeof(float)); + stream_.read((char *)&u_float_resolution_2, sizeof(float)); + } + + face::face() { } + face::face(std::istream & stream_, uint32_t version = 68) { + stream_.read((char *)&type, sizeof(uint8_t)); + assert(type == 3 || type == 4); + for (int x = 0; x < type; x++) { + uint16_t val; + stream_.read((char *)&val, sizeof(uint16_t)); + vertex_table.push_back(val); + } + } + + uint32_t flags; //ODOL7 ONLY see P3D Point and Face Flags + uint16_t texture; //ODOL7 ONLY + uint8_t type; // 3==Triangle or 4==Box + std::vector<uint16_t> vertex_table; + + stage_texture::stage_texture() : file(""), filter(0), transform_id(0) { } + stage_texture::stage_texture(std::istream &stream_, uint32_t type_) { + stream_.read((char *)&filter, sizeof(uint32_t)); + READ_STRING(file); + stream_.read((char *)&transform_id, sizeof(uint32_t)); + if (type_ == 11) { + READ_BOOL(wtf); + } + } + + material::material() { } + material::material(std::istream &stream_, uint32_t version = 68) { + uint32_t textures_count, transforms_count; + + READ_STRING(name); + + stream_.read((char *)&type, sizeof(uint32_t)); + + stream_.read((char *)&emissive, sizeof(float) * 4); + stream_.read((char *)&ambient, sizeof(float) * 4); + stream_.read((char *)&diffuse, sizeof(float) * 4); + stream_.read((char *)&forced_diffuse, sizeof(float) * 4); + stream_.read((char *)&specular, sizeof(float) * 4); + stream_.read((char *)&specular_2, sizeof(float) * 4); + + stream_.read((char *)&specular_power, sizeof(float)); + stream_.read((char *)&pixel_shader, sizeof(uint32_t)); + stream_.read((char *)&vertex_shader, sizeof(uint32_t)); + stream_.read((char *)&u_long_1, sizeof(uint32_t)); + stream_.read((char *)&an_index, sizeof(uint32_t)); + stream_.read((char *)&u_long_2, sizeof(uint32_t)); + + READ_STRING(surface); + + stream_.read((char *)&u_long_3, sizeof(uint32_t)); + stream_.read((char *)&render_flags, sizeof(uint32_t)); + + stream_.read((char *)&textures_count, sizeof(uint32_t)); + stream_.read((char *)&transforms_count, sizeof(uint32_t)); + + for (int x = 0; x < textures_count; x++) { + texture_stages.push_back(std::make_shared<stage_texture>(stream_, type)); + } + + for (int x = 0; x < textures_count; x++) { + uint32_t uv_source; + stream_.read((char *)&uv_source, sizeof(uint32_t)); + transform_stages.push_back(std::pair<uint32_t, transform_matrix>(uv_source, transform_matrix(stream_))); + } + if (type >= 10) { + texture_stages.push_back(std::make_shared<stage_texture>(stream_, type)); + } + } + + frame::frame() {} + frame::frame(std::istream &stream_, uint32_t version = 68) { + uint32_t count; + + stream_.read((char *)&time, sizeof(float)); + + stream_.read((char *)&count, sizeof(uint32_t)); + for (int x = 0; x < count; x++) { + bone_positions.push_back(ace::vector3<float>(stream_)); + } + } + + proxy::proxy() { } + proxy::proxy(std::istream &stream_, uint32_t version = 68) { + READ_STRING(name); + transform = ace::transform_matrix(stream_); + stream_.read((char *)&sequence_id, sizeof(uint32_t)); + stream_.read((char *)&named_selection_id, sizeof(uint32_t)); + stream_.read((char *)&bone_id, sizeof(uint32_t)); + stream_.read((char *)§ion_id, sizeof(uint32_t)); + + LOG(DEBUG) << "Proxy: [" << name << "]"; + + } + } +} \ No newline at end of file diff --git a/extensions/common/p3d/lod_info.hpp b/extensions/common/p3d/lod_info.hpp new file mode 100644 index 0000000000..e36922f253 --- /dev/null +++ b/extensions/common/p3d/lod_info.hpp @@ -0,0 +1,237 @@ +#pragma once + +#include "shared.hpp" + +#include "vector.hpp" +#include "transform_matrix.hpp" +#include "compressed.hpp" + +namespace ace { + namespace p3d { + + class proxy { + public: + proxy(); + proxy(std::istream &, uint32_t); + + std::string name; //"\ca\a10\agm65" (.p3d is implied) <<note the leading filename backslash + ace::transform_matrix transform; //see Generic FileFormat Data Types + uint32_t sequence_id; // + uint32_t named_selection_id; //see P3D Named Selections + //////// ARMA ONLY (ODOLV4x) /////// + int32_t bone_id; + uint32_t section_id; //see P3D_Lod_Sections + }; + typedef std::shared_ptr<proxy> proxy_p; + + class stage_texture { + public: + stage_texture(); + stage_texture(std::istream &, uint32_t); + + uint32_t filter; + std::string file; + uint32_t transform_id; + bool wtf; + }; + typedef std::shared_ptr<stage_texture> stage_texture_p; + + class material { + public: + material(); + material(std::istream &, uint32_t); + + std::string name; + std::string surface; + + uint32_t render_flags; + uint32_t type; + + float emissive[4]; + float ambient[4]; + float diffuse[4]; + float forced_diffuse[4]; + float specular[4]; + float specular_2[4]; + float specular_power; + + uint32_t pixel_shader; + uint32_t vertex_shader; + + uint32_t u_long_1; + uint32_t an_index; + uint32_t u_long_2; + uint32_t u_long_3; + + std::vector<stage_texture_p> texture_stages; + std::vector<std::pair<uint32_t, transform_matrix>> transform_stages; + }; + typedef std::shared_ptr<material> material_p; + + class edge_set { + public: + std::vector<uint16_t> mlod; + std::vector<uint16_t> vertex; + }; + + class face { + public: + face(); + face(std::istream &, uint32_t); + + uint32_t flags; //ODOL7 ONLY see P3D Point and Face Flags + uint16_t texture; //ODOL7 ONLY + uint8_t type; // 3==Triangle or 4==Box + std::vector<uint16_t> vertex_table; + }; + typedef std::shared_ptr<face> face_p; + + class section { + public: + section(); + section(std::istream &, uint32_t); + + uint32_t face_offsets[2]; // from / to region of LodFaces used + uint32_t material_offsets[2]; // ODOLV4x only + uint32_t common_points_user_value; // see P3D Point and Face Flags + // 0xC9 -> LodPoints 0x0C90003F + // LodPointFlags are in a separate table for arma, and in the VertexTable for ofp (odol7) + uint16_t common_texture; // + uint32_t common_face_flags; // see P3D Point and Face Flags + ///////// // ODOLV4x only////// + int32_t material_index; + //if MaterialIndex == -1 + // { + // byte ExtraByte; + //} + uint8_t extra; + uint32_t u_long_1; // ???? New in version 68!!! + uint32_t u_long_2; // generally 2 + float u_float_resolution_1; + float u_float_resolution_2; // generally 1000.0 + }; + typedef std::shared_ptr<section> section_p; + + class named_selection { + public: + named_selection(); + named_selection(std::istream &, uint32_t); + + std::string name; // "rightleg" or "neck" eg + compressed<uint16_t> faces; // indexing into the LodFaces Table + compressed<uint32_t> face_weights; + uint32_t Always0Count; + bool is_sectional; //Appears in the sections[]= list of a model.cfg + compressed<uint32_t> sections; //IsSectional must be true. Indexes into the LodSections Table + compressed<uint16_t> vertex_table; + compressed<uint8_t> texture_weights; // if present they correspond to (are exentsions of) the VertexTableIndexes + }; + typedef std::shared_ptr<named_selection> named_selection_p; + + class frame { + public: + frame(); + frame(std::istream &, uint32_t); + + float time; + std::vector<ace::vector3<float>> bone_positions; + }; + typedef std::shared_ptr<frame> frame_p; + + class uv { + public: + uv(); + uv(std::istream &, uint32_t); + + float uv_scale[4]; + compressed<float> data; + }; + typedef std::shared_ptr<uv> uv_p; + + class c_vertex_table { + public: + c_vertex_table(); + c_vertex_table(std::istream &, uint32_t, uint32_t); + + uint32_t size; + + compressed<uint32_t> point_flags; // Potentially compressed + std::vector<uv_p> uvsets; + + compressed<ace::vector3<float>> points; + compressed<ace::vector3<float>> normals; + compressed<ace::pair<float>> minmax; + compressed<ace::vector3<float>> vert_properties; + compressed<ace::vector3<float>> unknown_vtx; + /* + uint32_t NoOfPoints; + + uint32_t nNormals; + (A2)LodNormals LodNormals[nNormals]; + uint32_t nMinMax; + (A2)LodMinMax MinMax[nMinMax]; //optional + uint32_t nProperties; + VertProperty VertProperties[nProperties]; //optional related to skeleton + uint32_t Count; + UnknownVtxStruct UnknownVtxStructs[Count]; //optional + */ + + }; + typedef std::shared_ptr<c_vertex_table> vertex_table_p; + + class lod { + public: + lod(); + lod(std::istream &, uint32_t, uint32_t); + ~lod(); + + uint32_t id; + + std::vector<proxy_p> proxies; // see P3D Lod Proxies + std::vector<uint32_t> items; // potentially compressed + std::vector<std::vector<uint32_t>> bone_links; + uint32_t point_count; + uint32_t u_float_1; + + float u_float_2; + float u_float_3; + ace::vector3<float> min_pos; + ace::vector3<float> max_pos; + ace::vector3<float> autocenter_pos; + float sphere; // same as geo or mem values in modelinfo, if this lod is geo or memlod of course + std::vector<std::string> textures; //"ca\characters\hhl\hhl_01_co.paa" + std::vector<material_p> materials; + + edge_set edges; + + uint32_t u_count; + uint32_t offset_sections; // see below + uint16_t u_short_1; + + uint32_t faces_allocation_size; + std::vector<face_p> faces; + std::vector<section_p> sections; + + std::vector<named_selection_p> selections; + + std::map<std::string, std::string> named_properties; + + std::vector<frame_p> frames; + + uint32_t icon_color; + uint32_t selected_color; + uint32_t u_residue; + uint8_t u_byte_1; + uint32_t vertex_table_size; + + vertex_table_p vertices; + + /* + //(including these 4 bytes) + LodPointFlags LodPointFlags; // Potentially compressed + VertexTable VertexTable;*/ + }; + typedef std::shared_ptr<lod> lod_p; + + } +} diff --git a/extensions/common/p3d/lod_types.hpp b/extensions/common/p3d/lod_types.hpp new file mode 100644 index 0000000000..8f8bf05202 --- /dev/null +++ b/extensions/common/p3d/lod_types.hpp @@ -0,0 +1,33 @@ +#pragma once + +enum lod_types { + LOD_TYPE_VIEWGUNNER = 0x447a0000, //1.0e3 1,000 View Gunner + LOD_TYPE_VIEWPILOT = 0x44898000, //1.1e3 1,100 View Pilot + LOD_TYPE_VIEWCARGO = 0x44960000, //1.2e3 1,200 View Cargo + LOD_TYPE_SHADOWSTENCILE = 0x461c4000, //1.0e4 10,000 Stencil Shadow + LOD_TYPE_SHADOWSTENCILE_2 = 0x461c6800,// 1.001e4 10, 010 Stencil Shadow 2 + LOD_TYPE_SHADOWVOLUME = 0x462be000,// 1.1e4 11000 Shadow Volume + LOD_TYPE_SHADOWVOLUME_2 = 0x462c0800,// 1.101e4 11010 Shadow Volume 2 + LOD_TYPE_GEOMETRY = 0x551184e7, // 1.0e13 10, 000, 000, 000, 000 Geometry + LOD_TYPE_MEMORY = 0x58635fa9, // 1.0e15 1, 000, 000, 000, 000, 000 Memory + LOD_TYPE_LANDCONTACT = 0x58e35fa9, // 2.0e15 2, 000, 000, 000, 000, 000 Land Contact + LOD_TYPE_ROADWAY = 0x592a87bf, // 3.0e15 3, 000, 000, 000, 000, 000 Roadway + LOD_TYPE_PATHS = 0x59635fa9, // 4.0e15 4, 000, 000, 000, 000, 000 Paths + LOD_TYPE_HITPOINTS = 0x598e1bca, // 5.0e15 5, 000, 000, 000, 000, 000 HitPoints + LOD_TYPE_GEOMETRY_VIEW = 0x59aa87bf, // 6.0e15 6, 000, 000, 000, 000, 000 View Geometry + LOD_TYPE_GEOMETRY_FIRE = 0x59c6f3b4, // 7.0e15 7, 000, 000, 000, 000, 000 Fire Geometry + LOD_TYPE_GEOMETRY_VIEWCARGO = 0x59e35fa9, // 8.0e15 8, 000, 000, 000, 000, 000 View Cargo Geometry + LOD_TYPE_GEOMETRY_VIEWCARGO_FIRE = 0x59ffcb9e, // 9.0e15 9, 000, 000, 000, 000, 000 View Cargo Fire Geometry + LOD_TYPE_VIEWCOMMANDER = 0x5a0e1bca, // 1.0e16 10, 000, 000, 000, 000, 000 View Commander + LOD_TYPE_GEOMETRY_VIEWCOMMANDER = 0x5a1c51c4, // 1.1e16 11, 000, 000, 000, 000, 000 View Commander Geometry + LOD_TYPE_GEOMETRY_VIEWCOMMANDER_FIRE = 0x5a2a87bf, // 1.2e16 12, 000, 000, 000, 000, 000 View Commander Fire Geometry + LOD_TYPE_VIEWPILOT_GEOMETRY = 0x5a38bdb9, // 1.3e16 13, 000, 000, 000, 000, 000 View Pilot Geometry + LOD_TYPE_GEOMETRY_VIEWPILOT_FIRE = 0x5a46f3b4, // 1.4e16 14, 000, 000, 000, 000, 000 View Pilot Fire Geometry + LOD_TYPE_VIEWGUNNER_GEOMETRY = 0x5a5529af, // 1.5e16 15, 000, 000, 000, 000, 000 View Gunner Geometry + LOD_TYPE_GEOMETRY_VIEWGUNNER_FIRE = 0x5a635fa9, // 1.6e16 16, 000, 000, 000, 000, 000 View Gunner Fire Geometry + LOD_TYPE_SUBPARTS = 0x5a7195a4, // 1.7e16 17, 000, 000, 000, 000, 000 Sub Parts + LOD_TYPE_SHADOWVOLUME_VIEWCARGO = 0x5a7fcb9e, // 1.8e16 18, 000, 000, 000, 000, 000 SHADOW_VOLUME_VIEW_CARGO + LOD_TYPE_SHADOWVOLUME_VIEWPILOT = 0x5a8700cc, // 1.9e16 19, 000, 000, 000, 000, 000 SHADOW_VOLUME_VIEW_PILOT + LOD_TYPE_SHADOWVOLUME_VIEWGUNNER = 0x5a8e1bca, // 2.0e16 20, 000, 000, 000, 000, 000 SHADOW_VOLUME_VIEW_GUNNER + LOD_TYPE_WRECK = 0x5a9536c7 // 2.1e16 21, 000, 000, 000, 000, 000 WRECK +}; \ No newline at end of file diff --git a/extensions/common/p3d/model.cpp b/extensions/common/p3d/model.cpp new file mode 100644 index 0000000000..ffc909ca10 --- /dev/null +++ b/extensions/common/p3d/model.cpp @@ -0,0 +1,116 @@ +#include "p3d/model.hpp" + +#include "read_helpers.hpp" + +namespace ace { + namespace p3d { + model::model() : skeleton(nullptr), info(nullptr), useFaceDefaults(nullptr) {} + model::model(std::istream &stream_, const std::string &filename_) { + filename = filename_; + + // get the full file size + stream_.seekg(0, std::ios::end); + size = stream_.tellg(); + stream_.seekg(0, std::ios::beg); + + // Parse header here + stream_.read((char *)&filetype, sizeof(uint32_t)); + stream_.read((char *)&version, sizeof(uint64_t)); + if (version >= 48) { + READ_STRING(prefix_name); + } + + stream_.read((char *)&lod_count, sizeof(uint32_t)); + + // parse model info here + info = std::make_shared<model_info>(stream_, lod_count); + skeleton = info->skeleton; + + READ_BOOL(has_animations); + if (has_animations) { + uint32_t animation_count = 0; + stream_.read((char *)&animation_count, sizeof(uint32_t)); + for (int x = 0; x < animation_count; x++) { + animations.push_back(std::make_shared<animation>(stream_, version)); + } + + + // Now we re-walk, and association animations and bones + uint32_t bone_count, local_lod_count; + stream_.read((char *)&local_lod_count, sizeof(uint32_t)); + for (int lod = 0; lod < local_lod_count; lod++) { + stream_.read((char *)&bone_count, sizeof(uint32_t)); + std::vector<uint32_t> lod_bone2anim; + for (int x = 0; x < bone_count; x++) { + uint32_t anim_count; + stream_.read((char *)&anim_count, sizeof(uint32_t)); + + for (int anim = 0; anim < anim_count; anim++) { + uint32_t anim_index; + stream_.read((char *)&anim_index, sizeof(uint32_t)); + if(std::find(skeleton->all_bones[x]->animations.begin(), skeleton->all_bones[x]->animations.end(), anim_index) == skeleton->all_bones[x]->animations.end()) { + skeleton->all_bones[x]->animations.push_back(anim_index); + } + }; + } + } + + // Anims2Bones + for (int lod = 0; lod < lod_count; lod++) { + for (animation_p & anim : animations) { + animate_bone_p next = std::make_shared<animate_bone>(); + next->lod = lod; + stream_.read((char *)&next->index, sizeof(int32_t)); + if (next->index != -1 && anim->type != 8 && anim->type != 9) { + next->axis_position = ace::vector3<float>(stream_); + next->axis_direction = ace::vector3<float>(stream_); + } + anim->bones.push_back(next); + } + } + } + // LOD indexes + for (int lod = 0; lod < lod_count; lod++) { + uint32_t offset; + stream_.read((char *)&offset, sizeof(uint32_t)); + start_lod.push_back(offset); + LOG(DEBUG) << "LOD Offset: #" << lod << " : " << offset; + } + for (int lod = 0; lod < lod_count; lod++) { + uint32_t offset; + stream_.read((char *)&offset, sizeof(uint32_t)); + end_lod.push_back(offset); + LOG(DEBUG) << "LOD Offset: #" << lod << " : " << offset; + } + + // Attempt to read the faces? + useFaceDefaults = new bool[lod_count]; + for (int lod = 0; lod < lod_count; lod++) { + READ_BOOL(useFaceDefaults[lod]); + } + for (int x = 0; x < lod_count; x++) { + if (!useFaceDefaults[x]) { + face_settings tface(stream_); // @TODO: we dont save these because WHY!? + } + } + + for (int lod = 0; lod < lod_count; lod++) { + char buffer[64]; + #ifdef _DEBUG + sprintf_s(buffer, "\t\t%08X", info->resolutions[lod]); + LOG(DEBUG) << "LOD #" << lod << ", type: " << buffer; + #endif + //if (info->resolutions[lod] == LOD_TYPE_GEOMETRY_FIRE) { + // LOG(DEBUG) << "Found a desired geometry"; + stream_.clear(); + stream_.seekg(start_lod[lod], stream_.beg); + lods.push_back(std::make_shared<ace::p3d::lod>(stream_, lod, version)); + //} + } + } + model::~model() { + if(useFaceDefaults) + delete[] useFaceDefaults; + } + } +} diff --git a/extensions/common/p3d/model.hpp b/extensions/common/p3d/model.hpp new file mode 100644 index 0000000000..bd3cafe60c --- /dev/null +++ b/extensions/common/p3d/model.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include "shared.hpp" + +#include "animation.hpp" +#include "skeleton.hpp" +#include "model_info.hpp" +#include "lod_info.hpp" + +namespace ace { + namespace p3d { + class face_settings { + public: + face_settings() {} + face_settings(std::istream &stream_, uint32_t version = 68) { + stream_.read((char *)&count, sizeof(uint32_t)); + stream_.read((char *)&unknown, sizeof(uint8_t) * 21); + } + + uint32_t count; + uint8_t unknown[21]; + }; + typedef std::shared_ptr<face_settings> face_settings_p; + + class model { + public: + model(); + model(std::istream &, const std::string &filename_ = ""); + ~model(); + + // LOD info + bool *useFaceDefaults; + std::vector<face> defaultFaces; + std::vector<lod_p> lods; + + size_t size; + model_info_p info; + skeleton_p skeleton; + + bool has_animations; + std::vector<animation_p> animations; + + + std::vector<uint32_t> start_lod; + std::vector<uint32_t> end_lod; + + // data root fileds + std::string filename; + uint32_t lod_count; + uint32_t filetype; + uint64_t version; + std::string prefix_name; + + }; + typedef std::shared_ptr<model> model_p; + }; +}; \ No newline at end of file diff --git a/extensions/common/p3d/model_info.cpp b/extensions/common/p3d/model_info.cpp new file mode 100644 index 0000000000..c373907a9a --- /dev/null +++ b/extensions/common/p3d/model_info.cpp @@ -0,0 +1,91 @@ +#include "p3d/model_info.hpp" +#include "compressed.hpp" +#include "read_helpers.hpp" + +namespace ace { + namespace p3d { + model_info::model_info() : + raw_resolutions(nullptr), u_floats_1(nullptr), default_indicators(nullptr) + { } + + model_info::model_info(std::istream & stream_, const uint32_t lod_count, uint32_t version) + : raw_resolutions(nullptr), u_floats_1(nullptr), default_indicators(nullptr) { + + raw_resolutions = new float[lod_count]; + stream_.read((char *)raw_resolutions, sizeof(float) * lod_count); + // Get them to parsable int values + for (int x = 0; x < lod_count; x++) { + resolutions.push_back(*(int *)&raw_resolutions[x]); + } + + stream_.read((char *)&index, sizeof(uint32_t)); + stream_.read((char *)&lod_sphere_mem, sizeof(float)); + stream_.read((char *)&lod_sphere_geo, sizeof(float)); + stream_.read((char *)&point_flags, sizeof(uint32_t) * 3); + + offset_1 = ace::vector3<float>(stream_); + + stream_.read((char *)&map_icon_color, sizeof(uint32_t)); + stream_.read((char *)&map_selected_color, sizeof(uint32_t)); + stream_.read((char *)&view_density, sizeof(float)); + + bbox_min_pos = ace::vector3<float>(stream_); + bbox_max_pos = ace::vector3<float>(stream_); + + center_of_gravity = ace::vector3<float>(stream_); + offset_2 = ace::vector3<float>(stream_); + cog_offset = ace::vector3<float>(stream_); + + mass_vectors[0] = ace::vector3<float>(stream_); + mass_vectors[1] = ace::vector3<float>(stream_); + mass_vectors[2] = ace::vector3<float>(stream_); + + stream_.read((char *)&thermal_profile_2, sizeof(uint8_t) * 24); + + READ_BOOL(autocenter); + READ_BOOL(lock_autocenter); + READ_BOOL(allow_occlude); + READ_BOOL(allow_occluded); + READ_BOOL(allow_animation); + + stream_.read((char *)&u_bytes_1, sizeof(uint8_t) * 6); + stream_.read((char *)&thermal_profile, sizeof(uint8_t) * 24); + stream_.read((char *)&u_long_1, sizeof(uint32_t)); + + // Parse the full skeletal structure + skeleton = std::make_shared<ace::p3d::skeleton>(stream_, lod_count); + + stream_.read((char *)&u_byte_1, sizeof(uint8_t)); + + compressed<float> u_floats_1(stream_, true, false, version); + + stream_.read((char *)&mass, sizeof(float)); + stream_.read((char *)&mass_reciprocal, sizeof(float)); + stream_.read((char *)&mass_alt, sizeof(float)); + stream_.read((char *)&mass_alt_reciprocoal, sizeof(float)); + + stream_.read((char *)&u_bytes_1, sizeof(uint8_t) * 14); + + // + stream_.read((char *)&u_long_1, sizeof(uint32_t)); + READ_BOOL(u_bool_1); + //if (u_bool_1) { + + READ_STRING(class_type); + READ_STRING(destruct_type); + READ_BOOL(u_bool_2); + stream_.read((char *)&u_long_2, sizeof(uint32_t)); + + stream_.seekg(sizeof(uint8_t) * 12 * lod_count, stream_.cur); + } + + model_info::~model_info() { + if (raw_resolutions) + delete[] raw_resolutions; + if (u_floats_1) + delete[] u_floats_1; + if (default_indicators) + delete[] default_indicators; + } + } +} diff --git a/extensions/common/p3d/model_info.hpp b/extensions/common/p3d/model_info.hpp new file mode 100644 index 0000000000..195e925a5a --- /dev/null +++ b/extensions/common/p3d/model_info.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include "shared.hpp" +#include "vector.hpp" +#include "skeleton.hpp" +#include "lod_types.hpp" +#include <sstream> + +namespace ace { + namespace p3d { + class model_info { + public: + model_info(); + model_info(std::istream &, const uint32_t lod_count, uint32_t version = 68); + ~model_info(); + + + public: + std::vector<int> resolutions; + float *raw_resolutions;//LodTypes[Header.NoOfLods];// alias resolutions + uint32_t index; // appears to be a bit flag, 512, 256 eg + float lod_sphere_mem; + float lod_sphere_geo; // mostly same as MemLodSphere + uint32_t point_flags[3]; // typically 00 00 00 00 00 00 00 00 00 00 0C 00 eg (last is same as user point flags) + ace::vector3<float> offset_1; // model offset (unknown functionality),//mostly same as offset2 + uint32_t map_icon_color; // RGBA 32 color + uint32_t map_selected_color; // RGBA 32 color + float view_density; // + + ace::vector3<float> bbox_min_pos; // minimum coordinates of bounding box + ace::vector3<float> bbox_max_pos; // maximum coordinates of bounding box. Generally the complement of the 1st + // pew.GeometryBounds in Pew is bboxMinPosition-bboxMaxPosition for X and Z + // pew.ResolutionBounds mostly the same + ace::vector3<float> center_of_gravity; // pew.GeometryAutoCenterPos (and mostly pew.ResolutionAutoCenterPos too) + ace::vector3<float> offset_2; // mostly same as Offset1 often same as CentreOfGravity (but it isn't ResolutionPos) + ace::vector3<float> cog_offset; // see below + ace::vector3<float> mass_vectors[3]; // for ODOL7 this is a mixture of floats and index values + //// if Arma3 ///////////////// + uint8_t thermal_profile_2[24]; + /////////////////////////////// + bool autocenter; + bool lock_autocenter; + bool allow_occlude; + bool allow_occluded; + bool allow_animation; + ///////////ARMA/VBS2 //////////// + uint8_t u_bytes_1[6]; // + uint8_t thermal_profile[24]; // + uint32_t u_long_1; // V48 and beyond + //uint8_t thermal_profile[24]; // TOH only (v52) see above for arma3 + + skeleton_p skeleton; // + + uint8_t u_byte_1; + uint32_t u_floats_1_size; // always zero for arma + float *u_floats_1; // potentially compressed + float mass; + float mass_reciprocal; // see note + float mass_alt; // see note + float mass_alt_reciprocoal; // see note + uint8_t u_bytes_2[14]; // see note generally FF FF FF FF FF FF FF FF FF FF FF FF + uint8_t u_short_1; // often same as NoOfLods + bool u_bool_1; // generally set if ascii below has strings + std::string class_type; // asciiz ClassType; // class="House" See Named Properties + std::string destruct_type; //DestructType; // damage="Tent" See Named Properties + bool u_bool_2; // rarely true + bool u_bool_3; // rarely true + uint32_t u_long_2; // + uint8_t *default_indicators;//default_indicators[NoOfLods][12]; //generally FF FF FF FF FF FF FF FF FF FF FF FF + }; + typedef std::shared_ptr<model_info> model_info_p; + + }; +}; \ No newline at end of file diff --git a/extensions/common/p3d/parser.cpp b/extensions/common/p3d/parser.cpp new file mode 100644 index 0000000000..4eb11cb4b4 --- /dev/null +++ b/extensions/common/p3d/parser.cpp @@ -0,0 +1,26 @@ +#pragma once + +#include "p3d/parser.hpp" + +namespace ace { + namespace p3d { + parser::parser() { } + parser::~parser() { } + + model_p parser::load(const std::string &filepath) { + std::fstream filestream; + model_p _model = nullptr; + + filestream.open(filepath, std::ios::binary | std::ios::in); + if (!filestream.good()) { + LOG(ERROR) << "Cannot open file"; + return _model; + } + + _model = std::make_shared<model>(filestream, filepath); + + return _model; + } + } +} + diff --git a/extensions/common/p3d/parser.hpp b/extensions/common/p3d/parser.hpp new file mode 100644 index 0000000000..b3f584a017 --- /dev/null +++ b/extensions/common/p3d/parser.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "shared.hpp" +#include "p3d/model.hpp" + + +namespace ace { + namespace p3d { + class parser { + public: + parser(); + ~parser(); + + model_p load(const std::string &); + }; + }; +}; \ No newline at end of file diff --git a/extensions/common/p3d/parser_ref.txt b/extensions/common/p3d/parser_ref.txt new file mode 100644 index 0000000000..b2cd38f575 --- /dev/null +++ b/extensions/common/p3d/parser_ref.txt @@ -0,0 +1,269 @@ +#pragma once + +#include "ace_common.h" +#include "p3d/parser.hpp" +#include "p3d/model.hpp" + +#include <fstream> + +#include <lzo/minilzo.h> + +namespace ace { + namespace p3d { + + parser::parser() {} + parser::~parser() {} + + model * parser::load(const std::string filepath) { + std::ifstream ifstream; + model *_model = new model(); + size_t index = 4; + + _model->filepath = filepath; + + ifstream.open(filepath, std::ios::binary); + if (!ifstream.good()) { + printf("! File not found\n"); + return false; + } + // get length of file: + ifstream.seekg(0, std::ios::end); + _model->size = ifstream.tellg(); + ifstream.seekg(0, std::ios::beg); + + // Read the whole file into memory real fast + _model->raw = new unsigned char[_model->size]; + ifstream.read((char *)_model->raw, _model->size); + + // use the ifstream to read the data + ifstream.seekg(0, std::ios::beg); + + ifstream.read((char *)&_model->header.filetype, 4); + ifstream.read((char *)&_model->header.version, sizeof(uint64_t)); + + // If version > 48, it may have a path or a empty null byte. + if (_model->header.version >= 48) { + for (int x = 0; x < sizeof(_model->header.prefix); x++) { + char byte; + ifstream.read(&byte, 1); + _model->header.prefix[x] = byte; + if (byte == 0x00) break; + } + } + + ifstream.read((char *)&_model->header.lod_count, sizeof(uint32_t)); + + printf("Version: %d\n", _model->header.version); + printf("%s\n", _model->header.prefix); + printf("\tLODs:\t%d\n", (long long)_model->header.lod_count); +#ifdef _DEBUG +#define READ_DATA(stream, output, size) stream.read((char *)&output, size); +#else +#define READ_DATA(stream, output, size) stream.read((char *)&output, size); +#endif +#define PRINT_INDEX { std::streamoff pos = ifstream.tellg(); printf("Current Index: %08x\n", pos); } + + // Begin model info + READ_DATA(ifstream, _model->info.LodResolutions, sizeof(float)*_model->header.lod_count); + READ_DATA(ifstream, _model->info.Index, sizeof(uint32_t)); + READ_DATA(ifstream, _model->info.MemLodSphere, sizeof(float)); + READ_DATA(ifstream, _model->info.GeoLodSphere, sizeof(float)); + READ_DATA(ifstream, _model->info.PointFlags, sizeof(uint32_t)*3); + READ_DATA(ifstream, _model->info.Offset1, sizeof(XYZTriplet)); + + READ_DATA(ifstream, _model->info.mapIconColor, sizeof(uint32_t)); + READ_DATA(ifstream, _model->info.mapSelectedColor, sizeof(uint32_t)); + READ_DATA(ifstream, _model->info.ViewDensity, sizeof(float)); + + READ_DATA(ifstream, _model->info.bboxMinPosition, sizeof(XYZTriplet)); + READ_DATA(ifstream, _model->info.bboxMaxPosition, sizeof(XYZTriplet)); + READ_DATA(ifstream, _model->info.CentreOfGravity, sizeof(XYZTriplet)); + READ_DATA(ifstream, _model->info.Offset2, sizeof(XYZTriplet)); + READ_DATA(ifstream, _model->info.CogOffset, sizeof(XYZTriplet)); + READ_DATA(ifstream, _model->info.ModelMassVectors, sizeof(XYZTriplet)*3); + + READ_DATA(ifstream, _model->info.ThermalProfile2, sizeof(uint8_t)*24); + + READ_DATA(ifstream, _model->info.AutoCenter, sizeof(uint8_t)); + READ_DATA(ifstream, _model->info.lockAutoCenter, sizeof(uint8_t)); + READ_DATA(ifstream, _model->info.canOcclude, sizeof(uint8_t)); + READ_DATA(ifstream, _model->info.canBeOccluded, sizeof(uint8_t)); + READ_DATA(ifstream, _model->info.allowAnimation, sizeof(uint8_t)); + + READ_DATA(ifstream, _model->info.UnknownARMAFlags, sizeof(uint8_t) * 6); + READ_DATA(ifstream, _model->info.ThermalProfile, sizeof(uint8_t) * 24); + READ_DATA(ifstream, _model->info.UnknownLong, sizeof(uint32_t)); + + // Skeleton! + for (int x = 0; x < sizeof(_model->info.Skeleton); x++) { + char byte; + ifstream.read(&byte, 1); + _model->info.Skeleton.name[x] = byte; + if (byte == 0x00) break; + } + if (_model->info.Skeleton.name[0] != 0x00) { + READ_DATA(ifstream, _model->info.Skeleton.isInherited, sizeof(uint8_t)); + READ_DATA(ifstream, _model->info.Skeleton.bone_count, sizeof(uint32_t)); + for (int x = 0; x < 256 && x < _model->info.Skeleton.bone_count; x++) { + for (int y = 0; y < sizeof(_model->info.Skeleton.bone_names[x].BoneName); y++) { + char byte; + ifstream.read(&byte, 1); + _model->info.Skeleton.bone_names[x].BoneName[y] = byte; + if (byte == 0x00) break; + } + for (int y = 0; y < sizeof(_model->info.Skeleton.bone_names[x].ParentBoneName); y++) { + char byte; + ifstream.read(&byte, 1); + _model->info.Skeleton.bone_names[x].ParentBoneName[y] = byte; + if (byte == 0x00) break; + } + printf("Read bone entry: %s -> Parent:%s\n", _model->info.Skeleton.bone_names[x].BoneName, _model->info.Skeleton.bone_names[x].ParentBoneName); + } + } + + READ_DATA(ifstream, _model->info.UnknownByte, sizeof(uint8_t)); + READ_DATA(ifstream, _model->info.nFloats, sizeof(uint32_t)); + + printf("Floats: %d\n", _model->info.nFloats); + if (_model->info.nFloats * sizeof(float) > 1024) { + // TODO!: Read compressed segment + } else { + ifstream.seekg(_model->info.nFloats*sizeof(float), ifstream.cur); + //READ_DATA(ifstream, _model->info.UnknownFloats, ); + } + + READ_DATA(ifstream, _model->info.Mass, sizeof(float)); + READ_DATA(ifstream, _model->info.MassReciprocal, sizeof(float)); + READ_DATA(ifstream, _model->info.AltMass, sizeof(float)); + READ_DATA(ifstream, _model->info.AltMassReciprocal, sizeof(float)); + + READ_DATA(ifstream, _model->info.UnknownByteIndices, sizeof(uint8_t) * 14); + READ_DATA(ifstream, _model->info.UnknownShort, sizeof(uint16_t)); + READ_DATA(ifstream, _model->info.UnknownLodCount, sizeof(uint32_t)); + READ_DATA(ifstream, _model->info.UnknownBool, sizeof(uint8_t)); + /* + for (int x = 0; x < sizeof(_model->info.ClassType); x++) { + char byte; + ifstream.read(&byte, 1); + _model->info.ClassType[x] = byte; + if (byte == 0x00 || byte == 0xff) break; + } + for (int x = 0; x < sizeof(_model->info.DestructType); x++) { + char byte; + ifstream.read(&byte, 1); + _model->info.DestructType[x] = byte; + if (byte == 0x00 || byte == 0xff) break; + }*/ + + READ_DATA(ifstream, _model->info.UnknownBool2, sizeof(uint8_t)); + READ_DATA(ifstream, _model->info.Always0, sizeof(uint8_t)); + for (int x = 0; x < sizeof(_model->header.lod_count); x++) { + READ_DATA(ifstream, _model->info.DefaultIndicators[x], sizeof(uint8_t)*12); + } + + // Read ahead because i dont understand whats going on + for (int x = 0; x < _model->size; x++) { + char byte; + ifstream.read(&byte, 1); + if (byte != -1) { + ifstream.seekg(-1, ifstream.cur); + break; + }; + } + + READ_DATA(ifstream, _model->animations.AnimsExist, sizeof(uint8_t)); + if (_model->animations.AnimsExist) { + READ_DATA(ifstream, _model->animations.nAnimationClasses, sizeof(uint32_t)); + printf("Animations: %d", _model->animations.nAnimationClasses); + + for (int n = 0; n < _model->animations.nAnimationClasses; n++) { + READ_DATA(ifstream, _model->animations.AnimationClasses[n].AnimTransformType, sizeof(uint32_t)); + + for (int x = 0; x < sizeof(_model->animations.AnimationClasses[n].AnimClassName); x++) { + char byte; + ifstream.read(&byte, 1); + _model->animations.AnimationClasses[n].AnimClassName[x] = byte; + if (byte == 0x00) break; + } + for (int x = 0; x < sizeof(_model->animations.AnimationClasses[n].AnimSource); x++) { + char byte; + ifstream.read(&byte, 1); + _model->animations.AnimationClasses[n].AnimSource[x] = byte; + if (byte == 0x00) break; + } + + printf("Reading animation: [%08x]-[%s]-%s\n", _model->animations.AnimationClasses[n].AnimTransformType, _model->animations.AnimationClasses[n].AnimClassName, _model->animations.AnimationClasses[n].AnimSource); + + READ_DATA(ifstream, _model->animations.AnimationClasses[n].MinMaxValue, sizeof(float) * 2); + READ_DATA(ifstream, _model->animations.AnimationClasses[n].MinMaxPhase, sizeof(float) * 2); + READ_DATA(ifstream, _model->animations.AnimationClasses[n].sourceAddress, sizeof(uint32_t)); + READ_DATA(ifstream, _model->animations.AnimationClasses[n].Always0, sizeof(uint32_t)); + + READ_DATA(ifstream, _model->animations.AnimationClasses[n].nFloats, sizeof(uint32_t)); + for (int x = 0; x < _model->animations.AnimationClasses[n].nFloats; x++) { + READ_DATA(ifstream, _model->animations.AnimationClasses[n].floats, sizeof(float)); + } + + READ_DATA(ifstream, _model->animations.AnimationClasses[n].value, sizeof(float)); + switch (_model->animations.AnimationClasses[n].AnimTransformType) { + case 0:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//rotaton + case 1:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//rotationX + case 2:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//rotationY + case 3:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//rotationZ + READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float) * 2); + break; + case 4:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//translation + case 5:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//translationX + case 6:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break;//translationY + case 7:READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); break; //translationZ + READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)*2); + break; + case 8: //"direct" + READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float) * 8); + break; + case 9: //"hide" + READ_DATA(ifstream, _model->animations.AnimationClasses[n].data, sizeof(float)); + break; + default: + READ_DATA(ifstream, _model->animations.AnimationClasses[n].value, sizeof(float)); + } + PRINT_INDEX; + } + } + + // Animations done, WEEE! + READ_DATA(ifstream, _model->animations.NoOfResolutions, sizeof(uint32_t)); + for (int x = 0; x < _model->animations.NoOfResolutions; x++) { + // Read a Bones2Anims entry + READ_DATA(ifstream, _model->animations.Bones2Anims[x].NoOfBones, sizeof(uint32_t)); + for (int y = 0; y < _model->animations.Bones2Anims[x].NoOfBones; y++) { + READ_DATA(ifstream, _model->animations.Bones2Anims[x].Bone2AnimClassLists[y].NoOfAnimClasses, sizeof(uint32_t)); + for (int z = 0; z < _model->animations.Bones2Anims[x].Bone2AnimClassLists[y].NoOfAnimClasses; z++) { + READ_DATA(ifstream, _model->animations.Bones2Anims[x].Bone2AnimClassLists[y].AnimationClassIndex[z], sizeof(uint32_t)); + } + } + } + + for (int x = 0; x < _model->animations.NoOfResolutions; x++) { + // Read Anims2Bones + for (int y = 0; y < _model->animations.nAnimationClasses; y++) { + READ_DATA(ifstream, _model->animations.Anims2Bones[x].AnimBones[y].SkeletonBoneNameIndex, sizeof(uint32_t)); + + if (_model->animations.Anims2Bones[x].AnimBones[y].SkeletonBoneNameIndex != -1 && _model->animations.AnimationClasses[y].AnimTransformType != 8 && _model->animations.AnimationClasses[y].AnimTransformType != 9) { + READ_DATA(ifstream, _model->animations.Anims2Bones[x].AnimBones[y].axisPos, sizeof(float) * 3); + READ_DATA(ifstream, _model->animations.Anims2Bones[x].AnimBones[y].axisDir, sizeof(float) * 3); + } + PRINT_INDEX; + printf("Read bone index: %d\n", _model->animations.Anims2Bones[x].AnimBones[y].SkeletonBoneNameIndex); + } + } + + READ_DATA(ifstream, _model->StartAddressOfLods, sizeof(uint32_t)*_model->header.lod_count); + READ_DATA(ifstream, _model->EndAddressOfLods, sizeof(uint32_t)*_model->header.lod_count); + + printf("Beginning LOD Read: Start[%d] End[%d]\n", _model->StartAddressOfLods, _model->EndAddressOfLods); + + return _model; + } + }; +}; \ No newline at end of file diff --git a/extensions/common/p3d/read_helpers.hpp b/extensions/common/p3d/read_helpers.hpp new file mode 100644 index 0000000000..69558a6a06 --- /dev/null +++ b/extensions/common/p3d/read_helpers.hpp @@ -0,0 +1,11 @@ +#pragma once + +#define READ_BOOL(output) { uint8_t temp; stream_.read((char *)&temp, 1); if(temp != 0) { output = true; } else { output = false; } } +#define READ_DATA(output, size) stream_.read((char *)&output, size); +#define READ_STRING(output) { \ + std::stringstream ss; \ + for(int x = 0; x < 2056;x++) { char byte = 0; stream_.read((char *)&byte, 1); if(byte == 0x00) break; ss << byte; } \ + output = ss.str(); \ + } +// @TODO: +#define READ_COMPRESSED_DATA(output, size) stream_.read((char *)&output, size) diff --git a/extensions/common/p3d/skeleton.cpp b/extensions/common/p3d/skeleton.cpp new file mode 100644 index 0000000000..0180b0fdb1 --- /dev/null +++ b/extensions/common/p3d/skeleton.cpp @@ -0,0 +1,46 @@ +#include "p3d/model.hpp" +#include <sstream> + +#include "read_helpers.hpp" + +namespace ace { + namespace p3d { + skeleton::skeleton() : size(0) {} + skeleton::skeleton(std::istream & stream_, const uint32_t lod_count) : size(0) { + READ_STRING(name); + if (name.length() > 1) { + READ_BOOL(inherited); + stream_.read((char *)&size, sizeof(uint32_t)); + + for (int x = 0; x < size; x++) { + std::string _name, _parent; + + READ_STRING(_name); + READ_STRING(_parent); + + all_bones.push_back(std::make_shared<bone>(_name, _parent)); + } + + for (auto& tbone : all_bones) { + for (auto& child : all_bones) { + if (child->parent == tbone->name) { + tbone->children.push_back(child->name); + } + } + + if (tbone->parent.length() < 1) { + root_bones[tbone->name] = tbone; + } + } + + // Skip a byte because! + //stream_.seekg(1, stream_.cur); + LOG(DEBUG) << "Skeleton loaded: " << name; + char junk; + stream_.read((char *)&junk, sizeof(uint8_t)); + } + + } + skeleton::~skeleton() {} + } +} diff --git a/extensions/common/p3d/skeleton.hpp b/extensions/common/p3d/skeleton.hpp new file mode 100644 index 0000000000..86fa71c49c --- /dev/null +++ b/extensions/common/p3d/skeleton.hpp @@ -0,0 +1,36 @@ +#pragma once +#pragma once + +#include "shared.hpp" + + +namespace ace { + namespace p3d { + class bone { + public: + bone() : name(""), parent("") {} + bone(const std::string & name_, const std::string & parent_) + : name(name_), parent(parent_) { + } + std::string name; + std::string parent; + std::vector<std::string> children; + std::vector<uint32_t> animations; + }; + typedef std::shared_ptr<bone> bone_p; + + class skeleton { + public: + skeleton(); + skeleton(std::istream &, const uint32_t lod_count); + ~skeleton(); + + std::string name; + bool inherited; + uint32_t size; + std::map<std::string, bone_p> root_bones; + std::vector<bone_p> all_bones; + }; + typedef std::shared_ptr<skeleton> skeleton_p; + }; +}; \ No newline at end of file diff --git a/extensions/common/pbo/archive.cpp b/extensions/common/pbo/archive.cpp new file mode 100644 index 0000000000..71c11de3fe --- /dev/null +++ b/extensions/common/pbo/archive.cpp @@ -0,0 +1,91 @@ +#pragma once + +#include "archive.hpp" +#include "p3d/read_helpers.hpp" + +namespace ace { + namespace pbo { + + bool archive::get_file(std::istream &, const std::string & file, file_p output) { + return false; + } + + bool archive::get_file(std::istream & stream_, const entry_p entry, file_p output) { + uint32_t file_offset, bytes_read, use_size; + + std::streampos _save = stream_.tellg(); + file_offset = begin_data_offset + entry->offset; + + use_size = max(entry->size, entry->storage_size); + output->data = new uint8_t[use_size]; + + bytes_read = 0; + stream_.seekg(file_offset, stream_.beg); + while (bytes_read < use_size) { + if (!stream_.read((char *)output->data + bytes_read, use_size - bytes_read)) { + delete[] output->data; + output->data = nullptr; + return false; + } + bytes_read += stream_.gcount(); + } + + + output->size = use_size; + output->entry = entry; + + stream_.seekg(_save, stream_.beg); + + return true; + } + + archive::archive() { } + archive::archive(std::istream &stream_) { + // Read the first entry, then info, then next entry + uint32_t offset = 0; + entry_p root_entry = std::make_shared<entry>(stream_); + info = std::make_shared<ext_entry>(stream_); + root_entry->offset = 0; + entries.push_back(root_entry); + + entry_p next_entry = std::make_shared<entry>(stream_); + while (next_entry->filename != "") { // off by 1006 ?! + next_entry->offset = offset; + entries.push_back(next_entry); + offset += next_entry->storage_size; + + next_entry = std::make_shared<entry>(stream_); + } + begin_data_offset = stream_.tellg(); + } + archive::~archive() {} + + entry::entry() {} + entry::entry(std::istream &stream_) { + READ_STRING(filename); + std::transform(filename.begin(), filename.end(), filename.begin(), ::tolower); + + stream_.read((char *)&compression, sizeof(uint32_t)); + stream_.read((char *)&size, sizeof(uint32_t)); + stream_.read((char *)&reserved, sizeof(uint32_t)); + stream_.read((char *)×tamp, sizeof(uint32_t)); + stream_.read((char *)&storage_size, sizeof(uint32_t)); + } + + ext_entry::ext_entry() {} + ext_entry::ext_entry(std::istream &stream_) { + READ_STRING(name); + READ_STRING(data); + READ_STRING(version); + + std::string temp; + temp = version; + + while (temp != "") { + extras.push_back(temp); + READ_STRING(temp); + } + + } + } +} diff --git a/extensions/common/pbo/archive.hpp b/extensions/common/pbo/archive.hpp new file mode 100644 index 0000000000..18a795a8e0 --- /dev/null +++ b/extensions/common/pbo/archive.hpp @@ -0,0 +1,61 @@ +#pragma once + +#include "shared.hpp" + +namespace ace { + namespace pbo { + class ext_entry { + public: + ext_entry(); + ext_entry(std::istream &); + + std::string name; + std::string data; + std::string version; + + std::vector<std::string> extras; + }; + typedef std::shared_ptr<ext_entry> ext_entry_p; + + class entry { + public: + entry(); + entry(std::istream &); + + std::string filename; + + uint32_t compression; + uint32_t size; + uint32_t storage_size; + uint32_t offset; // pre-computed during search, offset of file + + uint32_t reserved; + uint32_t timestamp; + }; + typedef std::shared_ptr<entry> entry_p; + + class file { + public: + entry_p entry; + uint8_t *data; + uint32_t size; + }; + typedef std::shared_ptr<file> file_p; + + class archive { + public: + archive(); + archive(std::istream &); + ~archive(); + + bool get_file(std::istream &, const std::string & file, file_p output); + bool get_file(std::istream &, const entry_p entry, file_p output); + + uint32_t begin_data_offset; + + ext_entry_p info; + std::vector<entry_p> entries; + }; + typedef std::shared_ptr<archive> archive_p; + } +} diff --git a/extensions/common/pbo/search.cpp b/extensions/common/pbo/search.cpp new file mode 100644 index 0000000000..f383bf5dc5 --- /dev/null +++ b/extensions/common/pbo/search.cpp @@ -0,0 +1,301 @@ +#include "search.hpp" +#include <sstream> +#include <iterator> +#include <algorithm> +#include <regex> + +#define NT_SUCCESS(x) ((x) >= 0) +#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004 + +#define SystemHandleInformation 16 +#define ObjectBasicInformation 0 +#define ObjectNameInformation 1 +#define ObjectTypeInformation 2 + +typedef NTSTATUS(NTAPI *_NtQuerySystemInformation)( + ULONG SystemInformationClass, + PVOID SystemInformation, + ULONG SystemInformationLength, + PULONG ReturnLength + ); +typedef NTSTATUS(NTAPI *_NtDuplicateObject)( + HANDLE SourceProcessHandle, + HANDLE SourceHandle, + HANDLE TargetProcessHandle, + PHANDLE TargetHandle, + ACCESS_MASK DesiredAccess, + ULONG Attributes, + ULONG Options + ); +typedef NTSTATUS(NTAPI *_NtQueryObject)( + HANDLE ObjectHandle, + ULONG ObjectInformationClass, + PVOID ObjectInformation, + ULONG ObjectInformationLength, + PULONG ReturnLength + ); + +typedef struct _UNICODE_STRING +{ + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +typedef struct _SYSTEM_HANDLE +{ + ULONG ProcessId; + BYTE ObjectTypeNumber; + BYTE Flags; + USHORT Handle; + PVOID Object; + ACCESS_MASK GrantedAccess; +} SYSTEM_HANDLE, *PSYSTEM_HANDLE; + +typedef struct _SYSTEM_HANDLE_INFORMATION +{ + ULONG HandleCount; + SYSTEM_HANDLE Handles[1]; +} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION; + +typedef enum _POOL_TYPE +{ + NonPagedPool, + PagedPool, + NonPagedPoolMustSucceed, + DontUseThisType, + NonPagedPoolCacheAligned, + PagedPoolCacheAligned, + NonPagedPoolCacheAlignedMustS +} POOL_TYPE, *PPOOL_TYPE; + +typedef struct _OBJECT_TYPE_INFORMATION +{ + UNICODE_STRING Name; + ULONG TotalNumberOfObjects; + ULONG TotalNumberOfHandles; + ULONG TotalPagedPoolUsage; + ULONG TotalNonPagedPoolUsage; + ULONG TotalNamePoolUsage; + ULONG TotalHandleTableUsage; + ULONG HighWaterNumberOfObjects; + ULONG HighWaterNumberOfHandles; + ULONG HighWaterPagedPoolUsage; + ULONG HighWaterNonPagedPoolUsage; + ULONG HighWaterNamePoolUsage; + ULONG HighWaterHandleTableUsage; + ULONG InvalidAttributes; + GENERIC_MAPPING GenericMapping; + ULONG ValidAccess; + BOOLEAN SecurityRequired; + BOOLEAN MaintainHandleCount; + USHORT MaintainTypeList; + POOL_TYPE PoolType; + ULONG PagedPoolUsage; + ULONG NonPagedPoolUsage; +} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; + +PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName) +{ + return GetProcAddress(GetModuleHandleA(LibraryName), ProcName); +} + +namespace ace { + namespace pbo { + + bool search::index_files() { + return index_files(".*"); + } + + bool search::index_files(const std::string &filter) { + std::ifstream pbo_stream; + std::regex txt_regex(filter); + + if (_active_pbo_list.size() < 1) + return false; + + for (auto & pbo_file_path : _active_pbo_list) { + pbo_stream.open(pbo_file_path, std::ios::binary | std::ios::in); + if (!pbo_stream.good()) { + LOG(ERROR) << "Cannot open file - " << pbo_file_path; + continue; + } + + ace::pbo::archive _archive(pbo_stream); + for (ace::pbo::entry_p & entry : _archive.entries) { + if (entry->filename != "") { + if (std::regex_match(entry->filename, txt_regex)) { + std::string full_virtual_path = _archive.info->data + "\\" + entry->filename; + std::transform(full_virtual_path.begin(), full_virtual_path.end(), full_virtual_path.begin(), ::tolower); + _file_pbo_index[full_virtual_path] = pbo_file_path; + //LOG(DEBUG) << full_virtual_path << " = " << pbo_file_path; + } + } + } + pbo_stream.close(); + } + + LOG(INFO) << "PBO Index complete"; + + return true; + } + + search::search(const std::string & filter) { + generate_pbo_list(); + index_files(filter); + } + + search::search() { + generate_pbo_list(); + index_files(); + } + + bool search::generate_pbo_list() { + NTSTATUS status; + PSYSTEM_HANDLE_INFORMATION handleInfo; + ULONG handleInfoSize = 0x10000; + ULONG pid; + HANDLE processHandle; + ULONG i; + + _NtQuerySystemInformation NtQuerySystemInformation = + (_NtQuerySystemInformation)GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation"); + _NtDuplicateObject NtDuplicateObject = + (_NtDuplicateObject)GetLibraryProcAddress("ntdll.dll", "NtDuplicateObject"); + _NtQueryObject NtQueryObject = + (_NtQueryObject)GetLibraryProcAddress("ntdll.dll", "NtQueryObject"); + + if (!NtQuerySystemInformation || !NtDuplicateObject || !NtQueryObject) + return false; + + pid = GetCurrentProcessId(); + processHandle = GetCurrentProcess(); + + handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize); + + while ((status = NtQuerySystemInformation( + SystemHandleInformation, + handleInfo, + handleInfoSize, + NULL + )) == STATUS_INFO_LENGTH_MISMATCH) + handleInfo = (PSYSTEM_HANDLE_INFORMATION)realloc(handleInfo, handleInfoSize *= 2); + + /* NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH. */ + if (!NT_SUCCESS(status)) + { + LOG(ERROR) << "Error opening object for pbo search"; + free(handleInfo); + return false; + } + + for (i = 0; i < handleInfo->HandleCount; i++) + { + SYSTEM_HANDLE handle = handleInfo->Handles[i]; + HANDLE dupHandle = NULL; + POBJECT_TYPE_INFORMATION objectTypeInfo; + PVOID objectNameInfo; + UNICODE_STRING objectName; + ULONG returnLength; + + /* Check if this handle belongs to the PID the user specified. */ + if (handle.ProcessId != pid) + continue; + + /* Duplicate the handle so we can query it. */ + if (!NT_SUCCESS(NtDuplicateObject( + processHandle, + (HANDLE)handle.Handle, + GetCurrentProcess(), + &dupHandle, + 0, + 0, + 0 + ))) + { + continue; + } + + /* Query the object type. */ + objectTypeInfo = (POBJECT_TYPE_INFORMATION)malloc(0x1000); + if (!NT_SUCCESS(NtQueryObject( + dupHandle, + ObjectTypeInformation, + objectTypeInfo, + 0x1000, + NULL + ))) + { + CloseHandle(dupHandle); + continue; + } + + /* Query the object name (unless it has an access of + 0x0012019f, on which NtQueryObject could hang. */ + if (handle.GrantedAccess == 0x0012019f) + { + + free(objectTypeInfo); + CloseHandle(dupHandle); + continue; + } + + objectNameInfo = malloc(0x1000); + if (!NT_SUCCESS(NtQueryObject( + dupHandle, + ObjectNameInformation, + objectNameInfo, + 0x1000, + &returnLength + ))) + { + /* Reallocate the buffer and try again. */ + objectNameInfo = realloc(objectNameInfo, returnLength); + if (!NT_SUCCESS(NtQueryObject( + dupHandle, + ObjectNameInformation, + objectNameInfo, + returnLength, + NULL + ))) + { + free(objectTypeInfo); + free(objectNameInfo); + CloseHandle(dupHandle); + continue; + } + } + + /* Cast our buffer into an UNICODE_STRING. */ + objectName = *(PUNICODE_STRING)objectNameInfo; + + + + /* Print the information! */ + if (objectName.Length) + { + std::wstring tmp_type(objectTypeInfo->Name.Buffer); + std::wstring tmp_name(objectName.Buffer); + + std::string object_type(tmp_type.begin(), tmp_type.end()); + std::string object_name(tmp_name.begin(), tmp_name.end()); + if (object_type == "File" && object_name.find(".pbo") != object_name.npos) { + char buffer[MAX_PATH]; + GetFinalPathNameByHandle(dupHandle, buffer, sizeof(buffer), VOLUME_NAME_DOS); + + LOG(DEBUG) << "Pbo: " << buffer; + _active_pbo_list.push_back(std::string(buffer)); + } + } + + free(objectTypeInfo); + free(objectNameInfo); + CloseHandle(dupHandle); + } + + free(handleInfo); + + return true; + } + } +} \ No newline at end of file diff --git a/extensions/common/pbo/search.hpp b/extensions/common/pbo/search.hpp new file mode 100644 index 0000000000..61aaccb9f0 --- /dev/null +++ b/extensions/common/pbo/search.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include "shared.hpp" +#include "pbo/archive.hpp" + +namespace ace { + namespace pbo { + class search { + public: + search(); + search(const std::string &); + + const std::unordered_map<std::string, std::string> & file_index() { return _file_pbo_index; } + const std::vector<std::string> & active_pbo_list() { return _active_pbo_list; } + protected: + bool index_files(); + bool index_files(const std::string &); + bool generate_pbo_list(); + + std::unordered_map<std::string, std::string> _file_pbo_index; + + std::vector<std::string> _active_pbo_list; + std::vector<ace::pbo::archive_p> _archives; + }; + typedef std::shared_ptr<search> search_p; + } +} \ No newline at end of file diff --git a/extensions/common/shared.cpp b/extensions/common/shared.cpp new file mode 100644 index 0000000000..ca0c65f409 --- /dev/null +++ b/extensions/common/shared.cpp @@ -0,0 +1,41 @@ +#include "shared.hpp" + +#include <algorithm> +#include <functional> +#include <cctype> +#include <locale> + +int test(int var) { + return var; +} +namespace ace { + std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) { + std::stringstream ss(s); + std::string item; + while (std::getline(ss, item, delim)) { + elems.push_back(item); + } + return elems; + } + + std::vector<std::string> split(const std::string &s, char delim) { + std::vector<std::string> elems; + split(s, delim, elems); + return elems; + } + + void runtime_assert(bool result) { + assert(result); + if (!result) { + LOG(ERROR) << "ACE Assertion failed, execution cancelling"; + throw exception(-1, "assertion failed"); + } + } + void runtime_assert(bool result, const uint32_t code, const std::string & text) { + assert(result); + if (!result) { + LOG(ERROR) << "ACE Assertion failed, execution cancelling"; + throw exception(code, text); + } + } +} \ No newline at end of file diff --git a/extensions/common/shared.hpp b/extensions/common/shared.hpp new file mode 100644 index 0000000000..c84624132a --- /dev/null +++ b/extensions/common/shared.hpp @@ -0,0 +1,77 @@ +#pragma once + +#include "targetver.h" +#include <assert.h> +#include <stdio.h> +#include <string> +#include <vector> +#include <list> +#include <map> +#include <unordered_map> +#include <memory> +#include <cmath> +#include <cstdint> +#include <streambuf> +#include "ace_version.hpp" +#include "logging.hpp" + +#ifdef _DEBUG +#define ZERO_OUTPUT() { memset(output, 0x00, outputSize); } +#define EXTENSION_RETURN() {output[outputSize-1] = 0x00; } return; +#else +#define ZERO_OUTPUT() +#define EXTENSION_RETURN() return; +#endif + +#ifdef _WINDOWS +#define sleep(x) Sleep(x) +#endif + +namespace ace { + template< typename T > + struct array_deleter + { + void operator ()(T const * p) + { + delete[] p; + } + }; + + std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems); + std::vector<std::string> split(const std::string &s, char delim); + + // trim from start + static inline std::string <rim(std::string &s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace)))); + return s; + } + + // trim from end + static inline std::string &rtrim(std::string &s) { + s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end()); + return s; + } + + // trim from both ends + static inline std::string &trim(std::string &s) { + return ltrim(rtrim(s)); + } + + inline void runtime_assert(bool result); + + struct exception { + exception(const uint32_t code_, const std::string & text_) : code(code_), text(text_) {} + + exception & operator= (const exception& other) { code = other.code; text = other.text; return *this; } + bool operator == (const exception &r) const { return ( code == r.code ); } + + uint32_t code; + std::string text; + }; +} + +#ifdef _DEBUG +#define ACE_ASSERT assert() +#else +#define ACE_ASSERT ace::runtime_assert() +#endif \ No newline at end of file diff --git a/extensions/common/simplepipe_win32.cpp b/extensions/common/simplepipe_win32.cpp new file mode 100644 index 0000000000..f79af02857 --- /dev/null +++ b/extensions/common/simplepipe_win32.cpp @@ -0,0 +1,179 @@ +#include "simplepipe_win32.hpp" +#include <Sddl.h> +#include <AccCtrl.h> +#include <Aclapi.h> + +namespace ace { + namespace { + const wchar_t kPipePrefix[] = L"\\\\.\\pipe\\"; + const int kPipeBufferSz = 4 * 1024; + } // namespace + + bool checkIntegritySupport() { + OSVERSIONINFO osvi; + + ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + + return osvi.dwMajorVersion > 5; + } + + LONG g_pipe_seq = 0; + + HANDLE pipe_pair::open_pipe_server(const wchar_t* name, bool low_integrity, bool blocking) { + SECURITY_ATTRIBUTES sa = {0}; + SECURITY_ATTRIBUTES *psa = 0; + DWORD wait; + static const bool is_integrity_supported = checkIntegritySupport(); + + if (is_integrity_supported && low_integrity) { + psa = &sa; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; + if (!ConvertStringSecurityDescriptorToSecurityDescriptor( + TEXT("S:(ML;;NWNR;;;LW)"), SDDL_REVISION_1, &sa.lpSecurityDescriptor, NULL)) + return INVALID_HANDLE_VALUE; + } + + if (blocking) { + wait = PIPE_WAIT; + } else { + wait = PIPE_NOWAIT; + } + + std::wstring pipename(kPipePrefix); + pipename.append(name); + return ::CreateNamedPipeW(pipename.c_str(), PIPE_ACCESS_DUPLEX | FILE_FLAG_FIRST_PIPE_INSTANCE, + PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | wait, + 1, kPipeBufferSz, kPipeBufferSz, 200, psa); + } + + HANDLE pipe_pair::open_pipe_client(const wchar_t* name, bool inherit, bool impersonate) { + std::wstring pipename(kPipePrefix); + pipename.append(name); + + SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, inherit ? TRUE : FALSE}; + for (;;) { + DWORD attributes = impersonate ? 0 : SECURITY_SQOS_PRESENT | SECURITY_IDENTIFICATION; + HANDLE pipe = ::CreateFileW(pipename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, &sa, + OPEN_EXISTING, attributes, NULL); + if (INVALID_HANDLE_VALUE == pipe) { + if (ERROR_PIPE_BUSY != ::GetLastError()) { + return pipe; + } + // wait and retry. + if (! ::WaitNamedPipeW(pipename.c_str(), NMPWAIT_USE_DEFAULT_WAIT)) + continue; + } else { + // success. + return pipe; + } + } + } + + + pipe_pair::pipe_pair(bool inherit_fd2, bool blocking) : srv_(NULL), cln_(NULL) { + // Come up with a reasonable unique name. + const wchar_t kPipePattern[] = L"ko.%x.%x.%x"; + wchar_t name[8*3 + sizeof(kPipePattern)]; + ::wsprintfW(name, kPipePattern, ::GetCurrentProcessId(), ::GetTickCount(), + ::InterlockedIncrement(&g_pipe_seq)); + HANDLE server = open_pipe_server(name, blocking); + if (INVALID_HANDLE_VALUE == server) { + return; + } + // Don't allow client impersonation. + HANDLE client = open_pipe_client(name, inherit_fd2, false); + if (INVALID_HANDLE_VALUE == client) { + ::CloseHandle(server); + return; + } + if (!::ConnectNamedPipe(server, NULL)) { + if (ERROR_PIPE_CONNECTED != ::GetLastError()) { + ::CloseHandle(server); + ::CloseHandle(client); + return; + } + } + + srv_ = server; + cln_ = client; + } + + + pipe_win::pipe_win() : pipe_(INVALID_HANDLE_VALUE) { + } + + pipe_win::~pipe_win() { + if (pipe_ != INVALID_HANDLE_VALUE) { + ::DisconnectNamedPipe(pipe_); // $$$ disconect is valid on the server side. + ::CloseHandle(pipe_); + } + } + + bool pipe_win::open_client(HANDLE pipe) { + pipe_ = pipe; + return true; + } + + bool pipe_win::open_server(HANDLE pipe, bool connect) { + pipe_ = pipe; + + if (connect) { + if (!::ConnectNamedPipe(pipe, NULL)) { + if (ERROR_PIPE_CONNECTED != ::GetLastError()) { + return false; + } + } + } + return true; + } + + bool pipe_win::write(const void* buf, size_t sz) { + DWORD written = 0; + return (TRUE == ::WriteFile(pipe_, buf, sz, &written, NULL)); + } + + bool pipe_win::CheckStatus() { + char buf[5]; + uint32_t size = sizeof(buf); + BOOL ret; + ret = ::ReadFile(pipe_, buf, sizeof(buf), reinterpret_cast<DWORD*>(&size), NULL); + if (!ret) { + if (GetLastError() == ERROR_NO_DATA) { + return true; + } else { + return false; + } + } else { + return true; + } + } + + bool pipe_win::read(void* buf, size_t* sz) { + BOOL ret; + ret = ::ReadFile(pipe_, buf, *sz, reinterpret_cast<DWORD*>(sz), NULL); + if (!ret) { + if (GetLastError() == ERROR_BROKEN_PIPE) { + if (!DisconnectNamedPipe(pipe_)) { + printf("DisconnectNamedPipe() failed. hr=%08x", GetLastError()); + } + if (!::ConnectNamedPipe(pipe_, NULL)) { + } + } + } + return ret; + } + + + char* PipeTransport::receive(size_t* size) { + if (buf_.size() < kBufferSz) + buf_.resize(kBufferSz); + + *size = kBufferSz; + if (!read(&buf_[0], size)) + return NULL; + return &buf_[0]; + } +} \ No newline at end of file diff --git a/extensions/common/simplepipe_win32.hpp b/extensions/common/simplepipe_win32.hpp new file mode 100644 index 0000000000..3c37c9637b --- /dev/null +++ b/extensions/common/simplepipe_win32.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include <cstdint> +#include <string> +#include <vector> + +#include <Winsock2.h> + +namespace ace { + class pipe_pair { + public: + pipe_pair(bool inherit_fd2 = false, bool blocking = true); + HANDLE fd1() const { return srv_; } + HANDLE fd2() const { return cln_; } + + static HANDLE open_pipe_server(const wchar_t* name, bool low_integrity = true, bool blocking = true); + static HANDLE open_pipe_client(const wchar_t* name, bool inherit, bool impersonate); + + private: + HANDLE srv_; + HANDLE cln_; + }; + + class pipe_win { + public: + pipe_win(); + ~pipe_win(); + + bool open_client(HANDLE pipe); + bool open_server(HANDLE pipe, bool connect = false); + + bool write(const void* buf, size_t sz); + bool read(void* buf, size_t* sz); + + bool CheckStatus(); + bool IsConnected() const { return INVALID_HANDLE_VALUE != pipe_; } + + private: + HANDLE pipe_; + }; + + + class PipeTransport : public pipe_win { + public: + static const size_t kBufferSz = 4096; + + size_t send(const void* buf, size_t sz) { + return write(buf, sz) ? -1 : 0; + } + + char* receive(size_t* size); + + private: + std::vector<char> buf_; + }; +} + diff --git a/extensions/common/simulation/object.cpp b/extensions/common/simulation/object.cpp new file mode 100644 index 0000000000..0831111711 --- /dev/null +++ b/extensions/common/simulation/object.cpp @@ -0,0 +1,464 @@ +#include "object.hpp" +#include "p3d\parser.hpp" + + +#include "glm\gtc\matrix_transform.hpp" + +ace::simulation::vertex::vertex(vertex_table & _table, ace::vector3<float> _vertex, uint32_t _id) : table(_table), vertex_id(_id) +{ + this->original_vertex = _vertex; + this->animated_vertex = _vertex; +} + +ace::simulation::vertex::~vertex() +{ +} + + +ace::simulation::face::face( + const ace::p3d::face_p p3d_face, + const ace::p3d::lod_p p3d_lod, + const ace::p3d::model_p p3d, + ace::simulation::lod *object_lod) +{ + this->type = p3d_face->type; + for (uint16_t vertex_id : p3d_face->vertex_table) { + this->vertices.push_back(object_lod->vertices[vertex_id]); + object_lod->vertices[vertex_id]->faces.push_back(this); + } +} + +ace::simulation::face::~face() +{ +} + +void ace::simulation::vertex::animate(const glm::mat4 &matrix, ace::vector3<float> rotation_offset, bool offset) +{ + ace::vector3<float> temp_vector = this->original_vertex; + if (offset) { + temp_vector = temp_vector - rotation_offset; + } + glm::vec4 temp_gl_vector = glm::vec4(temp_vector.x(), temp_vector.y(), temp_vector.z(), 1.0f); + temp_gl_vector = matrix*temp_gl_vector; + this->animated_vertex = ace::vector3<float>(temp_gl_vector.x, temp_gl_vector.y, temp_gl_vector.z); + if (offset) { + // this->animated_vertex = this->animated_vertex + rotation_offset; + } +} + +ace::simulation::named_selection::named_selection( + const ace::p3d::named_selection_p p3d_selection, + const ace::p3d::lod_p p3d_lod, + const ace::p3d::model_p p3d, + ace::simulation::lod *object_lod) +{ + this->name = p3d_selection->name; + for (uint16_t vertex_id : p3d_selection->vertex_table.data) { + this->vertices.push_back(object_lod->vertices[vertex_id]); + object_lod->vertices[vertex_id]->selections.push_back(this); + } + for (uint16_t face_id : p3d_selection->faces.data) { + this->faces.push_back(object_lod->faces[face_id]); + } +} + +ace::simulation::named_selection::~named_selection() +{ +} + +void ace::simulation::named_selection::animate(const glm::mat4 &matrix, ace::vector3<float> rotation_offset) +{ + bool offset = !rotation_offset.zero_distance(); + for (auto selection_vertex : this->vertices) { + selection_vertex->animate(matrix, rotation_offset, offset); + } +} + + + + +ace::simulation::vertex_table::vertex_table(const ace::p3d::vertex_table_p p3d_vertex_table, const ace::p3d::lod_p p3d_lod, const ace::p3d::model_p p3d) : animated(false) +{ + this->vertices.resize(p3d_vertex_table->points.size); + for (uint32_t i = 0; i <= p3d_vertex_table->points.size - 1; ++i) { + if (p3d->info->autocenter) { + ace::vector3<float> new_vertex = ace::vector3<float>( + p3d_vertex_table->points[i].x() + (p3d_lod->autocenter_pos.x()*-1), + p3d_vertex_table->points[i].y() + (p3d_lod->autocenter_pos.y()*-1), + p3d_vertex_table->points[i].z() + (p3d_lod->autocenter_pos.z()*-1) + ); + this->vertices[i] = std::make_shared<vertex>(*this, new_vertex, i); + + } + else { + this->vertices[i] = std::make_shared<vertex>(*this, p3d_vertex_table->points[i], i); + } + } +} + +ace::simulation::vertex_table::~vertex_table() +{ +} + +ace::simulation::lod::lod(const ace::p3d::lod_p p3d_lod, const ace::p3d::model_p p3d) +{ + this->id = p3d_lod->id; + this->vertices = vertex_table(p3d_lod->vertices, p3d_lod, p3d); + this->autocenter_pos = p3d_lod->autocenter_pos; + + for (ace::p3d::face_p p3d_face : p3d_lod->faces) { + this->faces.push_back(std::make_shared<face>(p3d_face, p3d_lod, p3d, this)); + } + + for (ace::p3d::named_selection_p p3d_selection : p3d_lod->selections) { + this->selections[p3d_selection->name] = std::make_shared<named_selection>(p3d_selection, p3d_lod, p3d, this); + } +} + + +ace::simulation::lod::~lod() +{ +} + +ace::simulation::lod_animation_info::lod_animation_info( + animation *_animation, + lod_p _lod, + const ace::p3d::animate_bone_p p3d_animate_bone, + const ace::p3d::animation_p p3d_animation, + const ace::p3d::model_p p3d) : animation_definition(_animation), lod(_lod) +{ + this->index = p3d_animate_bone->index; + if (p3d->info->autocenter) { + this->axis_position = p3d_animate_bone->axis_position + (lod->autocenter_pos*-1); + this->axis_direction = p3d_animate_bone->axis_direction.normalize(); + } + else { + this->axis_position = p3d_animate_bone->axis_position; + this->axis_direction = p3d_animate_bone->axis_direction.normalize(); + } +} + +ace::simulation::lod_animation_info::~lod_animation_info() +{ +} + +ace::simulation::animation::animation(object *parent_object, const ace::p3d::animation_p p3d_animation, const ace::p3d::model_p p3d) +{ + this->type = p3d_animation->type; + this->name = p3d_animation->name; + this->source = p3d_animation->source; + + this->source_address = p3d_animation->source_address; + + this->min_value = p3d_animation->min_value; + this->max_value = p3d_animation->max_value; + + this->min_phase = p3d_animation->min_phase; + this->max_phase = p3d_animation->max_phase; + + switch (type) { + // rotations + case 0: + case 1: + case 2: + case 3: + angle0 = p3d_animation->angle0; + angle1 = p3d_animation->angle1; + break; + // translations + case 4: + case 5: + case 6: + case 7: + offset0 = p3d_animation->offset0; + offset1 = p3d_animation->offset1; + break; + case 8: + direct_axis_pos = p3d_animation->direct_axis_pos; + direct_axis_dir = p3d_animation->direct_axis_dir; + direct_angle = p3d_animation->direct_angle; + direct_axis_offset = p3d_animation->direct_axis_offset; + break; + case 9: + hide_value = p3d_animation->hide_value; + default: + offset0 = 0.0f; + offset1 = 0.0f; + } + + + + + for (ace::p3d::animate_bone_p animation_bone : p3d_animation->bones) { + this->lod_info[animation_bone->lod] = std::make_shared<lod_animation_info>(this, parent_object->lods[animation_bone->lod], animation_bone, p3d_animation, p3d); + } + +} + +ace::simulation::animation::~animation() +{ +} + +typedef union { + float f; + struct { + uint32_t sh1 : 32; + } parts; +} double_cast; + +#define RAD2DEG(rad) (rad * 180.0f / 3.1415926f); + +typedef std::map<uint32_t, std::pair<glm::mat4, ace::vector3<float>>> animation_transform; +animation_transform ace::simulation::animation::animate(const float phase, const std::vector<uint32_t> &lods, animation_transform base_transforms) +{ + animation_transform return_matrices; + for (auto lod_id : lods) { + glm::mat4 base_matrix = base_transforms[lod_id].first; + ace::vector3<float> base_rotation_offset = base_transforms[lod_id].second; + glm::mat4 animation_matrix, direction_matrix; + ace::vector3<float> rotation_offset = ace::vector3<float>(0, 0, 0); + + float scale = get_scale(phase); + + glm::vec3 axis_position = glm::vec3(this->lod_info[lod_id]->axis_position.x(), this->lod_info[lod_id]->axis_position.y(), this->lod_info[lod_id]->axis_position.z()); + glm::vec3 axis_direction = glm::vec3(this->lod_info[lod_id]->axis_direction.x(), this->lod_info[lod_id]->axis_direction.y(), this->lod_info[lod_id]->axis_direction.z()); + + if (this->type < 4) { + switch (this->type) { + //rotation + case 0: { + scale = (scale / (max_value - min_value)) * (angle1 - angle0); + + animation_matrix = glm::rotate(glm::mat4(1.0f), scale, axis_direction); + direction_matrix = glm::translate(glm::mat4(1.0f), axis_position); + + animation_matrix = animation_matrix * direction_matrix; + + rotation_offset = this->lod_info[lod_id]->axis_position; + break; + } + //rotationX + case 1: { + scale = (scale / (max_value - min_value)) * (angle1 - angle0); + glm::vec3 rotation_axis = glm::vec3(1.0f, 0.0f, 0.0f); + + animation_matrix = glm::rotate(glm::mat4(1.0f), -scale, rotation_axis); + direction_matrix = glm::translate(glm::mat4(1.0f), axis_position); + + animation_matrix = animation_matrix * direction_matrix; + + rotation_offset = this->lod_info[lod_id]->axis_position; + break; + } + //rotationY + case 2: { + scale = (scale / (max_value - min_value)) * (angle1 - angle0); + glm::vec3 rotation_axis = glm::vec3(0.0f, 1.0f, 0.0f); + + animation_matrix = glm::rotate(glm::mat4(1.0f), scale, rotation_axis); + direction_matrix = glm::translate(glm::mat4(1.0f), axis_position); + + animation_matrix = animation_matrix * direction_matrix; + + rotation_offset = this->lod_info[lod_id]->axis_position; + break; + } + //rotationZ + case 3: { + scale = (scale / (max_value - min_value)) * (angle1 - angle0); + glm::vec3 rotation_axis = glm::vec3(0.0f, 0.0f, 1.0f); + + direction_matrix = glm::translate(glm::mat4(1.0f), axis_position); + animation_matrix = glm::rotate(direction_matrix, -scale, rotation_axis); + + + animation_matrix = animation_matrix * direction_matrix; + + rotation_offset = this->lod_info[lod_id]->axis_position; + break; + } + //translation + case 4: { + scale = (scale / (max_value - min_value)) * (offset1 - offset0); + glm::vec3 direction( + this->lod_info[lod_id]->axis_direction.x(), + this->lod_info[lod_id]->axis_direction.y(), + this->lod_info[lod_id]->axis_direction.z() + ); + direction = direction * scale; + direction_matrix = glm::translate(glm::mat4(1.0f), axis_position); + animation_matrix = glm::translate(glm::mat4(1.0f), direction); + animation_matrix = animation_matrix * direction_matrix; + + break; + } + //translationX + case 5: { + scale = (scale / (max_value - min_value)) * (offset1 - offset0); + animation_matrix = glm::translate(animation_matrix, glm::vec3( + scale, + 0.0f, + 0.0f + )); + break; + } + //translationY + case 6: { + scale = (scale / (max_value - min_value)) * (offset1 - offset0); + animation_matrix = glm::translate(animation_matrix, glm::vec3( + 0.0f, + scale, + 0.0f + )); + break; + } + //translationZ + case 7: { + scale = (scale / (max_value - min_value)) * (offset1 - offset0); + animation_matrix = glm::translate(animation_matrix, glm::vec3( + 0.0f, + 0.0f, + scale + )); + break; + } + case 8: { + // fuck direct for now + break; + } + //hide + case 9: { + if (phase >= hide_value) + animation_matrix = glm::mat4x4(0.0f); + break; + } + default: {} + } + return_matrices[lod_id].first = animation_matrix * base_matrix; + return_matrices[lod_id].second = base_rotation_offset + rotation_offset; + } + } + return return_matrices; +} + +float ace::simulation::animation::get_scale(float phase) +{ + float scale = 0; + + + switch (source_address) + { + case 1: + scale = fmod(phase - min_value, (max_value - min_value) * 2) + min_value; + // when over limit, mirror + if (phase > max_value) phase = max_value - (phase - max_value); + + scale = std::min(std::max(scale, min_phase), max_phase); + + break; + case 2: + scale = fmod(phase - min_value, (max_value - min_value)) + min_value; + if (scale > max_value) scale = max_value - (scale - max_value); + scale = std::min(std::max(scale, min_phase), max_phase); + break; + default: + scale = std::min(std::max(phase, min_phase), max_phase); + } + + return scale; +} + +ace::simulation::bone::bone( + const std::string _name, + const std::vector<std::string> &children, + const std::map<std::string, ace::p3d::bone_p> &p3d_bones, + bone *_parent, + const ace::p3d::model_p p3d, + object * sim_object + ) : parent(_parent), name(_name), base_object(sim_object) +{ + for (auto const child_bone : children) { + if (sim_object->all_bones.find(child_bone) == sim_object->all_bones.end()) { + ace::p3d::bone_p p3d_bone = p3d_bones.find(child_bone)->second; + sim_object->all_bones[child_bone] = std::make_shared<bone>(p3d_bone->name, p3d_bone->children, p3d_bones, this, p3d, sim_object); + } + this->children.push_back(sim_object->all_bones[child_bone]); + } + if (parent) { + for (auto p3d_animation : p3d_bones.find(name)->second->animations) { + this->animations.push_back(sim_object->animations[p3d_animation]); + } + } +} + +void ace::simulation::bone::animate(const std::map<std::string, float> &animation_state, const std::vector<uint32_t> &lods, animation_transform base_transforms) +{ + if (animations.size() > 0) { + for (auto bone_animation : animations) { + if (animation_state.find(bone_animation->name) != animation_state.end()) { + base_transforms = bone_animation->animate(animation_state.find(bone_animation->name)->second, lods, base_transforms); + } + } + } + for (auto child_bone : children) { + child_bone->animate(animation_state, lods, base_transforms); + } + if (animations.size() > 0) { + for (auto bone_animation : animations) { + for (auto lod_id : lods) { + auto selection = this->base_object->lods[lod_id]->selections.find(this->name); + if (selection != this->base_object->lods[lod_id]->selections.end()) { + selection->second->animate(base_transforms[lod_id].first, base_transforms[lod_id].second); + } + } + } + } +} + +ace::simulation::object::object() +{ +} + +ace::simulation::object::object(const ace::p3d::model_p model) +{ + for (ace::p3d::lod_p p3d_lod : model->lods) { + lod_p new_lod = std::make_shared<lod>(p3d_lod, model); + this->lods.push_back(new_lod); + this->lods[p3d_lod->id]->type = model->info->resolutions[p3d_lod->id]; + } + + for (ace::p3d::animation_p p3d_animation : model->animations) { + this->animations.push_back(std::make_shared<animation>(this, p3d_animation, model)); + } + + std::map<std::string, ace::p3d::bone_p> p3d_bones; + for (auto const skeleton_bone : model->skeleton->all_bones) { + p3d_bones[skeleton_bone->name] = skeleton_bone; + } + + std::vector<std::string> root_bones; + for (auto const root_bone : model->skeleton->root_bones) { + root_bones.push_back(root_bone.first); + } + + this->root_bone = std::make_shared<bone>("", root_bones, p3d_bones, nullptr, model, this); +} + + + +ace::simulation::object::~object() +{ + +} + +void ace::simulation::object::animate(const std::map<std::string, float> &animation_state, const std::vector<uint32_t> &selected_lods) +{ + animation_transform identity_transform; + for (uint32_t lod_id : selected_lods) { + identity_transform[lod_id].first = glm::mat4(); + identity_transform[lod_id].second = ace::vector3<float>(0, 0, 0); + } + this->root_bone->animate(animation_state, selected_lods, identity_transform); +} + + diff --git a/extensions/common/simulation/object.hpp b/extensions/common/simulation/object.hpp new file mode 100644 index 0000000000..a77da9d5cf --- /dev/null +++ b/extensions/common/simulation/object.hpp @@ -0,0 +1,221 @@ +#pragma once + +#include "shared.hpp" + +#include <string> +#include <vector> +#include <map> + +#define GLM_PRECISION_HIGHP_FLOAT + +#include "p3d\model.hpp" +#include "glm\glm.hpp" +#include "glm\vec3.hpp" +#include "glm\mat4x4.hpp" + + +namespace ace { + namespace simulation { + + class vertex; + typedef std::shared_ptr<vertex> vertex_p; + + class lod; + typedef std::shared_ptr<lod> lod_p; + + class object; + typedef std::shared_ptr<object> object_p; + + typedef std::map<uint32_t, std::pair<glm::mat4, ace::vector3<float>>> animation_transform; + + class vertex_table { + public: + vertex_table() {}; + vertex_table(const ace::p3d::vertex_table_p, const ace::p3d::lod_p, const ace::p3d::model_p); + ~vertex_table(); + vertex_p operator[] (const int index) { return vertices[index]; } + std::vector<vertex_p> vertices; + private: + bool animated; + }; + + class face { + public: + face() {}; + face(const ace::p3d::face_p, const ace::p3d::lod_p, const ace::p3d::model_p, ace::simulation::lod *); + ~face(); + uint8_t type; + std::vector<vertex_p> vertices; + }; + typedef std::shared_ptr<face> face_p; + + class named_selection { + public: + named_selection() {}; + named_selection(const ace::p3d::named_selection_p, const ace::p3d::lod_p, const ace::p3d::model_p, ace::simulation::lod *); + ~named_selection(); + + std::string name; + std::vector<face_p> faces; + std::vector<vertex_p> vertices; + + void animate(const glm::mat4 &, ace::vector3<float>); + }; + typedef std::shared_ptr<named_selection> named_selection_p; + + class vertex { + public: + vertex(vertex_table &, ace::vector3<float>, uint32_t); + ~vertex(); + + ace::vector3<float> operator * (const float &v) { return animated_vertex * v; } + ace::vector3<float> operator / (const float &v) { return animated_vertex / v; } + + ace::vector3<float> operator * (const ace::vector3<float> &v) { return animated_vertex * v; } + ace::vector3<float> operator / (const ace::vector3<float> &v) { return animated_vertex / v; } + ace::vector3<float> operator + (const ace::vector3<float> &v) { return animated_vertex + v; } + ace::vector3<float> operator - (const ace::vector3<float> &v) { return animated_vertex - v; } + ace::vector3<float> operator - () { return -(animated_vertex); } + + bool operator == (const ace::vector3<float> &r) { return (animated_vertex == r); } + bool operator > (const ace::vector3<float> &r) const { throw 1; } + bool operator < (const ace::vector3<float> &r) const { throw 1; } + bool operator <= (const ace::vector3<float> &r) const { throw 1; } + bool operator >= (const ace::vector3<float> &r) const { throw 1; } + + float x() { return animated_vertex.x(); } + float y() { return animated_vertex.y(); } + float z() { return animated_vertex.z(); } + uint16_t id() { return this->vertex_id; } + + operator ace::vector3<float>() { return animated_vertex; } + + std::vector<face *> faces; + std::vector<named_selection *> selections; + + void animate(const glm::mat4 &, ace::vector3<float>, bool); + + private: + ace::vector3<float> original_vertex; + ace::vector3<float> animated_vertex; + vertex_table &table; + uint16_t vertex_id; + }; + + + + + class lod { + public: + lod() {}; + lod(const ace::p3d::lod_p, const ace::p3d::model_p); + ~lod(); + uint32_t id; + float type; + vertex_table vertices; + ace::vector3<float> autocenter_pos; + std::map<std::string, named_selection_p> selections; + std::vector<face_p> faces; + }; + + class animation; + typedef std::shared_ptr<animation> animation_p; + + class lod_animation_info { + public: + lod_animation_info() {}; + lod_animation_info(animation *, lod_p, const ace::p3d::animate_bone_p, const ace::p3d::animation_p, const ace::p3d::model_p); + ~lod_animation_info(); + animation *animation_definition; + int32_t index; + lod_p lod; + ace::vector3<float> axis_direction; + ace::vector3<float> axis_position; + }; + typedef std::shared_ptr<lod_animation_info> lod_animation_info_p; + + + + class animation { + public: + animation() {}; + animation(object *, const ace::p3d::animation_p, const ace::p3d::model_p); + ~animation(); + + uint32_t type; + std::string name; // "RightDoor" + std::string source; // "rotor" + + float min_value; + float max_value; + float min_phase; + float max_phase; + + float offset0; + float offset1; + + float angle0; + float angle1; + + float hide_value; + + ace::vector3<float> direct_axis_pos; + ace::vector3<float> direct_axis_dir; + + float direct_angle; + float direct_axis_offset; + + uint32_t source_address; + + std::vector<float> transforms; + std::map<uint32_t, lod_animation_info_p> lod_info; + + animation_transform animate(const float, const std::vector<uint32_t> &, animation_transform); + + float get_scale(float); + }; + + + class bone; + typedef std::shared_ptr<bone> bone_p; + + class bone { + public: + bone( + const std::string, + const std::vector<std::string> &, + const std::map<std::string, ace::p3d::bone_p> &, + bone *, + const ace::p3d::model_p, + object *); + + ~bone() {}; + std::string name; + bone *parent; + std::vector<bone_p> children; + std::vector<animation_p> animations; + object *base_object; + void animate(const std::map<std::string, float> &, const std::vector<uint32_t> &, animation_transform base_transforms); + }; + + + class object { + public: + object(); + object(const ace::p3d::model_p); + ~object(); + + std::vector<lod_p> lods; + + std::vector<animation_p> animations; + + void animate(const std::map<std::string, float> &, const std::vector<std::uint32_t> &); + + std::map<std::string, bone_p> all_bones; + + bone_p root_bone; + + }; + + } +} \ No newline at end of file diff --git a/extensions/common/singleton.hpp b/extensions/common/singleton.hpp new file mode 100644 index 0000000000..1c602f04ef --- /dev/null +++ b/extensions/common/singleton.hpp @@ -0,0 +1,31 @@ +#include <cstdint> +#include <assert.h> + +#pragma once + +namespace ace { + template<typename T> + class singleton { + public: + static T & get() { + + if (_singletonInstance == nullptr) { + assert(_initialized == false); + _initialized = true; + _singletonInstance = new T(); + } + + return *_singletonInstance; + } + static void release() { + delete _singletonInstance; + } + protected: + static T *_singletonInstance; + static bool _initialized; + }; + template<typename T> + T* singleton<T>::_singletonInstance = nullptr; + template<typename T> + bool singleton<T>::_initialized = false; +} \ No newline at end of file diff --git a/extensions/common/targetver.h b/extensions/common/targetver.h index 781012c18f..9a671c9f0b 100644 --- a/extensions/common/targetver.h +++ b/extensions/common/targetver.h @@ -1,7 +1,7 @@ #pragma once #ifdef _WIN32 - #define WIN32_LEAN_AND_MEAN +// #define WIN32_LEAN_AND_MEAN #include <windows.h> #else diff --git a/extensions/common/transform_matrix.hpp b/extensions/common/transform_matrix.hpp new file mode 100644 index 0000000000..f9c3056dc9 --- /dev/null +++ b/extensions/common/transform_matrix.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "shared.hpp" +#include "vector.hpp" + +namespace ace { + template <typename T> + class transform_matrix_base { + public: + transform_matrix_base & operator= (const transform_matrix_base& other) { _x = other.x(); _y = other.y(); _z = other.z(); _n = other.n(); return *this; } + + transform_matrix_base() {} + transform_matrix_base(std::istream &stream_, uint32_t version = 68) : _x(stream_), _y(stream_), _z(stream_), _n(stream_) { } + transform_matrix_base(ace::vector3<T> x_, ace::vector3<T> y_, ace::vector3<T> z_, ace::vector3<T> n_) : _x(x_), _y(y_), _z(z_), _n(n_) { } + + const ace::vector3<T> & x() const { return _x; } + const ace::vector3<T> & y() const { return _y; } + const ace::vector3<T> & z() const { return _z; } + const ace::vector3<T> & n() const { return _n; } + + void x(const ace::vector3<T> val) { _x = val; } + void y(const ace::vector3<T> val) { _y = val; } + void z(const ace::vector3<T> val) { _z = val; } + void n(const ace::vector3<T> val) { _n = val; } + + protected: + ace::vector3<T> _x; + ace::vector3<T> _y; + ace::vector3<T> _z; + ace::vector3<T> _n; + }; + + typedef transform_matrix_base<float> transform_matrix; +}; \ No newline at end of file diff --git a/extensions/common/vector.cpp b/extensions/common/vector.cpp new file mode 100644 index 0000000000..b7d180e5b6 --- /dev/null +++ b/extensions/common/vector.cpp @@ -0,0 +1,11 @@ +#include "vector.hpp" + + +namespace ace { + template <> float acos(float n) { return std::acosf(n); } + template <> double acos(double n) { return std::acos(n); } + template <> float cos(float n) { return std::cosf(n); } + template <> double cos(double n) { return std::cos(n); } + template <> float sin(float n) { return std::sinf(n); } + template <> double sin(double n) { return std::sin(n); } +} \ No newline at end of file diff --git a/extensions/common/vector.hpp b/extensions/common/vector.hpp new file mode 100644 index 0000000000..ac5b38bd1f --- /dev/null +++ b/extensions/common/vector.hpp @@ -0,0 +1,161 @@ +#pragma once + +/* +#ifdef USE_BULLET +#include "LinearMath\btVector3.h" +#endif +*/ +#include "shared.hpp" +namespace ace { + + template <typename T> T acos(T n) { return -1; } + template <typename T> T cos(T n) { return -1; } + template <typename T> T sin(T n) { return -1; } + + template<typename T> + class vector3 { + public: + vector3() : + _x(0), + _y(0), + _z(0) { + } + vector3(const T x_, const T y_, const T z_) : + _x(x_), + _y(y_), + _z(z_) { + } + vector3(std::istream & read_) { + // Constructor to read from a stream + read_.read((char *)&_x, sizeof(T)); + read_.read((char *)&_y, sizeof(T)); + read_.read((char *)&_z, sizeof(T)); + } + vector3(const float *buffer) { + _x = buffer[0]; + _y = buffer[1]; + _z = buffer[2]; + } + + vector3<T> & operator= (const vector3<T>& other) { _x = other.x(); _y = other.y(); _z = other.z(); return *this; } +/*#ifdef _WIN32 && _DIRECTX + vector3<T> & operator= (const XMFLOAT3& Float3) { _x = Float3.x; _y = Float3.y; _z = Float3.z; return *this; } +#endif + +#ifdef USE_BULLET + vector3<T> & operator= (const btVector3& bt_vec) { _x = bt_vec.x(); _y = bt_vec.y(); _z = bt_vec.z(); return *this; } +#endif +*/ + vector3 operator * (const T &val) const { return vector3(_x * val, _y * val, _z * val); } + vector3 operator / (const T &val) const { T invVal = T(1) / val; return vector3(_x * invVal, _y * invVal, _z * invVal); } + vector3 operator + (const vector3<T> &v) const { return vector3(_x + v.x(), _y + v.y(), _z + v.z()); } + vector3 operator / (const vector3 &v) const { return vector3(_x / v.x(), _y / v.y(), _z / v.z()); } + vector3 operator * (const vector3 &v) const { return vector3(_x * v.x(), _y * v.y(), _z * v.z()); } + vector3 operator - (const vector3 &v) const { return vector3(_x - v.x(), _y - v.y(), _z - v.z()); } + vector3 operator - () const { return vector3(-_x, -_y, -_z); } + + bool operator == (const vector3 &r) const { return (_x == r.x() && _y == r.y() && _z == r.z()); } + bool operator > (const vector3 &r) const { throw 1; } + bool operator < (const vector3 &r) const { throw 1; } + bool operator <= (const vector3 &r) const { throw 1; } + bool operator >= (const vector3 &r) const { throw 1; } + + T magnitude() const { return sqrt(_x * _x + _y * _y + _z * _z); } + T dot(const vector3 &v) const { return (_x * v.x() + _y * v.y() + _z * v.z()); } + T distance(const vector3 &v) const { vector3 dist = (*this - v); dist = dist * dist; return sqrt(dist.x() + dist.y() + dist.z()); } + vector3 cross(const vector3 &v) const { return vector3(_y * v.z() - _z * v.y(), _z * v.x() - _x * v.z(), _x * v.y() - _y * v.x()); } + vector3 normalize(void) const { return (*this / abs(magnitude())); }; + bool zero_distance() { return ((_x == 0.0f && _y == 0.0f && _z == 0.0f) ? true : false ); } + + static float clamp(T x, T a, T b) { return x < a ? a : (x > b ? b : x); } + + static vector3 lerp(const vector3& A, const vector3& B, const T t) { return A*t + B*(1.f - t); } + vector3 lerp(const vector3& B, const T t) { return vector3::lerp(*this, B, t); } + + static vector3 slerp(vector3 start, vector3 end, T percent) { + T dot = start.dot(end); + dot = vector3::clamp(dot, -1.0f, 1.0f); + + T theta = acos(dot) * percent; + vector3 relative = end - start*dot; + relative.normalize(); + return ((start * cos(theta)) + (relative*sin(theta))); + } + vector3 slerp(const vector3& B, const T p) { + return vector3::slerp(*this, B, p); + } + + const T & x() const { return _x; } + const T & y() const { return _y; } + const T & z() const { return _z; } + + void x(const T val) { _x = val; } + void y(const T val) { _y = val; } + void z(const T val) { _z = val; } + protected: + T _x; + T _y; + T _z; + }; + + template<typename T, unsigned int N = 3> + class vector { + public: + vector() : + _values(std::vector<T>(N)) { + } + std::vector<T> _values; + }; + + + template<typename T> + class spatial { + public: + spatial() : + position(vector3<T>()), + orientation(vector3<T>()) + { + } + explicit spatial(const vector3<T> & position_, const vector3<T> & orientation_) : + position(position_), + orientation(orientation_) + {} + spatial<T> & operator= (const spatial<T> & other) { position = other.position; orientation = other.orientation; return *this; } + vector3<T> position; + vector3<T> orientation; + }; + + + template<typename T> + class pair { + public: + pair() : + _x(0), + _y(0) { + } + pair(const T x_, const T y_, const T z_) : + _x(x_), + _y(y_) { + } + pair(const float *buffer) { + _x = buffer[0]; + _y = buffer[1]; + } + pair(std::istream & read_) { + // Constructor to read from a stream + read_.read((char *)&_x, sizeof(T)); + read_.read((char *)&_y, sizeof(T)); + } + + pair<T> & operator= (const pair<T>& other) { _x = other.x(); _y = other.y(); return *this; } + + const T & x() const { return _x; } + const T & y() const { return _y; } + + void x(const T val) { _x = val; } + void y(const T val) { _y = val; } + protected: + T _x; + T _y; + }; +}; \ No newline at end of file diff --git a/extensions/dynload/CMakeLists.txt b/extensions/dynload/CMakeLists.txt new file mode 100644 index 0000000000..d3b2b956bd --- /dev/null +++ b/extensions/dynload/CMakeLists.txt @@ -0,0 +1,14 @@ +set(ACE_EXTENSION_NAME "ace_dynload") + +file(GLOB SOURCES *.h *.hpp *.c *.cpp) +add_library( ${ACE_EXTENSION_NAME} SHARED ${SOURCES} ${GLOBAL_SOURCES}) +add_library( ${ACE_EXTENSION_NAME}_static STATIC ${SOURCES} ${GLOBAL_SOURCES}) + +target_link_libraries(${ACE_EXTENSION_NAME} ace_common) +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "") +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES FOLDER Extensions) + +if(CMAKE_COMPILER_IS_GNUCXX) + set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES LINK_SEARCH_START_STATIC 1) + set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES LINK_SEARCH_END_STATIC 1) +endif() \ No newline at end of file diff --git a/extensions/dynload/ace_dynload.cpp b/extensions/dynload/ace_dynload.cpp new file mode 100644 index 0000000000..3573ed3877 --- /dev/null +++ b/extensions/dynload/ace_dynload.cpp @@ -0,0 +1,66 @@ +/* + * ace_vd.cpp + * + * + */ + +#include "shared.hpp" +#include "arguments.hpp" +#include "dispatch.hpp" + +static char version[] = "1.0"; + +#ifndef _STATIC +extern "C" { + __declspec (dllexport) void __stdcall RVExtension(char *output, int outputSize, const char *function); +}; + +#endif + +std::string get_command(const std::string & input) { + size_t cmd_end; + std::string command; + + cmd_end = input.find(':'); + if (cmd_end < 1) { + return ""; + } + + return input.substr(0, cmd_end); +} + + +void __stdcall RVExtension(char *output, int outputSize, const char *function) { + ZERO_OUTPUT(); + + // Get the command, then the command args + std::string input = function; + + std::string command = get_command(input); + std::string argument_str; + if (command.length() > 1 && input.length() > command.length()+1) { + argument_str = input.substr(command.length() + 1, (input.length() + 1 - command.length())); + } + ace::arguments _args(argument_str); + + std::string result = ""; + + if (command.size() < 1) { + output[0] = 0x00; + EXTENSION_RETURN(); + } + if (command == "version") { + result = version; + } + if (command == "echo") { + result = function; + } + + /*************************/ + // Real functionality goes here + ace::dispatch::get().call(command, _args, result); + + + sprintf_s(output, outputSize, "%s", result.c_str()); + EXTENSION_RETURN(); +} diff --git a/extensions/dynload/ace_dynload_dllmain.cpp b/extensions/dynload/ace_dynload_dllmain.cpp new file mode 100644 index 0000000000..95228f2d38 --- /dev/null +++ b/extensions/dynload/ace_dynload_dllmain.cpp @@ -0,0 +1,33 @@ +#include "shared.hpp" +#include "logging.hpp" +#include "dynloader.hpp" + +INITIALIZE_EASYLOGGINGPP + +BOOLEAN WINAPI DllMain(IN HINSTANCE hDllHandle, + IN DWORD nReason, + IN LPVOID Reserved) { + BOOLEAN bSuccess = TRUE; + el::Configurations conf; + + switch (nReason) { + case DLL_PROCESS_ATTACH: + conf.setGlobally(el::ConfigurationType::Filename, "logs/ace_dynload.log"); + el::Loggers::setDefaultConfigurations(conf, true); + + conf.set( + el::Level::Global, + el::ConfigurationType::Filename, + "logs/server_events.log"); + + // Register functions + ace::dynloader::get().register_functions(); + + break; + case DLL_PROCESS_DETACH: + break; + } + + return bSuccess; + +} \ No newline at end of file diff --git a/extensions/dynload/dynloader.hpp b/extensions/dynload/dynloader.hpp new file mode 100644 index 0000000000..8916e9af92 --- /dev/null +++ b/extensions/dynload/dynloader.hpp @@ -0,0 +1,168 @@ +#pragma once + +#include "shared.hpp" +#include "dispatch.hpp" +#include "arguments.hpp" + +typedef void (__stdcall *RVExtension)(char *output, int outputSize, const char *function); + +namespace ace { + + class module { + public: + module() : handle(nullptr), function(nullptr), name("") {} + module(const std::string & name_, HMODULE handle_, RVExtension function_, const std::string & file_) : handle(handle_), function(function_), name(name_), temp_filename(file_) {} + + std::string name; + std::string temp_filename; + HMODULE handle; + RVExtension function; + }; + + class dynloader : public singleton<dynloader> { + public: + dynloader() {} + ~dynloader() { + for (auto & kv : _modules) { + arguments temp(kv.first); + std::string result_temp; + unload(temp, result_temp); + } + } + +#ifdef _WINDOWS + bool load(const arguments & args_, std::string & result) { + HMODULE dllHandle; + RVExtension function; + + LOG(INFO) << "Load requested [" << args_.as_string(0) << "]"; + + if (_modules.find(args_.as_string(0)) != _modules.end()) { + LOG(ERROR) << "Module already loaded [" << args_.as_string(0) << "]"; + return true; + } + +#ifdef _WINDOWS + // Make a copy of the file to temp, and load it from there, referencing the current path name + char tmpPath[MAX_PATH +1], buffer[MAX_PATH + 1]; + + if(!GetTempPathA(MAX_PATH, tmpPath)) { + LOG(ERROR) << "GetTempPath() failed, e=" << GetLastError(); + return false; + } + if(!GetTempFileNameA(tmpPath, "ace_dynload", TRUE, buffer)) { + LOG(ERROR) << "GetTempFileName() failed, e=" << GetLastError(); + return false; + } + std::string temp_filename = buffer; + if (!CopyFileA(args_.as_string(0).c_str(), temp_filename.c_str(), FALSE)) { + DeleteFile(temp_filename.c_str()); + if (!CopyFileA(args_.as_string(0).c_str(), temp_filename.c_str(), FALSE)) { + LOG(ERROR) << "CopyFile() , e=" << GetLastError(); + return false; + } + } +#else + std::string temp_filename = args_.as_string(0); +#endif + + dllHandle = LoadLibrary(temp_filename.c_str()); + if (!dllHandle) { + LOG(ERROR) << "LoadLibrary() failed, e=" << GetLastError() << " [" << args_.as_string(0) << "]"; + return false; + } + + function = (RVExtension)GetProcAddress(dllHandle, "_RVExtension@12"); + if (!function) { + LOG(ERROR) << "GetProcAddress() failed, e=" << GetLastError() << " [" << args_.as_string(0) << "]"; + FreeLibrary(dllHandle); + return false; + } + + LOG(INFO) << "Load completed [" << args_.as_string(0) << "]"; + + _modules[args_.as_string(0)] = module(args_.as_string(0), dllHandle, function, temp_filename); + + return false; + } + bool unload(const arguments & args_, std::string & result) { + + LOG(INFO) << "Unload requested [" << args_.as_string(0) << "]"; + + if (_modules.find(args_.as_string(0)) == _modules.end()) { + LOG(INFO) << "Unload failed, module not loaded [" << args_.as_string(0) << "]"; + return true; + } + + if (!FreeLibrary(_modules[args_.as_string(0)].handle)) { + LOG(INFO) << "FreeLibrary() failed during unload, e=" << GetLastError(); + return false; + } + //if (!DeleteFileA(_modules[args_.as_string(0)].temp_filename.c_str())) { + // LOG(INFO) << "DeleteFile() failed during unload, e=" << GetLastError(); + // return false; + //} + + _modules.erase(args_.as_string(0)); + + LOG(INFO) << "Unload complete [" << args_.as_string(0) << "]"; + + return true; + } +#endif + + bool call(const arguments & args_, std::string & result) { + //LOG(INFO) << "Calling [" << args_.as_string(0) << "]"; + + if (_modules.find(args_.as_string(0)) == _modules.end()) { + return false; + } + + result = ""; + result.resize(4096); + + std::string function_str; + std::vector<std::string> temp = ace::split(args_.get(), ','); + + if (temp.size() < 3) { + function_str = temp[1]; + } else { + for (int x = 1; x < temp.size(); x++) + function_str = function_str + temp[x] + ","; + } + _modules[args_.as_string(0)].function((char *)result.c_str(), 4096, (const char *)function_str.c_str()); +#ifdef _DEBUG + //if (args_.as_string(0) != "fetch_result" && args_.as_string(0) != "ready") { + // LOG(INFO) << "Called [" << args_.as_string(0) << "], with {" << function_str << "} result={" << result << "}"; + //} +#endif + return true; + } + + bool list(const arguments & args_, std::string & result) { + + LOG(INFO) << "Listing loaded modules"; + std::string res; + + for (auto & kv : _modules) { + res = res + kv.first + ", "; + LOG(INFO) << "\t" << kv.first; + } + + result = res; + + return false; + } + + bool register_functions() { + dispatch::get().add("list", std::bind(&ace::dynloader::list, this, std::placeholders::_1, std::placeholders::_2)); + dispatch::get().add("load", std::bind(&ace::dynloader::load, this, std::placeholders::_1, std::placeholders::_2)); + dispatch::get().add("unload", std::bind(&ace::dynloader::unload, this, std::placeholders::_1, std::placeholders::_2)); + dispatch::get().add("call", std::bind(&ace::dynloader::call, this, std::placeholders::_1, std::placeholders::_2)); + + return true; + } + protected: + std::unordered_map<std::string, module> _modules; + }; +}; diff --git a/extensions/fcs/CMakeLists.txt b/extensions/fcs/CMakeLists.txt index 0a4ba1b064..574884df76 100644 --- a/extensions/fcs/CMakeLists.txt +++ b/extensions/fcs/CMakeLists.txt @@ -1,9 +1,10 @@ set(ACE_EXTENSION_NAME "ace_fcs") file(GLOB SOURCES *.h *.hpp *.c *.cpp) -add_library( ${ACE_EXTENSION_NAME} SHARED ${GLOBAL_SOURCES} ${SOURCES}) -add_dependencies(${ACE_EXTENSION_NAME} ace_common) -SET_TARGET_PROPERTIES(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "") +add_library( ${ACE_EXTENSION_NAME} SHARED ${SOURCES} ${GLOBAL_SOURCES}) +target_link_libraries(${ACE_EXTENSION_NAME} ace_common) +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES PREFIX "") +set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES FOLDER Extensions) if(CMAKE_COMPILER_IS_GNUCXX) set_target_properties(${ACE_EXTENSION_NAME} PROPERTIES LINK_SEARCH_START_STATIC 1) diff --git a/extensions/fcs/ace_fcs.cpp b/extensions/fcs/ace_fcs.cpp index 4aada29aff..75ef3b240b 100644 --- a/extensions/fcs/ace_fcs.cpp +++ b/extensions/fcs/ace_fcs.cpp @@ -11,7 +11,7 @@ * Correction to angle */ -#include "ace_common.h" +#include "shared.hpp" #define _USE_MATH_DEFINES @@ -101,6 +101,8 @@ double getSolution(double initSpeed, double airFriction, double angleTarget, dou #pragma warning( disable : 4996 ) void __stdcall RVExtension(char *output, int outputSize, const char *function) { + ZERO_OUTPUT(); + if (!strcmp(function, "version")) { strncpy(output, ACE_FULL_VERSION_STR, outputSize); } else { @@ -118,6 +120,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) { strcpy(output, sstream.str().c_str()); output[outputSize - 1] = '\0'; } + EXTENSION_RETURN(); } #pragma warning( pop ) diff --git a/extensions/lib/bullet3 b/extensions/lib/bullet3 new file mode 160000 index 0000000000..30ebb32228 --- /dev/null +++ b/extensions/lib/bullet3 @@ -0,0 +1 @@ +Subproject commit 30ebb322285809bde98959e10e73e5acb9981efc From 9f3a57bf320aea39c74af773d749b6a3f6e99ed6 Mon Sep 17 00:00:00 2001 From: jaynus <jaynus@gmail.com> Date: Wed, 13 May 2015 09:57:24 -0700 Subject: [PATCH 35/51] Changed: checkFiles extension check prints version returned by extension Changed: Build changed to SSE2 instead of defaulting to AVX. --- addons/common/functions/fnc_checkFiles.sqf | 3 +++ extensions/CMakeLists.txt | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf index b0ea8a5200..631329ecee 100644 --- a/addons/common/functions/fnc_checkFiles.sqf +++ b/addons/common/functions/fnc_checkFiles.sqf @@ -49,6 +49,9 @@ _addons = [_addons, {_this find "ace_" == 0}] call FUNC(filter); if (hasInterface) then { ["[ACE] ERROR", _errorMsg, {findDisplay 46 closeDisplay 0}] call FUNC(errorMessage); }; + } else { + // Print the current extension version + diag_log text format ["[ACE] Extension version: %1: %2", _x, (_x callExtension "version")]; }; } forEach getArray (configFile >> "ACE_Extensions" >> "extensions"); diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index b1c1703f94..ee876efeef 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -24,11 +24,11 @@ if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") set(CMAKE_SHARED_LINKER_FLAGS "-static-libgcc -static-libstdc++") else() - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:x86") - set(CMAKE_CXX_FLAGS_DEBUG "/D _DEBUG /MTd /Zi /Ob0 /Od /RTC1") - set(CMAKE_CXX_FLAGS_MINSIZEREL "/MT /O1 /Ob1 /D NDEBUG") - set(CMAKE_CXX_FLAGS_RELEASE "/MT /O2 /Ob2 /D NDEBUG") - set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "/MT /Zi /O2 /Ob1 /D NDEBUG") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Wall /arch:SSE2 /Qpar-report:2") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /D _DEBUG /MTd /Zi /Ob0 /Od /RTC1") + set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS} /MT /O1 /Ob1 /D NDEBUG") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS} /MT /O2 /Ob2 /D NDEBUG") + set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS} /MT /Zi /O2 /Ob1 /D NDEBUG") endif() include_directories("common") From bf732a2a02a1a65cdd63c31b7a8f8410147521c8 Mon Sep 17 00:00:00 2001 From: jaynus <jaynus@gmail.com> Date: Wed, 13 May 2015 11:17:43 -0700 Subject: [PATCH 36/51] Changed: Disable snprintf_s usage to get around auto-vectorization in the 2015 STL strnlen implementation --- extensions/CMakeLists.txt | 4 +++- .../advanced_ballistics/AdvancedBallistics.cpp | 18 +++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/extensions/CMakeLists.txt b/extensions/CMakeLists.txt index ee876efeef..54db16213d 100644 --- a/extensions/CMakeLists.txt +++ b/extensions/CMakeLists.txt @@ -23,7 +23,9 @@ if(CMAKE_COMPILER_IS_GNUCXX) SET(CMAKE_CXX_FLAGS "-std=c++11 -march=i686 -m32 -O2 -s -fPIC -fpermissive") set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") set(CMAKE_SHARED_LINKER_FLAGS "-static-libgcc -static-libstdc++") -else() +elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") + message(ERROR "SUPPORT NOT COMPLETE") +elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Wall /arch:SSE2 /Qpar-report:2") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} /D _DEBUG /MTd /Zi /Ob0 /Od /RTC1") set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS} /MT /O1 /Ob1 /D NDEBUG") diff --git a/extensions/advanced_ballistics/AdvancedBallistics.cpp b/extensions/advanced_ballistics/AdvancedBallistics.cpp index 7e87592e00..48865f7f6b 100644 --- a/extensions/advanced_ballistics/AdvancedBallistics.cpp +++ b/extensions/advanced_ballistics/AdvancedBallistics.cpp @@ -238,7 +238,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) ZERO_OUTPUT(); if (!strcmp(function, "version")) { - int n = sprintf_s(output, outputSize, "%s", ACE_FULL_VERSION_STR); + int n = sprintf(output, "%s", ACE_FULL_VERSION_STR); EXTENSION_RETURN(); } @@ -258,7 +258,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) velocity = strtod(strtok_s(NULL, ":", &next_token), NULL); retard = calculateRetard(dragModel, ballisticCoefficient, velocity); - int n = sprintf_s(output, outputSize, "%f", retard); + int n = sprintf(output, "%f", retard); EXTENSION_RETURN(); } else if (!strcmp(mode, "atmosphericCorrection")) { double ballisticCoefficient = 1.0; @@ -274,7 +274,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) atmosphereModel = strtok_s(NULL, ":", &next_token); ballisticCoefficient = calculateAtmosphericCorrection(ballisticCoefficient, temperature, pressure, humidity, atmosphereModel); - int n = sprintf_s(output, outputSize, "%f", ballisticCoefficient); + int n = sprintf(output, "%f", ballisticCoefficient); EXTENSION_RETURN(); } else if (!strcmp(mode, "new")) { unsigned int index = 0; @@ -369,7 +369,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) bulletDatabase[index].frames = 0.0; bulletDatabase[index].randSeed = 0; - int n = sprintf_s(output, outputSize, "%s", ""); + int n = sprintf(output, "%s", ""); EXTENSION_RETURN(); } else if (!strcmp(mode, "simulate")) { // simulate:0:[-0.109985,542.529,-3.98301]:[3751.57,5332.23,214.252]:[0.598153,2.38829,0]:28.6:0:0.481542:0:215.16 @@ -586,7 +586,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) velocityOffset[2] += (distribution(bulletDatabase[index].randGenerator) * 0.8 - 0.4) * coef; }; - int n = sprintf_s(output, outputSize, "_bullet setVelocity (_bulletVelocity vectorAdd [%f, %f, %f]); _bullet setPosASL (_bulletPosition vectorAdd [%f, %f, %f]);", velocityOffset[0], velocityOffset[1], velocityOffset[2], positionOffset[0], positionOffset[1], positionOffset[2]); + int n = sprintf(output, "_bullet setVelocity (_bulletVelocity vectorAdd [%f, %f, %f]); _bullet setPosASL (_bulletPosition vectorAdd [%f, %f, %f]);", velocityOffset[0], velocityOffset[1], velocityOffset[2], positionOffset[0], positionOffset[1], positionOffset[2]); EXTENSION_RETURN(); } else if (!strcmp(mode, "set")) { int height = 0; @@ -601,7 +601,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) map->gridBuildingNums.push_back(numObjects); map->gridSurfaceIsWater.push_back(surfaceIsWater); - int n = sprintf_s(output, outputSize, "%s", ""); + int n = sprintf(output, "%s", ""); EXTENSION_RETURN(); } else if (!strcmp(mode, "init")) { int mapSize = 0; @@ -616,7 +616,7 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) map = &mapDatabase[worldName]; if (map->gridHeights.size() == gridCells) { - int n = sprintf_s(output, outputSize, "%s", "Terrain already initialized"); + int n = sprintf(output, "%s", "Terrain already initialized"); EXTENSION_RETURN(); } @@ -629,10 +629,10 @@ void __stdcall RVExtension(char *output, int outputSize, const char *function) map->gridBuildingNums.reserve(gridCells); map->gridSurfaceIsWater.reserve(gridCells); - int n = sprintf_s(output, outputSize, "%s", ""); + int n = sprintf(output, "%s", ""); EXTENSION_RETURN(); } - int n = sprintf_s(output, outputSize, "%s", ""); + int n = sprintf(output, "%s", ""); EXTENSION_RETURN(); } From 524f622bf42c08b3a503ca63efb4b8200ceb66f0 Mon Sep 17 00:00:00 2001 From: jaynus <jaynus@gmail.com> Date: Wed, 13 May 2015 11:19:37 -0700 Subject: [PATCH 37/51] Rebuilt DLL's for testing. --- ace_advanced_ballistics.dll | Bin 592896 -> 623104 bytes ace_break_line.dll | Bin 715264 -> 728576 bytes ace_clipboard.dll | Bin 426496 -> 427008 bytes ace_fcs.dll | Bin 784384 -> 798720 bytes 4 files changed, 0 insertions(+), 0 deletions(-) diff --git a/ace_advanced_ballistics.dll b/ace_advanced_ballistics.dll index 5aa9a66c0cd9fc73b3550129435eba0febf2d0b0..0a14d846b55c43bf8051149a15484c5834464b7a 100644 GIT binary patch delta 178134 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%0AjUp3yc;sbpGYVe;l6z&}=3%di=# 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	Nb^gl!L@3bS6)q-`!d5sc|RIxhJIbPO_l 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 delta 156015 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 M?C1T+zq9V~KQ>MA@&Et; diff --git a/ace_break_line.dll b/ace_break_line.dll index 0379fd6f34ef589baca5aac3d52d2ef802eb7e0d..482486ddd3d9094782ebf0eebd5b0d1173feb12d 100644 GIT binary patch literal 728576 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�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⋘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 I_~s4#8)4=~XaE2J delta 257692 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%0A>d~ftJmzEO*}q%k&DHtt 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%0ApbH@X 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 DyIy3- diff --git a/ace_clipboard.dll b/ace_clipboard.dll index 4f77d63f1f26f0ab9080be5cf30297754a09a994..5b4ac1c5377b69e594ecc8c7d8b1996c06930b79 100644 GIT binary patch literal 427008 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�yL4uG39^y@}| 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 R1D7;#NduQO@ZU}Y{|74R`Go)g literal 426496 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	~DJ=MS~_I)9ezPZ7Fi-=Dq)s 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ཹ@Ui%eFP0jlFN)wq7kMVKSVV|nt-vLc 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℘G*p-ICB4u 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 diff --git a/ace_fcs.dll b/ace_fcs.dll index 4d8790b150909314ec9dc27e99083dc276ffcd99..919a4d0e5bfc86fde93c4be6372a1ba3c3a245f6 100644 GIT binary patch delta 280796 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%0AoV!X=>?unUA9bjU&;JM^e-if{b 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 S%JwtA=Jk=fcjwR9@_zyB6qQ*3 delta 270554 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�xEuIfTF@rL5dJwzy}h$6Z<e& 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 From ea157ac0a7c236e62c612180c5e389fbb75f307a Mon Sep 17 00:00:00 2001 From: Josuan Albin <alganthe@live.fr> Date: Wed, 13 May 2015 21:26:51 +0200 Subject: [PATCH 38/51] Documentation pass Documentation improved for - ai - aircraft - attach - captives --- documentation/feature/ai.md | 23 ++++++++++++--------- documentation/feature/aircraft.md | 31 ++++++++++++++++++++-------- documentation/feature/attach.md | 24 ++++++++++++++++------ documentation/feature/captives.md | 34 ++++++++++++++++++++++++------- 4 files changed, 80 insertions(+), 32 deletions(-) diff --git a/documentation/feature/ai.md b/documentation/feature/ai.md index b82192b920..6e04720af5 100644 --- a/documentation/feature/ai.md +++ b/documentation/feature/ai.md @@ -7,21 +7,24 @@ parent: wiki --- # Overview -## Adjusted AI skill values +- ## Adjusted AI skill values The idea here is to reduce the AI's godlike aiming capabilties while retaining it's high intelligence. The AI should be smart enough to move through a town, but also be 'human' in their reaction time and aim. Note: All these values can still be adjusted via scripts, these arrays just change what 0 & 1 are for setSkill. -## Firing in burst mode + +- ## Firing in burst mode AIs will now use the automatic mode of their weapons on short distances, instead of always relying on firing single shots in quick succession. -## Longer engagement ranges + +- ## Longer engagement ranges The maximum engagement ranges are increased: AI will fire in bursts with variable length on high ranges of 500 - 700 meters, depending on their weapon and optic. -## No deadzones in CQB -Some weapons had minimum engagement ranges. If you were as close as 2 meters to an AAF soldier, he wouldn't open fire, because the AI couldn't find any valid fire mode for their weapon. AGM removes this behaviour mostly notable in CQB by adding a valid firing mode. -## No scripting -All changes of AGM AI are config based to ensure full compatibility with advanced AI modifications like ASR AI. + +- ## No deadzones in CQB +Some weapons had minimum engagement ranges. If you were as close as 2 meters to an AAF soldier, he wouldn't open fire, because the AI couldn't find any valid fire mode for their weapon. ACE 3 removes this behaviour mostly notable in CQB by adding a valid firing mode. + +- ## No scripting +All changes of ACE 3 AI are config based to ensure full compatibility with advanced AI modifications like ASR AI. # Usage -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. +Nothing # Dependencies -List of modules that must be present for this module to work. +None \ No newline at end of file diff --git a/documentation/feature/aircraft.md b/documentation/feature/aircraft.md index 6b99540466..156c75a384 100644 --- a/documentation/feature/aircraft.md +++ b/documentation/feature/aircraft.md @@ -6,20 +6,33 @@ order: 5 parent: wiki --- # Overview -## Adjusted flight behaviour +- ## Adjusted flight behaviour Changes the flight behaviour of various aircraft. -## Various adjustments to A2A, A2G and G2A munitions -- needs documentaion - -## Missile lock warnings + +- ## Various adjustments to aircraft and gunships munitions +- Higher capacity magazines for the comanche. +- Gatling rate of fire (ROF) increased. +- AP rockets have less splash damage. + + +- ## Missile lock warnings Adds missile-lock warning systems to helicopters and planes based on the various real life capabilities. -## Semi-automatic flare mode + +- ## Semi-automatic flare mode Adds the semi-automatic flare mode known from Arma 2. The key to switch the mode still exists in Arma 3's key settings, but is unused. -### Ejecting from pilot and copilot seats + +- ## Ejecting from pilot and copilot seats Pilots and copilots of all helicopters can now eject. -## Laser marker for wildcat + +- ## Laser marker for wildcat Adds a laser marker to the copilot seat of the Wildcat. -## HUD for AH-9 +- ## HUD for AH-9 Adds a HUD to the AH-9 based on the comanches HUD. +# Usage + +- ## switching flare mode: +the fefault keybind is ```ctrl + c``` + # Dependencies -List of modules that must be present for this module to work. +None \ No newline at end of file diff --git a/documentation/feature/attach.md b/documentation/feature/attach.md index 7bf2c400e6..257151739a 100644 --- a/documentation/feature/attach.md +++ b/documentation/feature/attach.md @@ -5,14 +5,26 @@ group: feature parent: wiki --- # Overview -## Attach items to uniform +- ## Attach items to uniform Enables player to attach IR grenades and chemlights to themselves. -## IR Strobe -Adds an attachable IR strobe, which is only visible using night vision devices and offers better visibility than IR grenades.re 2. + +- ## IR Strobe +Adds an attachable IR strobe, which is only visible using night vision devices and offers better visibility than IR grenades. # Usage -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. + - ## attaching to yourself +- Press the self interaction key +- go to the equipment section +- choose the item to attach + +same thing to detach + + - ##attaching to a vehicle +- Approach the vehicle and use the interaction key +- Attach item section +- Choose your item and where you want to place it + +to detach the item use the interaction key from outside the vehicle # Dependencies -List of modules that must be present for this module to work. +List of modules that must be present for this module to work. \ No newline at end of file diff --git a/documentation/feature/captives.md b/documentation/feature/captives.md index 305610cdce..0c38ecf8c8 100644 --- a/documentation/feature/captives.md +++ b/documentation/feature/captives.md @@ -5,16 +5,36 @@ group: feature parent: wiki --- # Overview -## Take captives +- ## Take captives Introduces a captivity system for taking and moving prisoners. -## Load and unload captives into / from vehicles -- needs documentaion - -## Frisk captives -- needs documentaion - + +- ## Load and unload captives into / from vehicles +You can load and unload captives from vehicles using ACE 3 interactions. + +- ## Frisk captives +You can frisk a restrained captive. + +- ## Surrendering +You can surrender, while surrendering AI will cease fire. # Usage -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. +- ## Capturing someone + - You need cable ties. + - Approach the victim / convict and use the interaction button. + - The interaction is around the hands in the form of a handcuffs icon. + - To free someone it's the same + - Use the interaction key, check around the hands for the handcuffs icon. + +- ## Escorting a captive + - Interact with the captive. + - Select the escort prisoner option. + - To stop escorting just scroll down or use self interaction. + +- ## Loading and unloading a captive in vehicle + - Escort the person. + - Approach the vehicle you desire to load the captive in. + - Interact with the vehicle and load him. + - Same for unloading, interact with the vehicle then unload. # Dependencies List of modules that must be present for this module to work. From aa0940e18015fc282d1ac488036f7b312391416c Mon Sep 17 00:00:00 2001 From: Dharma Bellamkonda <dharma.bellamkonda@gmail.com> Date: Wed, 13 May 2015 13:31:53 -0600 Subject: [PATCH 39/51] Document module dependencies Add a list of dependencies to each module's documentation. Also add a note to the documenation of modules which are a dependency for many other modules. Dependency lists are pulled from each module's config.cpp. --- documentation/feature/advanced_ballistics.md | 2 +- documentation/feature/ai.md | 2 +- documentation/feature/aircraft.md | 2 +- documentation/feature/apl.md | 2 +- documentation/feature/atragmx.md | 2 +- documentation/feature/attach.md | 2 +- documentation/feature/backpacks.md | 2 +- documentation/feature/ballistics.md | 2 +- documentation/feature/captives.md | 2 +- documentation/feature/common.md | 13 +++++++++++++ documentation/feature/difficulties.md | 2 +- documentation/feature/disarming.md | 2 +- documentation/feature/disposable.md | 2 +- documentation/feature/dragging.md | 2 +- documentation/feature/explosives.md | 2 +- documentation/feature/fcs.md | 2 +- documentation/feature/flashsuppressors.md | 2 +- documentation/feature/frag.md | 2 +- documentation/feature/gforces.md | 2 +- documentation/feature/goggles.md | 2 +- documentation/feature/grenades.md | 2 +- documentation/feature/hearing.md | 2 +- documentation/feature/hitreactions.md | 2 +- documentation/feature/interact_menu.md | 4 +++- documentation/feature/interaction.md | 4 +++- documentation/feature/inventory.md | 2 +- documentation/feature/javelin.md | 2 +- documentation/feature/kestrel4500.md | 2 +- documentation/feature/laser.md | 2 +- documentation/feature/laser_selfdesignate.md | 2 +- documentation/feature/laserpointer.md | 2 +- documentation/feature/logistics_uavbattery.md | 2 +- documentation/feature/logistics_wirecutter.md | 2 +- documentation/feature/magazinerepack.md | 2 +- documentation/feature/main.md | 13 +++++++++++++ documentation/feature/map.md | 2 +- documentation/feature/maptools.md | 2 +- documentation/feature/markers.md | 2 +- documentation/feature/medical-system.md | 3 +++ documentation/feature/microdagr.md | 2 +- documentation/feature/missileguidance.md | 2 +- documentation/feature/missionmodules.md | 2 +- documentation/feature/mk6mortar.md | 2 +- documentation/feature/movement.md | 2 +- documentation/feature/nametags.md | 2 +- documentation/feature/nightvision.md | 2 +- documentation/feature/noidle.md | 2 +- documentation/feature/noradio.md | 2 +- documentation/feature/norearm.md | 2 +- documentation/feature/optics.md | 2 +- documentation/feature/optionsmenu.md | 4 +++- documentation/feature/overheating.md | 2 +- documentation/feature/overpressure.md | 18 ++++++++++++++++++ documentation/feature/parachute.md | 2 +- documentation/feature/protection.md | 2 +- documentation/feature/ragdolls.md | 2 +- documentation/feature/realisticnames.md | 2 +- documentation/feature/recoil.md | 2 +- documentation/feature/reload.md | 2 +- documentation/feature/reloadlaunchers.md | 3 +-- documentation/feature/respawn.md | 2 +- documentation/feature/safemode.md | 2 +- documentation/feature/scopes.md | 2 +- documentation/feature/smallarms.md | 2 +- documentation/feature/switchunits.md | 2 +- documentation/feature/testmissions.md | 2 +- documentation/feature/thermals.md | 2 +- documentation/feature/vector.md | 2 +- documentation/feature/vehiclelock.md | 2 +- documentation/feature/vehicles.md | 2 +- documentation/feature/weaponselect.md | 2 +- documentation/feature/weather.md | 2 +- documentation/feature/windeflection.md | 2 +- 73 files changed, 122 insertions(+), 70 deletions(-) create mode 100644 documentation/feature/common.md create mode 100644 documentation/feature/main.md create mode 100644 documentation/feature/overpressure.md diff --git a/documentation/feature/advanced_ballistics.md b/documentation/feature/advanced_ballistics.md index fd44bb21b9..43db440b2d 100644 --- a/documentation/feature/advanced_ballistics.md +++ b/documentation/feature/advanced_ballistics.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_ballistics`, `ace_weather`, `ace_modules` diff --git a/documentation/feature/ai.md b/documentation/feature/ai.md index b82192b920..2f50572b99 100644 --- a/documentation/feature/ai.md +++ b/documentation/feature/ai.md @@ -24,4 +24,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/aircraft.md b/documentation/feature/aircraft.md index 6b99540466..0706d9912a 100644 --- a/documentation/feature/aircraft.md +++ b/documentation/feature/aircraft.md @@ -22,4 +22,4 @@ Adds a laser marker to the copilot seat of the Wildcat. Adds a HUD to the AH-9 based on the comanches HUD. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/apl.md b/documentation/feature/apl.md index fe69507f32..6f6b88794d 100644 --- a/documentation/feature/apl.md +++ b/documentation/feature/apl.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_main` diff --git a/documentation/feature/atragmx.md b/documentation/feature/atragmx.md index 77affe1326..0d96cdcc6e 100644 --- a/documentation/feature/atragmx.md +++ b/documentation/feature/atragmx.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common`, `ace_weather` diff --git a/documentation/feature/attach.md b/documentation/feature/attach.md index 7bf2c400e6..0a7d3a7e42 100644 --- a/documentation/feature/attach.md +++ b/documentation/feature/attach.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/backpacks.md b/documentation/feature/backpacks.md index ade414525f..ea10c7a24a 100644 --- a/documentation/feature/backpacks.md +++ b/documentation/feature/backpacks.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/ballistics.md b/documentation/feature/ballistics.md index 895f1e37ab..7a0bdc2931 100644 --- a/documentation/feature/ballistics.md +++ b/documentation/feature/ballistics.md @@ -25,4 +25,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/captives.md b/documentation/feature/captives.md index 305610cdce..7a1d24bce6 100644 --- a/documentation/feature/captives.md +++ b/documentation/feature/captives.md @@ -17,4 +17,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/common.md b/documentation/feature/common.md new file mode 100644 index 0000000000..36821a12e9 --- /dev/null +++ b/documentation/feature/common.md @@ -0,0 +1,13 @@ +--- +layout: wiki +title: Common +group: feature +parent: wiki +--- +# Overview +Module that provides common features required by many other modules. + +# Dependencies +`ace_main` + +Note: The Common module is required by many other modules. Disabling it is not recommended. \ No newline at end of file diff --git a/documentation/feature/difficulties.md b/documentation/feature/difficulties.md index 626576ee09..ad36f26e2c 100644 --- a/documentation/feature/difficulties.md +++ b/documentation/feature/difficulties.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/disarming.md b/documentation/feature/disarming.md index 7b30494adc..38fe114cb1 100644 --- a/documentation/feature/disarming.md +++ b/documentation/feature/disarming.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/disposable.md b/documentation/feature/disposable.md index dd634eb9c1..c1a5276f71 100644 --- a/documentation/feature/disposable.md +++ b/documentation/feature/disposable.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/dragging.md b/documentation/feature/dragging.md index 28d5c6089f..6b0d65c6ac 100644 --- a/documentation/feature/dragging.md +++ b/documentation/feature/dragging.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/explosives.md b/documentation/feature/explosives.md index 78f09d62bb..b5cd19dbf5 100644 --- a/documentation/feature/explosives.md +++ b/documentation/feature/explosives.md @@ -17,4 +17,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/fcs.md b/documentation/feature/fcs.md index 4eefe05e5b..3858def7dc 100644 --- a/documentation/feature/fcs.md +++ b/documentation/feature/fcs.md @@ -18,4 +18,4 @@ To engage moving targets, place the crosshair on the enemy vehicle and press and To use manual lasing, place the crosshair on the object to range and press and hold tab. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/flashsuppressors.md b/documentation/feature/flashsuppressors.md index 4217299857..cd510b7f6d 100644 --- a/documentation/feature/flashsuppressors.md +++ b/documentation/feature/flashsuppressors.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/frag.md b/documentation/feature/frag.md index 4d30c8d9f9..8a0d9fb667 100644 --- a/documentation/feature/frag.md +++ b/documentation/feature/frag.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/gforces.md b/documentation/feature/gforces.md index 73c3b321ed..e67a043ec7 100644 --- a/documentation/feature/gforces.md +++ b/documentation/feature/gforces.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/goggles.md b/documentation/feature/goggles.md index 1d77e342d4..af61102d4f 100644 --- a/documentation/feature/goggles.md +++ b/documentation/feature/goggles.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/grenades.md b/documentation/feature/grenades.md index 67918ae77b..05c2cc9341 100644 --- a/documentation/feature/grenades.md +++ b/documentation/feature/grenades.md @@ -17,4 +17,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/hearing.md b/documentation/feature/hearing.md index 32d4fce986..5c2e7e8aa7 100644 --- a/documentation/feature/hearing.md +++ b/documentation/feature/hearing.md @@ -16,4 +16,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/hitreactions.md b/documentation/feature/hitreactions.md index c109f10ddd..eae5c932ed 100644 --- a/documentation/feature/hitreactions.md +++ b/documentation/feature/hitreactions.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/interact_menu.md b/documentation/feature/interact_menu.md index d00ba6f977..50e72f495c 100644 --- a/documentation/feature/interact_menu.md +++ b/documentation/feature/interact_menu.md @@ -15,4 +15,6 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` + +Note: The Interact Menu module is required by many other modules. Disabling it is not recommended. diff --git a/documentation/feature/interaction.md b/documentation/feature/interaction.md index 36365342ae..8ef9caa6ef 100644 --- a/documentation/feature/interaction.md +++ b/documentation/feature/interaction.md @@ -15,4 +15,6 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interact_menu` + +Note: The Interaction module is required by many other modules. Disabling it is not recommended. diff --git a/documentation/feature/inventory.md b/documentation/feature/inventory.md index 8dac5b6644..12fd4d3d15 100644 --- a/documentation/feature/inventory.md +++ b/documentation/feature/inventory.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` \ No newline at end of file diff --git a/documentation/feature/javelin.md b/documentation/feature/javelin.md index 78102840c1..344ce39aab 100644 --- a/documentation/feature/javelin.md +++ b/documentation/feature/javelin.md @@ -25,4 +25,4 @@ Steps to lock titan/Javelin: CTRL+TAB is default key to change firemode (configurable as a key) # Dependencies -List of modules that must be present for this module to work. +`ace_main`, `ace_common`, `ace_missileguidance` diff --git a/documentation/feature/kestrel4500.md b/documentation/feature/kestrel4500.md index 0c6e03d304..4e4acf17ca 100644 --- a/documentation/feature/kestrel4500.md +++ b/documentation/feature/kestrel4500.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common`, `ace_weather` diff --git a/documentation/feature/laser.md b/documentation/feature/laser.md index 6e1de22002..f7dfd9533a 100644 --- a/documentation/feature/laser.md +++ b/documentation/feature/laser.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/laser_selfdesignate.md b/documentation/feature/laser_selfdesignate.md index 8405d57c43..367c3a9220 100644 --- a/documentation/feature/laser_selfdesignate.md +++ b/documentation/feature/laser_selfdesignate.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_laser` diff --git a/documentation/feature/laserpointer.md b/documentation/feature/laserpointer.md index c22471e320..a0e525236f 100644 --- a/documentation/feature/laserpointer.md +++ b/documentation/feature/laserpointer.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/logistics_uavbattery.md b/documentation/feature/logistics_uavbattery.md index 6cd3bc0b3b..cba26cd695 100644 --- a/documentation/feature/logistics_uavbattery.md +++ b/documentation/feature/logistics_uavbattery.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/logistics_wirecutter.md b/documentation/feature/logistics_wirecutter.md index 97d684e697..2c3a53f692 100644 --- a/documentation/feature/logistics_wirecutter.md +++ b/documentation/feature/logistics_wirecutter.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/magazinerepack.md b/documentation/feature/magazinerepack.md index e9ae26f315..146dcc148d 100644 --- a/documentation/feature/magazinerepack.md +++ b/documentation/feature/magazinerepack.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/main.md b/documentation/feature/main.md new file mode 100644 index 0000000000..667017a34f --- /dev/null +++ b/documentation/feature/main.md @@ -0,0 +1,13 @@ +--- +layout: wiki +title: Main +group: feature +parent: wiki +--- +# Overview +Main module which acts as the ACE core module. + +# Dependencies +Arma 3 and CBA + +Note: Note: The Common module is required by all other modules. Do not disable it! \ No newline at end of file diff --git a/documentation/feature/map.md b/documentation/feature/map.md index 88a3493d9e..596088f5e9 100644 --- a/documentation/feature/map.md +++ b/documentation/feature/map.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/maptools.md b/documentation/feature/maptools.md index 6814a5c1f5..de1b118a03 100644 --- a/documentation/feature/maptools.md +++ b/documentation/feature/maptools.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/markers.md b/documentation/feature/markers.md index eae1bfe333..f401004a88 100644 --- a/documentation/feature/markers.md +++ b/documentation/feature/markers.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/medical-system.md b/documentation/feature/medical-system.md index 443fb4b182..c0cf70e8d0 100644 --- a/documentation/feature/medical-system.md +++ b/documentation/feature/medical-system.md @@ -68,3 +68,6 @@ Morphine is used to alleviate large amounts of pain. Has an effect similar to He Epinephrine is used to increase heart rate and blood pressure and alleviate unconsciousness. Epinephrine is a synthetic form of Adrenaline, which is naturally produced in the body. It can also be applied to counter-act the effects of Atropine. Be careful though, as it may only be given once. _Epinephrine must never be given to a casualty with a high heart rate or blood pressure._ + +# Dependencies +`ace_interaction`, `ace_modules`, `ace_apl` \ No newline at end of file diff --git a/documentation/feature/microdagr.md b/documentation/feature/microdagr.md index a98730c9f4..f6ac61ddba 100644 --- a/documentation/feature/microdagr.md +++ b/documentation/feature/microdagr.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/missileguidance.md b/documentation/feature/missileguidance.md index fe5aa792b3..0ce4deb8eb 100644 --- a/documentation/feature/missileguidance.md +++ b/documentation/feature/missileguidance.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_laser` diff --git a/documentation/feature/missionmodules.md b/documentation/feature/missionmodules.md index 771a5ef290..3c7e7c49c5 100644 --- a/documentation/feature/missionmodules.md +++ b/documentation/feature/missionmodules.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/mk6mortar.md b/documentation/feature/mk6mortar.md index af718eedce..6560a7bf4c 100644 --- a/documentation/feature/mk6mortar.md +++ b/documentation/feature/mk6mortar.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/movement.md b/documentation/feature/movement.md index f1d9d93df9..5807701900 100644 --- a/documentation/feature/movement.md +++ b/documentation/feature/movement.md @@ -21,4 +21,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/nametags.md b/documentation/feature/nametags.md index 10ff3404c0..01c357b8e8 100644 --- a/documentation/feature/nametags.md +++ b/documentation/feature/nametags.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/nightvision.md b/documentation/feature/nightvision.md index efdc5721c5..84f0721286 100644 --- a/documentation/feature/nightvision.md +++ b/documentation/feature/nightvision.md @@ -20,4 +20,4 @@ Enables the user to manually adjust NVG brightness. Use Alt+PageUp and Alt+PageDown to adjust NVG brightness. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/noidle.md b/documentation/feature/noidle.md index aa6657728d..c8f64aeeb5 100644 --- a/documentation/feature/noidle.md +++ b/documentation/feature/noidle.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/noradio.md b/documentation/feature/noradio.md index f9a832abd0..ae7aefa304 100644 --- a/documentation/feature/noradio.md +++ b/documentation/feature/noradio.md @@ -14,4 +14,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/norearm.md b/documentation/feature/norearm.md index 7ed7a5c515..5f3d0eeeee 100644 --- a/documentation/feature/norearm.md +++ b/documentation/feature/norearm.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/optics.md b/documentation/feature/optics.md index 90b486bc88..d77f224a7b 100644 --- a/documentation/feature/optics.md +++ b/documentation/feature/optics.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/optionsmenu.md b/documentation/feature/optionsmenu.md index a0c9ad33da..76cf28d06f 100644 --- a/documentation/feature/optionsmenu.md +++ b/documentation/feature/optionsmenu.md @@ -15,4 +15,6 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` + +Note: The Options Menu module is utilized by many other modules. Disabling it is not recommended. diff --git a/documentation/feature/overheating.md b/documentation/feature/overheating.md index 3a10bf9f48..2c8cfee7e1 100644 --- a/documentation/feature/overheating.md +++ b/documentation/feature/overheating.md @@ -24,4 +24,4 @@ To clear a jammed weapon, press Shift+R. *needs documentation on swapping barrels* # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/overpressure.md b/documentation/feature/overpressure.md new file mode 100644 index 0000000000..3c20a00c51 --- /dev/null +++ b/documentation/feature/overpressure.md @@ -0,0 +1,18 @@ +--- +layout: wiki +title: Overpressure +group: feature +parent: wiki +--- +# Overview +## Sub-feature 1 +Short description of sub-feature 1. +## Sub-feature 2 +Short description of sub-feature 2. + +# Usage +Short overview of how to use the feature, e.g. menu options, key bindings, +instructions. May not apply to all modules. + +# Dependencies +`ace_common` diff --git a/documentation/feature/parachute.md b/documentation/feature/parachute.md index 48ad0e9836..f01688082d 100644 --- a/documentation/feature/parachute.md +++ b/documentation/feature/parachute.md @@ -19,4 +19,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` \ No newline at end of file diff --git a/documentation/feature/protection.md b/documentation/feature/protection.md index 2eb2a9aaef..cc81793469 100644 --- a/documentation/feature/protection.md +++ b/documentation/feature/protection.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/ragdolls.md b/documentation/feature/ragdolls.md index 585c6c71a8..b71c3e3f75 100644 --- a/documentation/feature/ragdolls.md +++ b/documentation/feature/ragdolls.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/realisticnames.md b/documentation/feature/realisticnames.md index 64d9a316cb..22739dbde5 100644 --- a/documentation/feature/realisticnames.md +++ b/documentation/feature/realisticnames.md @@ -14,4 +14,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/recoil.md b/documentation/feature/recoil.md index 919ab24836..1e1fada65c 100644 --- a/documentation/feature/recoil.md +++ b/documentation/feature/recoil.md @@ -17,4 +17,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/reload.md b/documentation/feature/reload.md index f791521a63..2e26f90212 100644 --- a/documentation/feature/reload.md +++ b/documentation/feature/reload.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/reloadlaunchers.md b/documentation/feature/reloadlaunchers.md index 7b1f26cea1..17312a8f0f 100644 --- a/documentation/feature/reloadlaunchers.md +++ b/documentation/feature/reloadlaunchers.md @@ -15,5 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. -r \ No newline at end of file +`ace_interaction` diff --git a/documentation/feature/respawn.md b/documentation/feature/respawn.md index 6059f33c59..9dc50650c2 100644 --- a/documentation/feature/respawn.md +++ b/documentation/feature/respawn.md @@ -17,4 +17,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/safemode.md b/documentation/feature/safemode.md index ea4f3fe902..ba150df353 100644 --- a/documentation/feature/safemode.md +++ b/documentation/feature/safemode.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/scopes.md b/documentation/feature/scopes.md index fb29c7d6e1..9f7c54488c 100644 --- a/documentation/feature/scopes.md +++ b/documentation/feature/scopes.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/smallarms.md b/documentation/feature/smallarms.md index 11e68d4373..2dbf5359e8 100644 --- a/documentation/feature/smallarms.md +++ b/documentation/feature/smallarms.md @@ -17,4 +17,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/switchunits.md b/documentation/feature/switchunits.md index 71ace0e055..7744a492b1 100644 --- a/documentation/feature/switchunits.md +++ b/documentation/feature/switchunits.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/testmissions.md b/documentation/feature/testmissions.md index 7d7ac52af8..f01c61d1ba 100644 --- a/documentation/feature/testmissions.md +++ b/documentation/feature/testmissions.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/thermals.md b/documentation/feature/thermals.md index 12f79a311b..099758b3e9 100644 --- a/documentation/feature/thermals.md +++ b/documentation/feature/thermals.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/vector.md b/documentation/feature/vector.md index 277f5eb524..31f9b0adcf 100644 --- a/documentation/feature/vector.md +++ b/documentation/feature/vector.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/vehiclelock.md b/documentation/feature/vehiclelock.md index 239661d153..8947264de7 100644 --- a/documentation/feature/vehiclelock.md +++ b/documentation/feature/vehiclelock.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_interaction` diff --git a/documentation/feature/vehicles.md b/documentation/feature/vehicles.md index 534bb35171..22be943876 100644 --- a/documentation/feature/vehicles.md +++ b/documentation/feature/vehicles.md @@ -29,4 +29,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/weaponselect.md b/documentation/feature/weaponselect.md index 872e27cad0..6d8c11be90 100644 --- a/documentation/feature/weaponselect.md +++ b/documentation/feature/weaponselect.md @@ -21,4 +21,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common` diff --git a/documentation/feature/weather.md b/documentation/feature/weather.md index 2cbeea5e7e..06084cc5d0 100644 --- a/documentation/feature/weather.md +++ b/documentation/feature/weather.md @@ -15,4 +15,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_common`, `ace_modules` diff --git a/documentation/feature/windeflection.md b/documentation/feature/windeflection.md index 7bca0b0f60..ba261700c0 100644 --- a/documentation/feature/windeflection.md +++ b/documentation/feature/windeflection.md @@ -13,4 +13,4 @@ Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies -List of modules that must be present for this module to work. +`ace_weather` From 5c7fd9cf90d153b9ae6c4cfd5188d56b827e0ed5 Mon Sep 17 00:00:00 2001 From: Dharma Bellamkonda <dharma.bellamkonda@gmail.com> Date: Wed, 13 May 2015 13:42:14 -0600 Subject: [PATCH 40/51] Correct module name in documentation --- documentation/feature/main.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/feature/main.md b/documentation/feature/main.md index 667017a34f..07657502ce 100644 --- a/documentation/feature/main.md +++ b/documentation/feature/main.md @@ -10,4 +10,4 @@ Main module which acts as the ACE core module. # Dependencies Arma 3 and CBA -Note: Note: The Common module is required by all other modules. Do not disable it! \ No newline at end of file +Note: Note: The Main module is required by all other modules. Do not disable it! \ No newline at end of file From 95bcb157795c3eda937bd268b53676f99d473d3f Mon Sep 17 00:00:00 2001 From: Josuan Albin <alganthe@live.fr> Date: Thu, 14 May 2015 00:45:46 +0200 Subject: [PATCH 41/51] Documentation pass : typos fixed some typos and removed some lines that dharmab is going to add. --- documentation/feature/ai.md | 6 ------ documentation/feature/aircraft.md | 5 +---- documentation/feature/attach.md | 5 +---- documentation/feature/captives.md | 5 +---- 4 files changed, 3 insertions(+), 18 deletions(-) diff --git a/documentation/feature/ai.md b/documentation/feature/ai.md index 6e04720af5..cf74e76688 100644 --- a/documentation/feature/ai.md +++ b/documentation/feature/ai.md @@ -22,9 +22,3 @@ Some weapons had minimum engagement ranges. If you were as close as 2 meters to - ## No scripting All changes of ACE 3 AI are config based to ensure full compatibility with advanced AI modifications like ASR AI. - -# Usage -Nothing - -# Dependencies -None \ No newline at end of file diff --git a/documentation/feature/aircraft.md b/documentation/feature/aircraft.md index 156c75a384..ec263bb702 100644 --- a/documentation/feature/aircraft.md +++ b/documentation/feature/aircraft.md @@ -32,7 +32,4 @@ Adds a HUD to the AH-9 based on the comanches HUD. # Usage - ## switching flare mode: -the fefault keybind is ```ctrl + c``` - -# Dependencies -None \ No newline at end of file +the default keybind is ```ctrl + c``` \ No newline at end of file diff --git a/documentation/feature/attach.md b/documentation/feature/attach.md index 257151739a..d9482354af 100644 --- a/documentation/feature/attach.md +++ b/documentation/feature/attach.md @@ -24,7 +24,4 @@ same thing to detach - Attach item section - Choose your item and where you want to place it -to detach the item use the interaction key from outside the vehicle - -# Dependencies -List of modules that must be present for this module to work. \ No newline at end of file +to detach the item use the interaction key from outside the vehicle \ No newline at end of file diff --git a/documentation/feature/captives.md b/documentation/feature/captives.md index 0c38ecf8c8..5157a20bb5 100644 --- a/documentation/feature/captives.md +++ b/documentation/feature/captives.md @@ -34,7 +34,4 @@ You can surrender, while surrendering AI will cease fire. - Escort the person. - Approach the vehicle you desire to load the captive in. - Interact with the vehicle and load him. - - Same for unloading, interact with the vehicle then unload. - -# Dependencies -List of modules that must be present for this module to work. + - Same for unloading, interact with the vehicle then unload. \ No newline at end of file From b13d44fb6b1883f12a9aabc12d5af97efa444907 Mon Sep 17 00:00:00 2001 From: jaynus <jaynus@gmail.com> Date: Wed, 13 May 2015 17:29:09 -0700 Subject: [PATCH 42/51] Fixed: Litter spawning at huge radius, floating litter over water. Fixes #1112 --- addons/medical/functions/fnc_createLitter.sqf | 12 +++++++++--- addons/medical/functions/fnc_handleCreateLitter.sqf | 5 ++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/addons/medical/functions/fnc_createLitter.sqf b/addons/medical/functions/fnc_createLitter.sqf index 8682cc24d5..6797785763 100644 --- a/addons/medical/functions/fnc_createLitter.sqf +++ b/addons/medical/functions/fnc_createLitter.sqf @@ -38,12 +38,18 @@ _litter = getArray (_config >> "litter"); _createLitter = { private["_position", "_litterClass", "_direction"]; - _position = getPos (_this select 0); + + // @TODO: handle carriers over water + // For now, don't spawn litter if we are over water to avoid floating litter + if(surfaceIsWater (getPos (_this select 0))) exitWith { false }; + + _position = getPosATL (_this select 0); + _position = [_position select 0, _position select 1, 0]; _litterClass = _this select 1; if (random(1) >= 0.5) then { - _position = [(_position select 0) + random 2, (_position select 1) + random 2, _position select 2]; + _position = [(_position select 0) + random 1, (_position select 1) + random 1, _position select 2]; } else { - _position = [(_position select 0) - random 2, (_position select 1) - random 2, _position select 2]; + _position = [(_position select 0) - random 1, (_position select 1) - random 1, _position select 2]; }; _direction = (random 360); diff --git a/addons/medical/functions/fnc_handleCreateLitter.sqf b/addons/medical/functions/fnc_handleCreateLitter.sqf index 617d05e519..848bdb268c 100644 --- a/addons/medical/functions/fnc_handleCreateLitter.sqf +++ b/addons/medical/functions/fnc_handleCreateLitter.sqf @@ -14,7 +14,10 @@ if (isNil QGVAR(allCreatedLitter)) then { _litterObject = _litterClass createVehicleLocal _position; _litterObject setDir _direction; - +_litterObject setPosATL _position; +// Move the litter next frame to get rid of HORRIBLE spacing, fixes #1112 +[{ (_this select 0) setPosATL (_this select 1); }, [_litterObject, _position], 0, 0] call EFUNC(common,waitAndExecute); + _maxLitterCount = getArray (configFile >> "ACE_Settings" >> QGVAR(litterSimulationDetail) >> "_values") select GVAR(litterSimulationDetail); if((count GVAR(allCreatedLitter)) > _maxLitterCount ) then { // gank the first litter object, and spawn ours. From ca1ff8382ca4e83997f0feb0d412fbef68388e56 Mon Sep 17 00:00:00 2001 From: Grzegorz <gienkov.grzegorz@gmail.com> Date: Thu, 14 May 2015 14:33:33 +0200 Subject: [PATCH 43/51] Tabs fixed --- addons/nametags/config.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addons/nametags/config.cpp b/addons/nametags/config.cpp index 7a0086bfb6..b14873779c 100644 --- a/addons/nametags/config.cpp +++ b/addons/nametags/config.cpp @@ -27,7 +27,7 @@ class ACE_Settings { typeName = "SCALAR"; isClientSettable = 1; displayName = "$STR_ACE_NameTags_ShowPlayerNames"; - description = "$STR_ACE_NameTags_ShowPlayerNames_Desc"; + description = "$STR_ACE_NameTags_ShowPlayerNames_Desc"; values[] = {"$STR_ACE_Common_Disabled", "$STR_ACE_Common_Enabled", "$STR_ACE_Common_OnlyCursor", "$STR_ACE_Common_OnlyOnKeypress", "$STR_ACE_Common_OnlyCursorAndKeyPress"}; }; class GVAR(showPlayerRanks) { @@ -58,7 +58,7 @@ class ACE_Settings { typeName = "SCALAR"; isClientSettable = 1; displayName = "$STR_ACE_NameTags_ShowSoundWaves"; - description = "$STR_ACE_NameTags_ShowSoundWaves_Desc"; + description = "$STR_ACE_NameTags_ShowSoundWaves_Desc"; values[] = {"$STR_ACE_Common_Disabled", "$STR_ACE_Common_NameTagSettings", "$STR_ACE_Common_AlwaysShowAll"}; }; class GVAR(PlayerNamesViewDistance) { From a167336b40d03ec5ec191aec1540843cf6fa1335 Mon Sep 17 00:00:00 2001 From: ulteq <ulteq@web.de> Date: Thu, 14 May 2015 15:39:29 +0200 Subject: [PATCH 44/51] Made the Kestrel menu persistent --- addons/kestrel4500/XEH_postInit.sqf | 4 +++- addons/kestrel4500/XEH_preInit.sqf | 7 ++++--- .../functions/fnc_buttonPressed.sqf | 1 + .../kestrel4500/functions/fnc_collectData.sqf | 6 +++--- .../functions/fnc_restoreUserData.sqf | 18 ++++++++++++++++++ .../functions/fnc_storeUserData.sqf | 18 ++++++++++++++++++ 6 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 addons/kestrel4500/functions/fnc_restoreUserData.sqf create mode 100644 addons/kestrel4500/functions/fnc_storeUserData.sqf diff --git a/addons/kestrel4500/XEH_postInit.sqf b/addons/kestrel4500/XEH_postInit.sqf index 24a972c326..eb22aa1de2 100644 --- a/addons/kestrel4500/XEH_postInit.sqf +++ b/addons/kestrel4500/XEH_postInit.sqf @@ -22,4 +22,6 @@ GVAR(MeasuredWindSpeed) = 0; GVAR(ImpellerState) = 0; GVAR(Kestrel4500) = false; -GVAR(Overlay) = false; \ No newline at end of file +GVAR(Overlay) = false; + +[] call FUNC(restoreUserData); \ No newline at end of file diff --git a/addons/kestrel4500/XEH_preInit.sqf b/addons/kestrel4500/XEH_preInit.sqf index 4e29b9bdbf..7b36167a16 100644 --- a/addons/kestrel4500/XEH_preInit.sqf +++ b/addons/kestrel4500/XEH_preInit.sqf @@ -9,10 +9,11 @@ PREP(createKestrelDialog); PREP(displayKestrel); PREP(generateOutputData); PREP(measureWindSpeed); +PREP(onCloseDialog); +PREP(onCloseDisplay); +PREP(restoreUserData); +PREP(storeUserData); PREP(updateDisplay); PREP(updateImpellerState); -PREP(onCloseDialog); -PREP(onCloseDisplay); - ADDON = true; diff --git a/addons/kestrel4500/functions/fnc_buttonPressed.sqf b/addons/kestrel4500/functions/fnc_buttonPressed.sqf index f0f9a10db1..1d73f9ac79 100644 --- a/addons/kestrel4500/functions/fnc_buttonPressed.sqf +++ b/addons/kestrel4500/functions/fnc_buttonPressed.sqf @@ -51,3 +51,4 @@ switch (_this) do { }; [] call FUNC(updateDisplay); +[] call FUNC(storeUserData); diff --git a/addons/kestrel4500/functions/fnc_collectData.sqf b/addons/kestrel4500/functions/fnc_collectData.sqf index a812ad0f7c..ddd9fcb962 100644 --- a/addons/kestrel4500/functions/fnc_collectData.sqf +++ b/addons/kestrel4500/functions/fnc_collectData.sqf @@ -42,9 +42,9 @@ if (GVAR(MinAvgMaxMode) == 1) then { // Wind SPD _windSpeed = call FUNC(measureWindSpeed); - GVAR(MIN) set [1, (GVAR(MIN) select 1) min abs(_windSpeed)]; - GVAR(MAX) set [1, abs(_windSpeed) max (GVAR(MAX) select 1)]; - GVAR(TOTAL) set [1, (GVAR(TOTAL) select 1) + abs(_windSpeed)]; + GVAR(MIN) set [1, (GVAR(MIN) select 1) min _windSpeed]; + GVAR(MAX) set [1, _windSpeed max (GVAR(MAX) select 1)]; + GVAR(TOTAL) set [1, (GVAR(TOTAL) select 1) + _windSpeed]; // CROSSWIND _crosswind = 0; diff --git a/addons/kestrel4500/functions/fnc_restoreUserData.sqf b/addons/kestrel4500/functions/fnc_restoreUserData.sqf new file mode 100644 index 0000000000..3cd96d80af --- /dev/null +++ b/addons/kestrel4500/functions/fnc_restoreUserData.sqf @@ -0,0 +1,18 @@ +/* + * Author: Ruthberg + * Reads user data from profileNamespace + * + * Arguments: + * Nothing + * + * Return Value: + * Nothing + * + * Example: + * call ace_kestrel4500_fnc_restore_user_data + * + * Public: No + */ +#include "script_component.hpp" + +GVAR(Menu) = 0 max (profileNamespace getVariable ["ACE_Kestrel4500_menu", 0]) min ((count GVAR(Menus)) - 1); diff --git a/addons/kestrel4500/functions/fnc_storeUserData.sqf b/addons/kestrel4500/functions/fnc_storeUserData.sqf new file mode 100644 index 0000000000..3b7ce9dd4d --- /dev/null +++ b/addons/kestrel4500/functions/fnc_storeUserData.sqf @@ -0,0 +1,18 @@ +/* + * Author: Ruthberg + * Saves user data into profileNamespace + * + * Arguments: + * Nothing + * + * Return Value: + * Nothing + * + * Example: + * call ace_kestrel4500_fnc_store_user_data + * + * Public: No + */ +#include "script_component.hpp" + +profileNamespace setVariable ["ACE_Kestrel4500_menu", GVAR(menu)]; From 33b94be5ff294a7fa9031f512b00ac5add308eae Mon Sep 17 00:00:00 2001 From: KoffeinFlummi <koffeinflummi@gmail.com> Date: Thu, 14 May 2015 16:02:01 +0200 Subject: [PATCH 45/51] Insert additional newlines --- documentation/feature/advanced_ballistics.md | 8 +++- documentation/feature/ai.md | 11 +++-- documentation/feature/aircraft.md | 23 ++++++---- documentation/feature/apl.md | 8 +++- documentation/feature/atragmx.md | 9 +++- documentation/feature/attach.md | 14 ++++-- documentation/feature/backpacks.md | 8 +++- documentation/feature/ballistics.md | 25 +++++++--- documentation/feature/captives.md | 46 ++++++++++--------- documentation/feature/difficulties.md | 8 +++- documentation/feature/disarming.md | 11 ++++- documentation/feature/disposable.md | 8 +++- documentation/feature/dragging.md | 10 +++- documentation/feature/explosives.md | 14 ++++-- documentation/feature/fcs.md | 14 ++++-- documentation/feature/flashsuppressors.md | 11 ++++- documentation/feature/frag.md | 11 ++++- documentation/feature/gforces.md | 11 ++++- documentation/feature/goggles.md | 8 +++- documentation/feature/grenades.md | 14 ++++-- documentation/feature/hearing.md | 11 ++++- documentation/feature/hitreactions.md | 11 ++++- documentation/feature/interact_menu.md | 11 ++++- documentation/feature/interaction.md | 7 +++ documentation/feature/inventory.md | 6 +++ documentation/feature/javelin.md | 7 +++ documentation/feature/kestrel4500.md | 7 +++ documentation/feature/laser.md | 7 +++ documentation/feature/laser_selfdesignate.md | 7 +++ documentation/feature/laserpointer.md | 7 +++ documentation/feature/logistics_uavbattery.md | 7 +++ documentation/feature/logistics_wirecutter.md | 7 +++ documentation/feature/magazinerepack.md | 6 +++ documentation/feature/map.md | 7 +++ documentation/feature/maptools.md | 7 +++ documentation/feature/markers.md | 6 +++ documentation/feature/microdagr.md | 7 +++ documentation/feature/missileguidance.md | 7 +++ documentation/feature/missionmodules.md | 7 +++ documentation/feature/mk6mortar.md | 7 +++ documentation/feature/movement.md | 10 ++++ documentation/feature/nametags.md | 6 +++ documentation/feature/nightvision.md | 8 ++++ documentation/feature/noidle.md | 7 +++ documentation/feature/noradio.md | 6 +++ documentation/feature/norearm.md | 7 +++ documentation/feature/optics.md | 7 +++ documentation/feature/optionsmenu.md | 7 +++ documentation/feature/ovepressure.md | 7 +++ documentation/feature/overheating.md | 8 ++++ documentation/feature/parachute.md | 8 ++++ documentation/feature/protection.md | 7 +++ documentation/feature/ragdolls.md | 6 +++ documentation/feature/realisticnames.md | 6 +++ documentation/feature/recoil.md | 8 ++++ documentation/feature/reload.md | 6 +++ documentation/feature/reloadlaunchers.md | 11 +++-- documentation/feature/respawn.md | 8 ++++ documentation/feature/safemode.md | 6 +++ documentation/feature/scopes.md | 6 +++ documentation/feature/smallarms.md | 8 ++++ documentation/feature/switchunits.md | 7 +++ documentation/feature/testmissions.md | 7 +++ documentation/feature/thermals.md | 6 +++ documentation/feature/vector.md | 6 +++ documentation/feature/vehiclelock.md | 7 +++ documentation/feature/vehicles.md | 14 ++++++ documentation/feature/weaponselect.md | 10 ++++ documentation/feature/weather.md | 7 +++ documentation/feature/windeflection.md | 6 +++ 70 files changed, 558 insertions(+), 86 deletions(-) diff --git a/documentation/feature/advanced_ballistics.md b/documentation/feature/advanced_ballistics.md index fd44bb21b9..9b601aa397 100644 --- a/documentation/feature/advanced_ballistics.md +++ b/documentation/feature/advanced_ballistics.md @@ -4,12 +4,16 @@ title: Advanced Ballistics group: feature parent: wiki --- + # Overview -## Sub-feature 1 + +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 + +### Sub-feature 2 Short description of sub-feature 2. + # Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. diff --git a/documentation/feature/ai.md b/documentation/feature/ai.md index cf74e76688..a6ef524b25 100644 --- a/documentation/feature/ai.md +++ b/documentation/feature/ai.md @@ -7,18 +7,19 @@ parent: wiki --- # Overview -- ## Adjusted AI skill values + +### Adjusted AI skill values The idea here is to reduce the AI's godlike aiming capabilties while retaining it's high intelligence. The AI should be smart enough to move through a town, but also be 'human' in their reaction time and aim. Note: All these values can still be adjusted via scripts, these arrays just change what 0 & 1 are for setSkill. -- ## Firing in burst mode +### Firing in burst mode AIs will now use the automatic mode of their weapons on short distances, instead of always relying on firing single shots in quick succession. -- ## Longer engagement ranges +### Longer engagement ranges The maximum engagement ranges are increased: AI will fire in bursts with variable length on high ranges of 500 - 700 meters, depending on their weapon and optic. -- ## No deadzones in CQB +### No deadzones in CQB Some weapons had minimum engagement ranges. If you were as close as 2 meters to an AAF soldier, he wouldn't open fire, because the AI couldn't find any valid fire mode for their weapon. ACE 3 removes this behaviour mostly notable in CQB by adding a valid firing mode. -- ## No scripting +### No scripting All changes of ACE 3 AI are config based to ensure full compatibility with advanced AI modifications like ASR AI. diff --git a/documentation/feature/aircraft.md b/documentation/feature/aircraft.md index ec263bb702..094d328417 100644 --- a/documentation/feature/aircraft.md +++ b/documentation/feature/aircraft.md @@ -5,31 +5,34 @@ group: feature order: 5 parent: wiki --- + # Overview -- ## Adjusted flight behaviour + +### Adjusted flight behaviour Changes the flight behaviour of various aircraft. -- ## Various adjustments to aircraft and gunships munitions +### Various adjustments to aircraft and gunships munitions - Higher capacity magazines for the comanche. - Gatling rate of fire (ROF) increased. - AP rockets have less splash damage. - -- ## Missile lock warnings +### Missile lock warnings Adds missile-lock warning systems to helicopters and planes based on the various real life capabilities. -- ## Semi-automatic flare mode +### Semi-automatic flare mode Adds the semi-automatic flare mode known from Arma 2. The key to switch the mode still exists in Arma 3's key settings, but is unused. -- ## Ejecting from pilot and copilot seats +### Ejecting from pilot and copilot seats Pilots and copilots of all helicopters can now eject. -- ## Laser marker for wildcat +### Laser marker for wildcat Adds a laser marker to the copilot seat of the Wildcat. -- ## HUD for AH-9 + +### HUD for AH-9 Adds a HUD to the AH-9 based on the comanches HUD. + # Usage -- ## switching flare mode: -the default keybind is ```ctrl + c``` \ No newline at end of file +### Adjusted flight behaviour +Changes the flight behaviour of various aircraft. diff --git a/documentation/feature/apl.md b/documentation/feature/apl.md index fe69507f32..9ac140018d 100644 --- a/documentation/feature/apl.md +++ b/documentation/feature/apl.md @@ -4,15 +4,19 @@ title: APL group: feature parent: wiki --- + # Overview -## Sub-feature 1 + +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. + # Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/atragmx.md b/documentation/feature/atragmx.md index 77affe1326..10a0a4e32e 100644 --- a/documentation/feature/atragmx.md +++ b/documentation/feature/atragmx.md @@ -4,15 +4,20 @@ title: ATragMX group: feature parent: wiki --- + # Overview -## Sub-feature 1 + +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 + +### Sub-feature 2 Short description of sub-feature 2. + # Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/attach.md b/documentation/feature/attach.md index d9482354af..359b9e5800 100644 --- a/documentation/feature/attach.md +++ b/documentation/feature/attach.md @@ -4,24 +4,28 @@ title: Attach group: feature parent: wiki --- + # Overview -- ## Attach items to uniform + +### Attach items to uniform Enables player to attach IR grenades and chemlights to themselves. -- ## IR Strobe +### IR Strobe Adds an attachable IR strobe, which is only visible using night vision devices and offers better visibility than IR grenades. + # Usage - - ## attaching to yourself + +### attaching to yourself - Press the self interaction key - go to the equipment section - choose the item to attach same thing to detach - - ##attaching to a vehicle +### attaching to a vehicle - Approach the vehicle and use the interaction key - Attach item section - Choose your item and where you want to place it -to detach the item use the interaction key from outside the vehicle \ No newline at end of file +to detach the item use the interaction key from outside the vehicle diff --git a/documentation/feature/backpacks.md b/documentation/feature/backpacks.md index ade414525f..b0ec4a31d1 100644 --- a/documentation/feature/backpacks.md +++ b/documentation/feature/backpacks.md @@ -4,13 +4,19 @@ title: Backpacks group: feature parent: wiki --- + # Overview -## Lock backpack + +### Lock backpack Adds the ability to lock backpacks. Locked backpacks can't be accessed by others. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/ballistics.md b/documentation/feature/ballistics.md index 3168389859..c2748526db 100644 --- a/documentation/feature/ballistics.md +++ b/documentation/feature/ballistics.md @@ -4,25 +4,36 @@ title: Ballistics group: feature parent: wiki --- + # Overview -## Realistic rifle ammunition + +### Realistic rifle ammunition Changes include adjusted muzzle velocity, air friction and dispersion based on real life values. -## Body armour nerf + +### Body armour nerf Nerfs protection values of vests, CSAT uniforms and various campaign only gear to more realistic levels comparable to Arma 2 levels. -## Realistic silencers and sub-sonic ammunition + +### Realistic silencers and sub-sonic ammunition Silencers no longer decrease the muzzle velocity and are generally less effective when used with normal ammunition. They now only remove the muzzle blast and flash. To prevent the crack caused by super sonic projectiles, ACE introduces sub sonic ammunition. This is also fully compatible with AI. Sub sonic ammunition is available for the calibers 5.56mm, 6.5mm and 7.62mm. -## Armour piercing ammunition + +### Armour piercing ammunition Armour piercing rounds have higher penetration values against light armoured targets or other obstacles on the battlefield. Their drawback is a slighly decreased man-stopping power. AP rounds are available for the calibers 5.56mm, 6.5mm and 7.62mm. -## IR-Dim tracer ammunition + +### IR-Dim tracer ammunition IR-Dim ammunition is similar to tracer rounds, but their tracers are only visible using night vision devices. -## M118 Long range ammunition + +### M118 Long range ammunition The M14 EBR now uses ammunition with decreased muzzle velocity and air friction to improve precission on long ranges. -## Flash suppressors + +### Flash suppressors Flash suppressors are similar to sound suppressors and prevent the muzzle flash reducing visibilty without decreasing combat effectiveness. Flash suppressors are available for the calibers 5.56mm, 6.5mm, 7.62mm, .45 ACP and 9mm. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/captives.md b/documentation/feature/captives.md index 5157a20bb5..0b04167f08 100644 --- a/documentation/feature/captives.md +++ b/documentation/feature/captives.md @@ -4,34 +4,38 @@ title: Captives group: feature parent: wiki --- + # Overview -- ## Take captives + +### Take captives Introduces a captivity system for taking and moving prisoners. -- ## Load and unload captives into / from vehicles +### Load and unload captives into / from vehicles You can load and unload captives from vehicles using ACE 3 interactions. -- ## Frisk captives +### Frisk captives You can frisk a restrained captive. -- ## Surrendering +### Surrendering You can surrender, while surrendering AI will cease fire. -# Usage -- ## Capturing someone - - You need cable ties. - - Approach the victim / convict and use the interaction button. - - The interaction is around the hands in the form of a handcuffs icon. - - To free someone it's the same - - Use the interaction key, check around the hands for the handcuffs icon. - -- ## Escorting a captive - - Interact with the captive. - - Select the escort prisoner option. - - To stop escorting just scroll down or use self interaction. -- ## Loading and unloading a captive in vehicle - - Escort the person. - - Approach the vehicle you desire to load the captive in. - - Interact with the vehicle and load him. - - Same for unloading, interact with the vehicle then unload. \ No newline at end of file +# Usage + +### Capturing someone +- You need cable ties. +- Approach the victim / convict and use the interaction button. +- The interaction is around the hands in the form of a handcuffs icon. +- To free someone it's the same +- Use the interaction key, check around the hands for the handcuffs icon. + +### Escorting a captive +- Interact with the captive. +- Select the escort prisoner option. +- To stop escorting just scroll down or use self interaction. + +### Loading and unloading a captive in vehicle +- Escort the person. +- Approach the vehicle you desire to load the captive in. +- Interact with the vehicle and load him. +- Same for unloading, interact with the vehicle then unload. diff --git a/documentation/feature/difficulties.md b/documentation/feature/difficulties.md index 626576ee09..309725a252 100644 --- a/documentation/feature/difficulties.md +++ b/documentation/feature/difficulties.md @@ -4,13 +4,19 @@ title: Difficulties group: feature parent: wiki --- + # Overview -## Elite mode adjustments + +### Elite mode adjustments Adjusts the default settings for the hardest difficulty to more closely resemble A2 settings. (No crosshair, stat screen, death messages...) + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/disarming.md b/documentation/feature/disarming.md index 7b30494adc..10674a7626 100644 --- a/documentation/feature/disarming.md +++ b/documentation/feature/disarming.md @@ -4,15 +4,22 @@ title: Disarming group: feature parent: wiki --- + # Overview -## Sub-feature 1 + +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 + +### Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/disposable.md b/documentation/feature/disposable.md index dd634eb9c1..dc072f2dc9 100644 --- a/documentation/feature/disposable.md +++ b/documentation/feature/disposable.md @@ -4,13 +4,19 @@ title: Disposable group: feature parent: wiki --- + # Overview -## NLAW disposable anti tank weapon + +### NLAW disposable anti tank weapon Makes the NLAW disposable and provides the tools for other addons to do the same. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/dragging.md b/documentation/feature/dragging.md index 28d5c6089f..80eb6a5099 100644 --- a/documentation/feature/dragging.md +++ b/documentation/feature/dragging.md @@ -4,15 +4,21 @@ title: Dragging group: feature parent: wiki --- + # Overview -## Sub-feature 1 + +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/explosives.md b/documentation/feature/explosives.md index 78f09d62bb..7971bf49fb 100644 --- a/documentation/feature/explosives.md +++ b/documentation/feature/explosives.md @@ -4,17 +4,25 @@ title: Explosives group: feature parent: wiki --- + # Overview -## Advanced explosives placement + +### Advanced explosives placement Enables more precise placement of explosives. -## More trigger types + +### More trigger types Offers different trigger types, like clackers and dead man switches. -## Attack explosives to vehicles + +### Attack explosives to vehicles Enables attaching explosives to vehicles. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/fcs.md b/documentation/feature/fcs.md index 4eefe05e5b..81a3c7553c 100644 --- a/documentation/feature/fcs.md +++ b/documentation/feature/fcs.md @@ -4,18 +4,26 @@ title: FCS (Fire Control System) group: feature parent: wiki --- + # Overview -## Fire control system + +### Fire control system Offers a custom fire control system for tanks and helicopters. It enables engaging stationary and moving targets. -## Manual lasing targets + +### Manual lasing targets Changes the default rangefinders, including those in vehicles, to require manual lasing. -## Air burst ammunition + +### Air burst ammunition Anti air cannons can now use airburst ammunition. It will explode on the FCS' zeroed in range. + # Usage + To engage moving targets, place the crosshair on the enemy vehicle and press and hold tab. Follow the moving target with your crosshair for about 2 seconds and release tab. The optic will now be adjusted sideways to ensure a hit. To use manual lasing, place the crosshair on the object to range and press and hold tab. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/flashsuppressors.md b/documentation/feature/flashsuppressors.md index 4217299857..fc1ecb58cf 100644 --- a/documentation/feature/flashsuppressors.md +++ b/documentation/feature/flashsuppressors.md @@ -4,15 +4,22 @@ title: Flash Suppressors group: feature parent: wiki --- + # Overview -## Sub-feature 1 + +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 + +### Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/frag.md b/documentation/feature/frag.md index 4d30c8d9f9..99c1d6c922 100644 --- a/documentation/feature/frag.md +++ b/documentation/feature/frag.md @@ -4,15 +4,22 @@ title: Frag group: feature parent: wiki --- + # Overview -## Sub-feature 1 + +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 + +### Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/gforces.md b/documentation/feature/gforces.md index 73c3b321ed..6f6ad8dc83 100644 --- a/documentation/feature/gforces.md +++ b/documentation/feature/gforces.md @@ -4,15 +4,22 @@ title: G-Forces group: feature parent: wiki --- + # Overview -## Sub-feature 1 + +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 + +### Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/goggles.md b/documentation/feature/goggles.md index 1d77e342d4..991a063219 100644 --- a/documentation/feature/goggles.md +++ b/documentation/feature/goggles.md @@ -4,15 +4,21 @@ title: Goggles group: feature parent: wiki --- + # Overview -## Visual Effects for eyewear + +### Visual Effects for eyewear Adds color tint to sunglasses and other eyewear. Causes raindrops to appear on the screen in rain. Causes dirt to appear on the screen when dirt is kicked up nearby (e.g. explsions, rotor wash, bullet impacts). + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/grenades.md b/documentation/feature/grenades.md index 67918ae77b..14a41c1757 100644 --- a/documentation/feature/grenades.md +++ b/documentation/feature/grenades.md @@ -4,17 +4,25 @@ title: Grenades group: feature parent: wiki --- + # Overview -## Throw modes + +### Throw modes Provides different modes for throwing grenades (high throw, precision throw and drop mode). -## Hand flares + +### Hand flares Adds throwable hand flares in the colors white, red, green and yellow. Additionally buffs existing flares. -## M84 stun grenade + +### M84 stun grenade Adds stun grenade. This will also affect AI. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/hearing.md b/documentation/feature/hearing.md index 32d4fce986..0ce0fbbc46 100644 --- a/documentation/feature/hearing.md +++ b/documentation/feature/hearing.md @@ -4,16 +4,23 @@ title: Hearing group: feature parent: wiki --- + # Overview -## Hearing damage simulation + +### Hearing damage simulation Introduces hearing damage caused by nearby explosions and large-caliber weapons. -## Earplugs + +### Earplugs Adds ear plugs to mitigate that effect. Soldiers with high caliber weapons or missile launchers will be equipped with those, but remember to put them in. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/hitreactions.md b/documentation/feature/hitreactions.md index c109f10ddd..3263c7c01f 100644 --- a/documentation/feature/hitreactions.md +++ b/documentation/feature/hitreactions.md @@ -4,15 +4,22 @@ title: Hit Reactions group: feature parent: wiki --- + # Overview -## Sub-feature 1 + +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 + +### Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/interact_menu.md b/documentation/feature/interact_menu.md index d00ba6f977..964ef31a0a 100644 --- a/documentation/feature/interact_menu.md +++ b/documentation/feature/interact_menu.md @@ -4,15 +4,22 @@ title: Interact Menu group: feature parent: wiki --- + # Overview -## Sub-feature 1 + +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 + +### Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/interaction.md b/documentation/feature/interaction.md index 36365342ae..49624e39a4 100644 --- a/documentation/feature/interaction.md +++ b/documentation/feature/interaction.md @@ -4,15 +4,22 @@ title: Interaction group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/inventory.md b/documentation/feature/inventory.md index 8dac5b6644..ce8f8076bf 100644 --- a/documentation/feature/inventory.md +++ b/documentation/feature/inventory.md @@ -4,13 +4,19 @@ title: Inventory group: feature parent: wiki --- + # Overview + ## Resized inventory UI Makes the inventory dialog bigger and increases the number of items that can be seen in the list at once. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/javelin.md b/documentation/feature/javelin.md index 78102840c1..921935a1e5 100644 --- a/documentation/feature/javelin.md +++ b/documentation/feature/javelin.md @@ -4,13 +4,18 @@ title: Javelin group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. @@ -24,5 +29,7 @@ Steps to lock titan/Javelin: CTRL+TAB is default key to change firemode (configurable as a key) + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/kestrel4500.md b/documentation/feature/kestrel4500.md index 0c6e03d304..1f13252337 100644 --- a/documentation/feature/kestrel4500.md +++ b/documentation/feature/kestrel4500.md @@ -4,15 +4,22 @@ title: Kestrel 4500 group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/laser.md b/documentation/feature/laser.md index 6e1de22002..e68d63dd9b 100644 --- a/documentation/feature/laser.md +++ b/documentation/feature/laser.md @@ -4,15 +4,22 @@ title: Laser group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/laser_selfdesignate.md b/documentation/feature/laser_selfdesignate.md index 8405d57c43..f530525641 100644 --- a/documentation/feature/laser_selfdesignate.md +++ b/documentation/feature/laser_selfdesignate.md @@ -4,15 +4,22 @@ title: Laser Self-Designate group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/laserpointer.md b/documentation/feature/laserpointer.md index c22471e320..3fcf7258f5 100644 --- a/documentation/feature/laserpointer.md +++ b/documentation/feature/laserpointer.md @@ -4,15 +4,22 @@ title: Laser Pointer group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/logistics_uavbattery.md b/documentation/feature/logistics_uavbattery.md index 6cd3bc0b3b..e97e9ba97c 100644 --- a/documentation/feature/logistics_uavbattery.md +++ b/documentation/feature/logistics_uavbattery.md @@ -4,15 +4,22 @@ title: Logistics - UAV Battery group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/logistics_wirecutter.md b/documentation/feature/logistics_wirecutter.md index 97d684e697..ba3fd10a5c 100644 --- a/documentation/feature/logistics_wirecutter.md +++ b/documentation/feature/logistics_wirecutter.md @@ -4,15 +4,22 @@ title: Logistics - Wirecutter group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/magazinerepack.md b/documentation/feature/magazinerepack.md index e9ae26f315..4811840080 100644 --- a/documentation/feature/magazinerepack.md +++ b/documentation/feature/magazinerepack.md @@ -4,15 +4,21 @@ title: Magazine Repack group: feature parent: wiki --- + # Overview + ## Repacking magazines Adds ability to repack magazines of the same type. An optional module provides options to adjust the repacking time of single rounds and whole magazines to the mission maker. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/map.md b/documentation/feature/map.md index 88a3493d9e..20df9c0955 100644 --- a/documentation/feature/map.md +++ b/documentation/feature/map.md @@ -4,15 +4,22 @@ title: Map group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/maptools.md b/documentation/feature/maptools.md index 6814a5c1f5..d80702f0e9 100644 --- a/documentation/feature/maptools.md +++ b/documentation/feature/maptools.md @@ -4,15 +4,22 @@ title: Map Tools group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/markers.md b/documentation/feature/markers.md index eae1bfe333..6dd8ccbc8c 100644 --- a/documentation/feature/markers.md +++ b/documentation/feature/markers.md @@ -4,13 +4,19 @@ title: Markers group: feature parent: wiki --- + # Overview + ## Improved marker placement Expands the "Insert Marker" menu and allows to rotate map markers. Shows the currently selected channel to prevent misplacement. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/microdagr.md b/documentation/feature/microdagr.md index a98730c9f4..bb1abe4c95 100644 --- a/documentation/feature/microdagr.md +++ b/documentation/feature/microdagr.md @@ -4,15 +4,22 @@ title: MicroDAGR group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/missileguidance.md b/documentation/feature/missileguidance.md index fe5aa792b3..797479d252 100644 --- a/documentation/feature/missileguidance.md +++ b/documentation/feature/missileguidance.md @@ -4,15 +4,22 @@ title: Missile Guidance group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/missionmodules.md b/documentation/feature/missionmodules.md index 771a5ef290..5f12d1449a 100644 --- a/documentation/feature/missionmodules.md +++ b/documentation/feature/missionmodules.md @@ -4,15 +4,22 @@ title: Mission Modules group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/mk6mortar.md b/documentation/feature/mk6mortar.md index af718eedce..2b5ba54609 100644 --- a/documentation/feature/mk6mortar.md +++ b/documentation/feature/mk6mortar.md @@ -4,15 +4,22 @@ title: Mk6 Mortar group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/movement.md b/documentation/feature/movement.md index 3b98e43cc7..90e19188a2 100644 --- a/documentation/feature/movement.md +++ b/documentation/feature/movement.md @@ -4,21 +4,31 @@ title: Movement group: feature parent: wiki --- + # Overview + ## Jumping Adds the ability to jump when pressing the vault key while moving. (V - key) + ## Minor animation tweaks Walking slowly with the weapon lowered now has a less silly looking animation. + ## Fatigue adjustments Soldiers get fatigued slower, but regain their stamina slower aswell. Fatigued soldiers have a faster walking speed and no longer turn into snails. + ## Weight display Adds a weight of the current loadout display in the inventory to estimate the fatigue gain while moving in combat. Can be adjusted to display lb. instead of kg in the ACE Options Menu. + ## Optics view in all stances The player can now use the sights of rifles and pistols in all prone stances. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/nametags.md b/documentation/feature/nametags.md index 0086060d87..becf24671f 100644 --- a/documentation/feature/nametags.md +++ b/documentation/feature/nametags.md @@ -4,13 +4,19 @@ title: Nametags group: feature parent: wiki --- + # Overview + ## Nametag and rank display Adds nametags and soldier ranks to friendly players in multiplayer. This can be adjusted in the ACE Options Menu to not display the rank, display all nametags of nearby soldiers instead of those who are looked directly at, to require a button press to show the nametags or to disable them altogether. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/nightvision.md b/documentation/feature/nightvision.md index 64442b7311..d3fe72369e 100644 --- a/documentation/feature/nightvision.md +++ b/documentation/feature/nightvision.md @@ -4,20 +4,28 @@ title: Nightvision group: feature parent: wiki --- + # Overview + ## Multiple Generation NVGs Adds different night vision devices with varying image quality and field of view. New Classnames for Generations 1, 2, and 4 NVGs (default ArmA3 NVGs represents Generation 3) and a wide view NVG. + ## Blending effects Adds a blending effect depending on ammunition type when firing while using a night vision device. Especially tracer rounds are bright, but you can use the IR-dim tracers from the Ballistics module to reduce tis effect. + ## Brightness adjustment Enables the user to manually adjust NVG brightness. + + # Usage Use Alt+PageUp and Alt+PageDown to adjust NVG brightness. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/noidle.md b/documentation/feature/noidle.md index aa6657728d..3f96869eb0 100644 --- a/documentation/feature/noidle.md +++ b/documentation/feature/noidle.md @@ -4,15 +4,22 @@ title: No Idle group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/noradio.md b/documentation/feature/noradio.md index f9a832abd0..44ee670a67 100644 --- a/documentation/feature/noradio.md +++ b/documentation/feature/noradio.md @@ -4,14 +4,20 @@ title: No Radio group: feature parent: wiki --- + # Overview + ## Silent avatar Mutes the player's automatic callouts ("Enemy man, 100 meters, front!"). Does not mute AI callouts. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/norearm.md b/documentation/feature/norearm.md index 7ed7a5c515..565762eb1e 100644 --- a/documentation/feature/norearm.md +++ b/documentation/feature/norearm.md @@ -4,15 +4,22 @@ title: No Rearm group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/optics.md b/documentation/feature/optics.md index 90b486bc88..0d084ef2f6 100644 --- a/documentation/feature/optics.md +++ b/documentation/feature/optics.md @@ -4,15 +4,22 @@ title: Optics group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/optionsmenu.md b/documentation/feature/optionsmenu.md index a0c9ad33da..8958f10469 100644 --- a/documentation/feature/optionsmenu.md +++ b/documentation/feature/optionsmenu.md @@ -4,15 +4,22 @@ title: Options Menu group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/ovepressure.md b/documentation/feature/ovepressure.md index af8e47ae0c..7b6aeeeadd 100644 --- a/documentation/feature/ovepressure.md +++ b/documentation/feature/ovepressure.md @@ -4,15 +4,22 @@ title: Overpressure group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/overheating.md b/documentation/feature/overheating.md index 3a10bf9f48..3f52ed6736 100644 --- a/documentation/feature/overheating.md +++ b/documentation/feature/overheating.md @@ -4,24 +4,32 @@ title: Overheating group: feature parent: wiki --- + # Overview + ## Weapon Jamming Adds a propability to jam a weapon when firing. Jams can be cleared by reloading or by using the clear jam-key. + ## Temperature simulation Introduces weapon temperature simulation depending on weapon and bullet mass. Hot weapons are more prone to jamming. Depending on weapon type the accuracy and in extreme cases the muzzle velocity might be reduced on high temperatues. Adds smoke puff and heat refraction effects to indicate this. + ## Spare barrels Adds the ability to changes barrels on machine guns to compensate for those effects. + # Usage To clear a jammed weapon, press Shift+R. + *needs documentation on swapping barrels* + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/parachute.md b/documentation/feature/parachute.md index 48ad0e9836..db08f053ab 100644 --- a/documentation/feature/parachute.md +++ b/documentation/feature/parachute.md @@ -4,19 +4,27 @@ title: Parachute group: feature parent: wiki --- + # Overview + ## Altimeter Removes the altitude and descend speed UI elements when free-falling and parachuting on higher difficulties and instead adds an altimeter watch type item. + ## Non-steerable parachute Adds a non-steerable parachute variant for jet pilots. + ## Landing animation Smoothens parachute landing animation. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/protection.md b/documentation/feature/protection.md index 2eb2a9aaef..8a972c0740 100644 --- a/documentation/feature/protection.md +++ b/documentation/feature/protection.md @@ -4,15 +4,22 @@ title: Protection group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/ragdolls.md b/documentation/feature/ragdolls.md index 585c6c71a8..e4caec683d 100644 --- a/documentation/feature/ragdolls.md +++ b/documentation/feature/ragdolls.md @@ -4,13 +4,19 @@ title: Ragdolls group: feature parent: wiki --- + # Overview + ## Adjusted Ragdolls Changes the ragdolls to react more to the force of shots and explosions. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/realisticnames.md b/documentation/feature/realisticnames.md index 64d9a316cb..80ae544450 100644 --- a/documentation/feature/realisticnames.md +++ b/documentation/feature/realisticnames.md @@ -4,14 +4,20 @@ title: Realistic Names group: feature parent: wiki --- + # Overview + ## Real names Changes the names of vehicles, magazines, weapons, grenades, explosive charges and mines to their respective real-world counterparts whenever possible. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/recoil.md b/documentation/feature/recoil.md index 919ab24836..c1dfedf324 100644 --- a/documentation/feature/recoil.md +++ b/documentation/feature/recoil.md @@ -4,17 +4,25 @@ title: Recoil group: feature parent: wiki --- + # Overview + ## Recoil adjustment Overhauls the recoil system reducing upwards recoil. + ## Advanced cam shake Introducing camshake when firing on foot or as vehicle gunner depending on stance and weapon type. + ## Burst dispersion Firing in longer burst (> 3 rounds per burst) slightly reduces the accuracy. Firing machine guns in bursts is now useful. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/reload.md b/documentation/feature/reload.md index f791521a63..5806fec169 100644 --- a/documentation/feature/reload.md +++ b/documentation/feature/reload.md @@ -4,13 +4,19 @@ title: Reload group: feature parent: wiki --- + # Overview + ## Ammo count Hides the actual round count of magazines and removes the icon when the current magazine is emptied. The player can instead check the magazine weight, but that gives only estimated values for magazines with more than 10 rounds. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/reloadlaunchers.md b/documentation/feature/reloadlaunchers.md index 7b1f26cea1..4b19d43471 100644 --- a/documentation/feature/reloadlaunchers.md +++ b/documentation/feature/reloadlaunchers.md @@ -4,16 +4,21 @@ title: Reload Launchers group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. + +Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. -r \ No newline at end of file diff --git a/documentation/feature/respawn.md b/documentation/feature/respawn.md index 6059f33c59..778be0b857 100644 --- a/documentation/feature/respawn.md +++ b/documentation/feature/respawn.md @@ -4,17 +4,25 @@ title: Respawn group: feature parent: wiki --- + # Overview + ## Respawn with same gear Requires the Respawn Gear module to be placed. Respawned soldiers now have their loadout when killed. + ## Friendly Fire messages Shows friendly fire warnings in system chat if the module is placed. Works even in higher difficulties where kill messages are normally disabled. + ## Rallypoints Adds rallypoints to all 3 sides to enable teleportation from base spawn to FOBs. Requires some setup from the mission maker. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/safemode.md b/documentation/feature/safemode.md index ea4f3fe902..6d3e967153 100644 --- a/documentation/feature/safemode.md +++ b/documentation/feature/safemode.md @@ -4,13 +4,19 @@ title: Safe Mode group: feature parent: wiki --- + # Overview + ## Safety You can now use the safety mode of any weapon. Switching weapon modes takes the safety off. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/scopes.md b/documentation/feature/scopes.md index fb29c7d6e1..4ac7d7562a 100644 --- a/documentation/feature/scopes.md +++ b/documentation/feature/scopes.md @@ -4,13 +4,19 @@ title: Scopes group: feature parent: wiki --- + # Overview + ## Sniper Scope Adjustment Enables snipers to adjust their scopes horizontally and vertically in mils. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/smallarms.md b/documentation/feature/smallarms.md index 11e68d4373..96a07ab099 100644 --- a/documentation/feature/smallarms.md +++ b/documentation/feature/smallarms.md @@ -4,17 +4,25 @@ title: Small Arms group: feature parent: wiki --- + # Overview + ## Magazine Names Unifies the name formatting of magazines similar to Arma 2 standards. + ## No tracers in non-tracer mags Assault rifles no longer have tracer rounds in their non-tracer magazines. This doesn't effect the additional tracers in the last rounds of machine gun magazines. + ## Real magazine round counts All pistol and sub machine gun magazines now have adjusted capacaties to match their real life counterparts. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/switchunits.md b/documentation/feature/switchunits.md index 71ace0e055..a59ad206dd 100644 --- a/documentation/feature/switchunits.md +++ b/documentation/feature/switchunits.md @@ -4,15 +4,22 @@ title: Switch Units group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/testmissions.md b/documentation/feature/testmissions.md index 7d7ac52af8..e9a920872e 100644 --- a/documentation/feature/testmissions.md +++ b/documentation/feature/testmissions.md @@ -4,15 +4,22 @@ title: Test Missions group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/thermals.md b/documentation/feature/thermals.md index 12f79a311b..f8a47f7df1 100644 --- a/documentation/feature/thermals.md +++ b/documentation/feature/thermals.md @@ -4,13 +4,19 @@ title: Thermals group: feature parent: wiki --- + # Overview + ## Body Warmth Adjusts the thermal properties of humans making them less like torches. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/vector.md b/documentation/feature/vector.md index 277f5eb524..9c0a27d9b3 100644 --- a/documentation/feature/vector.md +++ b/documentation/feature/vector.md @@ -4,13 +4,19 @@ title: Vector group: feature parent: wiki --- + # Overview + ## Vector IV Rangefinder Adds the Vector IV rangefinder, including all real-life usage modes (distance between two points, angle between two points etc.) + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/vehiclelock.md b/documentation/feature/vehiclelock.md index 239661d153..4731834e46 100644 --- a/documentation/feature/vehiclelock.md +++ b/documentation/feature/vehiclelock.md @@ -4,15 +4,22 @@ title: Vehicle Lock group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/vehicles.md b/documentation/feature/vehicles.md index 534bb35171..0965ca81cc 100644 --- a/documentation/feature/vehicles.md +++ b/documentation/feature/vehicles.md @@ -4,29 +4,43 @@ title: Vehicles group: feature parent: wiki --- + # Overview + ## Speedlimiter Adds ability to limit the max. speed of any vehicle. + ## Engine start delay The engine has to be started before the vehicle can move. Starting the engine takes aprox. 1 to 2 seconds. + ## Fuel capacity The range of all vehicle gets signifigantly reduced to reflect ranges of their real life counterparts. Scaled down to match the relative short distances in Arma. A full vehicle on mission start should still most likely never need a refueling during a mission. + ## Main gun muzzles APCs and Tanks now share a muzzle for all ammunition types of their main guns. This prevents an exploit that skips the reloading time of a round or clip while changing the ammunition type. Also makes it possible to switch between ammunition types using the scroll wheel like in Arma 2. + ## Boat machine gun tracers NATO and AAF armed boats now use their respective tracer colours like any vehicle when they fire their rear gun. (Red for BluFor, yellow for Indep) + ## Improved smoke launcher of Fennek (Strider) Reduced smoke shell count and launch angle of the AAF Fennek to match the models smoke launcher. + ## Stabilized optic of Fennek (Strider) Stabilizes the commander's view in the Fennek (Strider). + ## Vehicle mounted machine guns ROF The rate of fire of vehicle mounted miniguns and machine guns is adjusted to match real life values. + ## 120mm gun and mortar behavior MBT main guns and mortars can no longer lock on enemies. The AT rounds of both now have raised cost values to encourage the AI to not use those rounds against foot soldiers over their machine guns or HE rounds. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/weaponselect.md b/documentation/feature/weaponselect.md index 872e27cad0..1fc9cec3e2 100644 --- a/documentation/feature/weaponselect.md +++ b/documentation/feature/weaponselect.md @@ -4,21 +4,31 @@ title: Weapon Select group: feature parent: wiki --- + # Overview + ## Weapon select The number key can be used to quickly switch between weapons. (1 key - pistol, 2 key - rifle, 3 key - grenade launcher, 4 key - rocket launcher, 5 key - binocular) + ## Holster weapon Adds the ability to holster a weapon on the back. (0 key) + ## Engine select Quickly turn engine on and off (1 key - turn off, 2 key - turn on) + ## Weapon select Quickly switch between vehicle weapons (1-3 key) + ## Grenade select To prevent accidents a grenade has to be selected before it can be thrown. Toggles between explosive and non-explosive grenades. When spamming the throw key, the player won't automatically switch to frag grenades when all smokes are used up. Also shows an indicator to quickly see how many grenades are left when selecting and after throwing (6 key - switch between frag grenades, 7 key - switch between other grenades) + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/weather.md b/documentation/feature/weather.md index 2cbeea5e7e..31089495af 100644 --- a/documentation/feature/weather.md +++ b/documentation/feature/weather.md @@ -4,15 +4,22 @@ title: Weather group: feature parent: wiki --- + # Overview + ## Sub-feature 1 Short description of sub-feature 1. + ## Sub-feature 2 Short description of sub-feature 2. + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. diff --git a/documentation/feature/windeflection.md b/documentation/feature/windeflection.md index 7bca0b0f60..b6d751b126 100644 --- a/documentation/feature/windeflection.md +++ b/documentation/feature/windeflection.md @@ -4,13 +4,19 @@ title: Wind Deflection group: feature parent: wiki --- + # Overview + ## Wind Deflection Adds ballistic influences of wind, air density and temperature + # Usage + Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. + # Dependencies + List of modules that must be present for this module to work. From 011570535fb0d50ad9e782e35e7f0a90bcd7562f Mon Sep 17 00:00:00 2001 From: KoffeinFlummi <koffeinflummi@gmail.com> Date: Thu, 14 May 2015 16:04:45 +0200 Subject: [PATCH 46/51] Change H2s to H3s --- documentation/feature/interaction.md | 4 ++-- documentation/feature/inventory.md | 2 +- documentation/feature/javelin.md | 4 ++-- documentation/feature/kestrel4500.md | 4 ++-- documentation/feature/laser.md | 4 ++-- documentation/feature/laser_selfdesignate.md | 4 ++-- documentation/feature/laserpointer.md | 4 ++-- documentation/feature/logistics_uavbattery.md | 4 ++-- documentation/feature/logistics_wirecutter.md | 4 ++-- documentation/feature/magazinerepack.md | 2 +- documentation/feature/map.md | 4 ++-- documentation/feature/maptools.md | 4 ++-- documentation/feature/markers.md | 2 +- documentation/feature/medical-system.md | 6 +++--- documentation/feature/microdagr.md | 4 ++-- documentation/feature/missileguidance.md | 4 ++-- documentation/feature/missionmodules.md | 4 ++-- documentation/feature/mk6mortar.md | 4 ++-- documentation/feature/movement.md | 10 +++++----- documentation/feature/nametags.md | 2 +- documentation/feature/nightvision.md | 6 +++--- documentation/feature/noidle.md | 4 ++-- documentation/feature/noradio.md | 2 +- documentation/feature/norearm.md | 4 ++-- documentation/feature/optics.md | 4 ++-- documentation/feature/optionsmenu.md | 4 ++-- documentation/feature/ovepressure.md | 4 ++-- documentation/feature/overheating.md | 6 +++--- documentation/feature/parachute.md | 6 +++--- documentation/feature/protection.md | 4 ++-- documentation/feature/ragdolls.md | 2 +- documentation/feature/realisticnames.md | 2 +- documentation/feature/recoil.md | 6 +++--- documentation/feature/reload.md | 2 +- documentation/feature/reloadlaunchers.md | 4 ++-- documentation/feature/respawn.md | 6 +++--- documentation/feature/safemode.md | 2 +- documentation/feature/scopes.md | 2 +- documentation/feature/smallarms.md | 6 +++--- documentation/feature/switchunits.md | 4 ++-- documentation/feature/testmissions.md | 4 ++-- documentation/feature/thermals.md | 2 +- documentation/feature/vector.md | 2 +- documentation/feature/vehiclelock.md | 4 ++-- documentation/feature/vehicles.md | 18 +++++++++--------- documentation/feature/weaponselect.md | 10 +++++----- documentation/feature/weather.md | 4 ++-- documentation/feature/windeflection.md | 2 +- 48 files changed, 103 insertions(+), 103 deletions(-) diff --git a/documentation/feature/interaction.md b/documentation/feature/interaction.md index 49624e39a4..86824f8c7e 100644 --- a/documentation/feature/interaction.md +++ b/documentation/feature/interaction.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/inventory.md b/documentation/feature/inventory.md index ce8f8076bf..151baf1ef7 100644 --- a/documentation/feature/inventory.md +++ b/documentation/feature/inventory.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Resized inventory UI +### Resized inventory UI Makes the inventory dialog bigger and increases the number of items that can be seen in the list at once. diff --git a/documentation/feature/javelin.md b/documentation/feature/javelin.md index 921935a1e5..f6d98b398b 100644 --- a/documentation/feature/javelin.md +++ b/documentation/feature/javelin.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/kestrel4500.md b/documentation/feature/kestrel4500.md index 1f13252337..a70b97eb17 100644 --- a/documentation/feature/kestrel4500.md +++ b/documentation/feature/kestrel4500.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/laser.md b/documentation/feature/laser.md index e68d63dd9b..e563aed749 100644 --- a/documentation/feature/laser.md +++ b/documentation/feature/laser.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/laser_selfdesignate.md b/documentation/feature/laser_selfdesignate.md index f530525641..d9a7cb375c 100644 --- a/documentation/feature/laser_selfdesignate.md +++ b/documentation/feature/laser_selfdesignate.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/laserpointer.md b/documentation/feature/laserpointer.md index 3fcf7258f5..d43b02978b 100644 --- a/documentation/feature/laserpointer.md +++ b/documentation/feature/laserpointer.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/logistics_uavbattery.md b/documentation/feature/logistics_uavbattery.md index e97e9ba97c..448bd87d36 100644 --- a/documentation/feature/logistics_uavbattery.md +++ b/documentation/feature/logistics_uavbattery.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/logistics_wirecutter.md b/documentation/feature/logistics_wirecutter.md index ba3fd10a5c..bf19a60e35 100644 --- a/documentation/feature/logistics_wirecutter.md +++ b/documentation/feature/logistics_wirecutter.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/magazinerepack.md b/documentation/feature/magazinerepack.md index 4811840080..eb66c4dace 100644 --- a/documentation/feature/magazinerepack.md +++ b/documentation/feature/magazinerepack.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Repacking magazines +### Repacking magazines Adds ability to repack magazines of the same type. An optional module provides options to adjust the repacking time of single rounds and whole magazines to the mission maker. diff --git a/documentation/feature/map.md b/documentation/feature/map.md index 20df9c0955..0df1cfcfb2 100644 --- a/documentation/feature/map.md +++ b/documentation/feature/map.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/maptools.md b/documentation/feature/maptools.md index d80702f0e9..a3f94e0d57 100644 --- a/documentation/feature/maptools.md +++ b/documentation/feature/maptools.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/markers.md b/documentation/feature/markers.md index 6dd8ccbc8c..821220997f 100644 --- a/documentation/feature/markers.md +++ b/documentation/feature/markers.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Improved marker placement +### Improved marker placement Expands the "Insert Marker" menu and allows to rotate map markers. Shows the currently selected channel to prevent misplacement. diff --git a/documentation/feature/medical-system.md b/documentation/feature/medical-system.md index 443fb4b182..01a9e2c0a6 100644 --- a/documentation/feature/medical-system.md +++ b/documentation/feature/medical-system.md @@ -6,11 +6,11 @@ order: 4 parent: wiki --- -## 1. Overview +### 1. Overview ACE provide users with a more realistic medical system and comes in both a basic and advanced version. This page will detail the differences between both systems and what they do. It is split into two parts; basic and advanced. Both versions have overlap but each have their own unique characteristics. -## 2. Basic Medical +### 2. Basic Medical ACE's basic medical system is quite a bit more complex than Arma's default system, but not really difficult to grasp. ACE basic medical is a mixture between the ACE2 and AGM medical systems. The four main elements that basic medical introduces are: @@ -31,7 +31,7 @@ To stop the bleeding, the combat life saver needs to bandage every wounded limb. Should a unit be in pain, materializing itself with a chromatic aberration screen effect, he can be given morphine. -## 3. Advanced Medical +### 3. Advanced Medical The advanced medical system provides a more complex and detailed medical simulation and is based off the CSE/CMS medical system. It focuses on a more realistic model for injuries and treatment, thus resulting in a more important and prominent role for combat medics, and a bigger incentive to not get shot. The system behind advanced medical is designed to attempt to mimic important parts of the human body, as well as react to any injuries sustained and treatments applied in a realistic manner. The available treatments and supplies in advanced medical are based off the Tactical Combat Casualty Care (TCCC) guidelines, which are the same guidelines used by real-life combat medics around the world. diff --git a/documentation/feature/microdagr.md b/documentation/feature/microdagr.md index bb1abe4c95..ee5126fb90 100644 --- a/documentation/feature/microdagr.md +++ b/documentation/feature/microdagr.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/missileguidance.md b/documentation/feature/missileguidance.md index 797479d252..6b66edb547 100644 --- a/documentation/feature/missileguidance.md +++ b/documentation/feature/missileguidance.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/missionmodules.md b/documentation/feature/missionmodules.md index 5f12d1449a..358c00388a 100644 --- a/documentation/feature/missionmodules.md +++ b/documentation/feature/missionmodules.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/mk6mortar.md b/documentation/feature/mk6mortar.md index 2b5ba54609..61a777c18c 100644 --- a/documentation/feature/mk6mortar.md +++ b/documentation/feature/mk6mortar.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/movement.md b/documentation/feature/movement.md index 90e19188a2..78a3f12d3c 100644 --- a/documentation/feature/movement.md +++ b/documentation/feature/movement.md @@ -7,19 +7,19 @@ parent: wiki # Overview -## Jumping +### Jumping Adds the ability to jump when pressing the vault key while moving. (V - key) -## Minor animation tweaks +### Minor animation tweaks Walking slowly with the weapon lowered now has a less silly looking animation. -## Fatigue adjustments +### Fatigue adjustments Soldiers get fatigued slower, but regain their stamina slower aswell. Fatigued soldiers have a faster walking speed and no longer turn into snails. -## Weight display +### Weight display Adds a weight of the current loadout display in the inventory to estimate the fatigue gain while moving in combat. Can be adjusted to display lb. instead of kg in the ACE Options Menu. -## Optics view in all stances +### Optics view in all stances The player can now use the sights of rifles and pistols in all prone stances. diff --git a/documentation/feature/nametags.md b/documentation/feature/nametags.md index becf24671f..1a7946f4e2 100644 --- a/documentation/feature/nametags.md +++ b/documentation/feature/nametags.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Nametag and rank display +### Nametag and rank display Adds nametags and soldier ranks to friendly players in multiplayer. This can be adjusted in the ACE Options Menu to not display the rank, display all nametags of nearby soldiers instead of those who are looked directly at, to require a button press to show the nametags or to disable them altogether. diff --git a/documentation/feature/nightvision.md b/documentation/feature/nightvision.md index d3fe72369e..35a42813a4 100644 --- a/documentation/feature/nightvision.md +++ b/documentation/feature/nightvision.md @@ -7,17 +7,17 @@ parent: wiki # Overview -## Multiple Generation NVGs +### Multiple Generation NVGs Adds different night vision devices with varying image quality and field of view. New Classnames for Generations 1, 2, and 4 NVGs (default ArmA3 NVGs represents Generation 3) and a wide view NVG. -## Blending effects +### Blending effects Adds a blending effect depending on ammunition type when firing while using a night vision device. Especially tracer rounds are bright, but you can use the IR-dim tracers from the Ballistics module to reduce tis effect. -## Brightness adjustment +### Brightness adjustment Enables the user to manually adjust NVG brightness. diff --git a/documentation/feature/noidle.md b/documentation/feature/noidle.md index 3f96869eb0..b6b4261f7c 100644 --- a/documentation/feature/noidle.md +++ b/documentation/feature/noidle.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/noradio.md b/documentation/feature/noradio.md index 44ee670a67..a19fd60145 100644 --- a/documentation/feature/noradio.md +++ b/documentation/feature/noradio.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Silent avatar +### Silent avatar Mutes the player's automatic callouts ("Enemy man, 100 meters, front!"). Does not mute AI callouts. diff --git a/documentation/feature/norearm.md b/documentation/feature/norearm.md index 565762eb1e..559551eab9 100644 --- a/documentation/feature/norearm.md +++ b/documentation/feature/norearm.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/optics.md b/documentation/feature/optics.md index 0d084ef2f6..c9c6804109 100644 --- a/documentation/feature/optics.md +++ b/documentation/feature/optics.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/optionsmenu.md b/documentation/feature/optionsmenu.md index 8958f10469..0630f894ca 100644 --- a/documentation/feature/optionsmenu.md +++ b/documentation/feature/optionsmenu.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/ovepressure.md b/documentation/feature/ovepressure.md index 7b6aeeeadd..aa528afbf8 100644 --- a/documentation/feature/ovepressure.md +++ b/documentation/feature/ovepressure.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/overheating.md b/documentation/feature/overheating.md index 3f52ed6736..916d60af90 100644 --- a/documentation/feature/overheating.md +++ b/documentation/feature/overheating.md @@ -7,18 +7,18 @@ parent: wiki # Overview -## Weapon Jamming +### Weapon Jamming Adds a propability to jam a weapon when firing. Jams can be cleared by reloading or by using the clear jam-key. -## Temperature simulation +### Temperature simulation Introduces weapon temperature simulation depending on weapon and bullet mass. Hot weapons are more prone to jamming. Depending on weapon type the accuracy and in extreme cases the muzzle velocity might be reduced on high temperatues. Adds smoke puff and heat refraction effects to indicate this. -## Spare barrels +### Spare barrels Adds the ability to changes barrels on machine guns to compensate for those effects. diff --git a/documentation/feature/parachute.md b/documentation/feature/parachute.md index db08f053ab..a2a27a3228 100644 --- a/documentation/feature/parachute.md +++ b/documentation/feature/parachute.md @@ -7,15 +7,15 @@ parent: wiki # Overview -## Altimeter +### Altimeter Removes the altitude and descend speed UI elements when free-falling and parachuting on higher difficulties and instead adds an altimeter watch type item. -## Non-steerable parachute +### Non-steerable parachute Adds a non-steerable parachute variant for jet pilots. -## Landing animation +### Landing animation Smoothens parachute landing animation. diff --git a/documentation/feature/protection.md b/documentation/feature/protection.md index 8a972c0740..ae370756b8 100644 --- a/documentation/feature/protection.md +++ b/documentation/feature/protection.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/ragdolls.md b/documentation/feature/ragdolls.md index e4caec683d..b8d125b792 100644 --- a/documentation/feature/ragdolls.md +++ b/documentation/feature/ragdolls.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Adjusted Ragdolls +### Adjusted Ragdolls Changes the ragdolls to react more to the force of shots and explosions. diff --git a/documentation/feature/realisticnames.md b/documentation/feature/realisticnames.md index 80ae544450..9458f752a4 100644 --- a/documentation/feature/realisticnames.md +++ b/documentation/feature/realisticnames.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Real names +### Real names Changes the names of vehicles, magazines, weapons, grenades, explosive charges and mines to their respective real-world counterparts whenever possible. diff --git a/documentation/feature/recoil.md b/documentation/feature/recoil.md index c1dfedf324..23d49877bb 100644 --- a/documentation/feature/recoil.md +++ b/documentation/feature/recoil.md @@ -7,13 +7,13 @@ parent: wiki # Overview -## Recoil adjustment +### Recoil adjustment Overhauls the recoil system reducing upwards recoil. -## Advanced cam shake +### Advanced cam shake Introducing camshake when firing on foot or as vehicle gunner depending on stance and weapon type. -## Burst dispersion +### Burst dispersion Firing in longer burst (> 3 rounds per burst) slightly reduces the accuracy. Firing machine guns in bursts is now useful. diff --git a/documentation/feature/reload.md b/documentation/feature/reload.md index 5806fec169..fac42ef365 100644 --- a/documentation/feature/reload.md +++ b/documentation/feature/reload.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Ammo count +### Ammo count Hides the actual round count of magazines and removes the icon when the current magazine is emptied. The player can instead check the magazine weight, but that gives only estimated values for magazines with more than 10 rounds. diff --git a/documentation/feature/reloadlaunchers.md b/documentation/feature/reloadlaunchers.md index 4b19d43471..7000ff5fd0 100644 --- a/documentation/feature/reloadlaunchers.md +++ b/documentation/feature/reloadlaunchers.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/respawn.md b/documentation/feature/respawn.md index 778be0b857..d07d179438 100644 --- a/documentation/feature/respawn.md +++ b/documentation/feature/respawn.md @@ -7,13 +7,13 @@ parent: wiki # Overview -## Respawn with same gear +### Respawn with same gear Requires the Respawn Gear module to be placed. Respawned soldiers now have their loadout when killed. -## Friendly Fire messages +### Friendly Fire messages Shows friendly fire warnings in system chat if the module is placed. Works even in higher difficulties where kill messages are normally disabled. -## Rallypoints +### Rallypoints Adds rallypoints to all 3 sides to enable teleportation from base spawn to FOBs. Requires some setup from the mission maker. diff --git a/documentation/feature/safemode.md b/documentation/feature/safemode.md index 6d3e967153..b0c006ef24 100644 --- a/documentation/feature/safemode.md +++ b/documentation/feature/safemode.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Safety +### Safety You can now use the safety mode of any weapon. Switching weapon modes takes the safety off. diff --git a/documentation/feature/scopes.md b/documentation/feature/scopes.md index 4ac7d7562a..cb1ac8fef6 100644 --- a/documentation/feature/scopes.md +++ b/documentation/feature/scopes.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Sniper Scope Adjustment +### Sniper Scope Adjustment Enables snipers to adjust their scopes horizontally and vertically in mils. diff --git a/documentation/feature/smallarms.md b/documentation/feature/smallarms.md index 96a07ab099..c714448283 100644 --- a/documentation/feature/smallarms.md +++ b/documentation/feature/smallarms.md @@ -7,13 +7,13 @@ parent: wiki # Overview -## Magazine Names +### Magazine Names Unifies the name formatting of magazines similar to Arma 2 standards. -## No tracers in non-tracer mags +### No tracers in non-tracer mags Assault rifles no longer have tracer rounds in their non-tracer magazines. This doesn't effect the additional tracers in the last rounds of machine gun magazines. -## Real magazine round counts +### Real magazine round counts All pistol and sub machine gun magazines now have adjusted capacaties to match their real life counterparts. diff --git a/documentation/feature/switchunits.md b/documentation/feature/switchunits.md index a59ad206dd..2102761f59 100644 --- a/documentation/feature/switchunits.md +++ b/documentation/feature/switchunits.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/testmissions.md b/documentation/feature/testmissions.md index e9a920872e..094fabbadb 100644 --- a/documentation/feature/testmissions.md +++ b/documentation/feature/testmissions.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/thermals.md b/documentation/feature/thermals.md index f8a47f7df1..295746ee1f 100644 --- a/documentation/feature/thermals.md +++ b/documentation/feature/thermals.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Body Warmth +### Body Warmth Adjusts the thermal properties of humans making them less like torches. diff --git a/documentation/feature/vector.md b/documentation/feature/vector.md index 9c0a27d9b3..206c6bfc37 100644 --- a/documentation/feature/vector.md +++ b/documentation/feature/vector.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Vector IV Rangefinder +### Vector IV Rangefinder Adds the Vector IV rangefinder, including all real-life usage modes (distance between two points, angle between two points etc.) diff --git a/documentation/feature/vehiclelock.md b/documentation/feature/vehiclelock.md index 4731834e46..6bd8d361ae 100644 --- a/documentation/feature/vehiclelock.md +++ b/documentation/feature/vehiclelock.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/vehicles.md b/documentation/feature/vehicles.md index 0965ca81cc..14dba54d27 100644 --- a/documentation/feature/vehicles.md +++ b/documentation/feature/vehicles.md @@ -7,31 +7,31 @@ parent: wiki # Overview -## Speedlimiter +### Speedlimiter Adds ability to limit the max. speed of any vehicle. -## Engine start delay +### Engine start delay The engine has to be started before the vehicle can move. Starting the engine takes aprox. 1 to 2 seconds. -## Fuel capacity +### Fuel capacity The range of all vehicle gets signifigantly reduced to reflect ranges of their real life counterparts. Scaled down to match the relative short distances in Arma. A full vehicle on mission start should still most likely never need a refueling during a mission. -## Main gun muzzles +### Main gun muzzles APCs and Tanks now share a muzzle for all ammunition types of their main guns. This prevents an exploit that skips the reloading time of a round or clip while changing the ammunition type. Also makes it possible to switch between ammunition types using the scroll wheel like in Arma 2. -## Boat machine gun tracers +### Boat machine gun tracers NATO and AAF armed boats now use their respective tracer colours like any vehicle when they fire their rear gun. (Red for BluFor, yellow for Indep) -## Improved smoke launcher of Fennek (Strider) +### Improved smoke launcher of Fennek (Strider) Reduced smoke shell count and launch angle of the AAF Fennek to match the models smoke launcher. -## Stabilized optic of Fennek (Strider) +### Stabilized optic of Fennek (Strider) Stabilizes the commander's view in the Fennek (Strider). -## Vehicle mounted machine guns ROF +### Vehicle mounted machine guns ROF The rate of fire of vehicle mounted miniguns and machine guns is adjusted to match real life values. -## 120mm gun and mortar behavior +### 120mm gun and mortar behavior MBT main guns and mortars can no longer lock on enemies. The AT rounds of both now have raised cost values to encourage the AI to not use those rounds against foot soldiers over their machine guns or HE rounds. diff --git a/documentation/feature/weaponselect.md b/documentation/feature/weaponselect.md index 1fc9cec3e2..36d11d3c97 100644 --- a/documentation/feature/weaponselect.md +++ b/documentation/feature/weaponselect.md @@ -7,19 +7,19 @@ parent: wiki # Overview -## Weapon select +### Weapon select The number key can be used to quickly switch between weapons. (1 key - pistol, 2 key - rifle, 3 key - grenade launcher, 4 key - rocket launcher, 5 key - binocular) -## Holster weapon +### Holster weapon Adds the ability to holster a weapon on the back. (0 key) -## Engine select +### Engine select Quickly turn engine on and off (1 key - turn off, 2 key - turn on) -## Weapon select +### Weapon select Quickly switch between vehicle weapons (1-3 key) -## Grenade select +### Grenade select To prevent accidents a grenade has to be selected before it can be thrown. Toggles between explosive and non-explosive grenades. When spamming the throw key, the player won't automatically switch to frag grenades when all smokes are used up. Also shows an indicator to quickly see how many grenades are left when selecting and after throwing (6 key - switch between frag grenades, 7 key - switch between other grenades) diff --git a/documentation/feature/weather.md b/documentation/feature/weather.md index 31089495af..89f180338f 100644 --- a/documentation/feature/weather.md +++ b/documentation/feature/weather.md @@ -7,10 +7,10 @@ parent: wiki # Overview -## Sub-feature 1 +### Sub-feature 1 Short description of sub-feature 1. -## Sub-feature 2 +### Sub-feature 2 Short description of sub-feature 2. diff --git a/documentation/feature/windeflection.md b/documentation/feature/windeflection.md index b6d751b126..6fad78614f 100644 --- a/documentation/feature/windeflection.md +++ b/documentation/feature/windeflection.md @@ -7,7 +7,7 @@ parent: wiki # Overview -## Wind Deflection +### Wind Deflection Adds ballistic influences of wind, air density and temperature From cf487b544eea614e0b0a5aa184ec8714f6c47fd6 Mon Sep 17 00:00:00 2001 From: ulteq <ulteq@web.de> Date: Thu, 14 May 2015 16:07:41 +0200 Subject: [PATCH 47/51] Moved all temperature calculations into the weather module. --- .../functions/fnc_handleFired.sqf | 4 ++-- addons/advanced_ballistics/script_component.hpp | 1 - .../kestrel4500/functions/fnc_collectData.sqf | 15 ++++++++------- .../functions/fnc_generateOutputData.sqf | 15 ++++++++------- addons/kestrel4500/script_component.hpp | 2 -- addons/mk6mortar/functions/fnc_handleFired.sqf | 3 +-- addons/weather/XEH_preInit.sqf | 1 + .../fnc_calculateBarometricPressure.sqf | 5 +---- .../fnc_calculateTemperatureAtHeight.sqf | 17 +++++++++++++++++ 9 files changed, 38 insertions(+), 25 deletions(-) create mode 100644 addons/weather/functions/fnc_calculateTemperatureAtHeight.sqf diff --git a/addons/advanced_ballistics/functions/fnc_handleFired.sqf b/addons/advanced_ballistics/functions/fnc_handleFired.sqf index 5404953bd0..bb0b649da4 100644 --- a/addons/advanced_ballistics/functions/fnc_handleFired.sqf +++ b/addons/advanced_ballistics/functions/fnc_handleFired.sqf @@ -76,7 +76,7 @@ if (GVAR(barrelLengthInfluenceEnabled)) then { }; if (GVAR(ammoTemperatureEnabled)) then { - _temperature = GET_TEMPERATURE_AT_HEIGHT((getPosASL _unit) select 2); + _temperature = ((getPosASL _unit) select 2) call EFUNC(weather,calculateTemperatureAtHeight); _muzzleVelocityShift = [_AmmoCacheEntry select 9, _temperature] call FUNC(calculateAmmoTemperatureVelocityShift); if (_muzzleVelocityShift != 0) then { _bulletVelocity = _bulletVelocity vectorAdd ((vectorNormalized _bulletVelocity) vectorMultiply (_muzzleVelocityShift)); @@ -105,7 +105,7 @@ _barrelTwist = _WeaponCacheEntry select 0; _stabilityFactor = 1.5; if (_caliber > 0 && _bulletLength > 0 && _bulletMass > 0 && _barrelTwist > 0) then { - _temperature = GET_TEMPERATURE_AT_HEIGHT((getPosASL _unit) select 2); + _temperature = ((getPosASL _unit) select 2) call EFUNC(weather,calculateTemperatureAtHeight); _barometricPressure = ((getPosASL _bullet) select 2) call EFUNC(weather,calculateBarometricPressure); _stabilityFactor = [_caliber, _bulletLength, _bulletMass, _barrelTwist, _muzzleVelocity, _temperature, _barometricPressure] call FUNC(calculateStabilityFactor); }; diff --git a/addons/advanced_ballistics/script_component.hpp b/addons/advanced_ballistics/script_component.hpp index 3334bb3207..757330a5d0 100644 --- a/addons/advanced_ballistics/script_component.hpp +++ b/addons/advanced_ballistics/script_component.hpp @@ -21,6 +21,5 @@ #define SPECIFIC_GAS_CONSTANT_DRY_AIR 287.058 #define STD_AIR_DENSITY_ICAO 1.22498 #define STD_AIR_DENSITY_ASM 1.20885 -#define GET_TEMPERATURE_AT_HEIGHT(h) (EGVAR(weather,currentTemperature) - 0.0065 * (h)) #define EXTENSION_REQUIRED_VERSION "1.0" diff --git a/addons/kestrel4500/functions/fnc_collectData.sqf b/addons/kestrel4500/functions/fnc_collectData.sqf index a812ad0f7c..d5be7bbf22 100644 --- a/addons/kestrel4500/functions/fnc_collectData.sqf +++ b/addons/kestrel4500/functions/fnc_collectData.sqf @@ -14,13 +14,14 @@ */ #include "script_component.hpp" -private ["_playerDir", "_windSpeed", "_crosswind", "_headwind", "_humidity", "_temperature", "_humidity", "_barometricPressure", "_altitude"]; +private ["_playerAltitude", "_playerDir", "_windSpeed", "_crosswind", "_headwind", "_humidity", "_temperature", "_humidity", "_barometricPressure", "_altitude"]; +_playerAltitude = (getPosASL ACE_player) select 2; if (isNil QGVAR(MIN) || isNil QGVAR(MAX)) then { - _temperature = GET_TEMPERATURE_AT_HEIGHT((getPosASL ACE_player) select 2); + _temperature = _playerAltitude call EFUNC(weather,calculateTemperatureAtHeight); _humidity = EGVAR(weather,currentHumidity); - _barometricPressure = ((getPosASL ACE_player) select 2) call EFUNC(weather,calculateBarometricPressure); - _altitude = EGVAR(weather,Altitude) + ((getPosASL ACE_player) select 2); + _barometricPressure = _playerAltitude call EFUNC(weather,calculateBarometricPressure); + _altitude = EGVAR(weather,Altitude) + _playerAltitude; GVAR(MIN) = [0, 0, 0, 0, _temperature, _humidity, _barometricPressure, _altitude]; GVAR(MAX) = [0, 0, 0, 0, _temperature, _humidity, _barometricPressure, _altitude]; }; @@ -70,7 +71,7 @@ if (GVAR(MinAvgMaxMode) == 1) then { }; // TEMP -_temperature = GET_TEMPERATURE_AT_HEIGHT((getPosASL ACE_player) select 2); +_temperature = _playerAltitude call EFUNC(weather,calculateTemperatureAtHeight); GVAR(MIN) set [4, (GVAR(MIN) select 4) min _temperature]; GVAR(MAX) set [4, _temperature max (GVAR(MAX) select 4)]; GVAR(TOTAL) set [4, (GVAR(TOTAL) select 4) + _temperature]; @@ -82,13 +83,13 @@ GVAR(MAX) set [5, _humidity max (GVAR(MAX) select 5)]; GVAR(TOTAL) set [5, (GVAR(TOTAL) select 5) + _humidity]; // BARO -_barometricPressure = ((getPosASL ACE_player) select 2) call EFUNC(weather,calculateBarometricPressure); +_barometricPressure = _playerAltitude call EFUNC(weather,calculateBarometricPressure); GVAR(MIN) set [6, (GVAR(MIN) select 6) min _barometricPressure]; GVAR(MAX) set [6, _barometricPressure max (GVAR(MAX) select 6)]; GVAR(TOTAL) set [6, (GVAR(TOTAL) select 6) + _barometricPressure]; // ALTITUDE -_altitude = EGVAR(weather,Altitude) + ((getPosASL ACE_player) select 2); +_altitude = EGVAR(weather,Altitude) + _playerAltitude; GVAR(MIN) set [7, (GVAR(MIN) select 7) min _altitude]; GVAR(MAX) set [7, _altitude max (GVAR(MAX) select 7)]; GVAR(TOTAL) set [7, (GVAR(TOTAL) select 7) + _altitude]; \ No newline at end of file diff --git a/addons/kestrel4500/functions/fnc_generateOutputData.sqf b/addons/kestrel4500/functions/fnc_generateOutputData.sqf index 6b139fe72e..1549bbe9cb 100644 --- a/addons/kestrel4500/functions/fnc_generateOutputData.sqf +++ b/addons/kestrel4500/functions/fnc_generateOutputData.sqf @@ -34,10 +34,11 @@ _textInfoLine2 = ""; _windSpeed = call FUNC(measureWindSpeed); _windDir = (ACE_wind select 0) atan2 (ACE_wind select 1); -_temperature = GET_TEMPERATURE_AT_HEIGHT((getPosASL ACE_player) select 2); -_humidity = EGVAR(weather,currentHumidity); - _playerDir = getDir ACE_player; +_playerAltitude = (getPosASL ACE_player) select 2; + +_temperature = _playerAltitude call EFUNC(weather,calculateTemperatureAtHeight); +_humidity = EGVAR(weather,currentHumidity); GVAR(Direction) = 4 * floor(_playerDir / 90); if (_playerDir % 90 > 10) then { GVAR(Direction) = GVAR(Direction) + 1}; @@ -174,7 +175,7 @@ switch (GVAR(Menu)) do { }; case 6: { // BARO if (!GVAR(MinAvgMax)) then { - _textCenterBig = Str(round((((getPosASL ACE_player) select 2) call EFUNC(weather,calculateBarometricPressure)) * 10) / 10); + _textCenterBig = Str(round((_playerAltitude call EFUNC(weather,calculateBarometricPressure)) * 10) / 10); } else { _textCenterLine1Left = "Min"; _textCenterLine2Left = "Avg"; @@ -186,7 +187,7 @@ switch (GVAR(Menu)) do { }; case 7: { // ALTITUDE if (!GVAR(MinAvgMax)) then { - _textCenterBig = Str(round(EGVAR(weather,Altitude) + ((getPosASL ACE_player) select 2))); + _textCenterBig = Str(round(EGVAR(weather,Altitude) + _playerAltitude)); } else { _textCenterLine1Left = "Min"; _textCenterLine2Left = "Avg"; @@ -198,7 +199,7 @@ switch (GVAR(Menu)) do { }; case 8: { // User Screen 1 _textCenterLine1Left = Str(round(_playerDir)); - _textCenterLine2Left = Str(round(EGVAR(weather,Altitude) + ((getPosASL ACE_player) select 2))); + _textCenterLine2Left = Str(round(EGVAR(weather,Altitude) + _playerAltitude)); _textCenterLine3Left = Str(round(abs(_windSpeed) * 10) / 10); _textCenterLine1Right = GVAR(Directions) select GVAR(Direction); _textCenterLine2Right = "m"; @@ -207,7 +208,7 @@ switch (GVAR(Menu)) do { case 9: { // User Screen 2 _textCenterLine1Left = Str(round(_temperature * 10) / 10); _textCenterLine2Left = Str(round(_humidity * 100 * 10) / 10); - _textCenterLine3Left = Str(round((1013.25 * exp(-(EGVAR(weather,Altitude) + ((getPosASL ACE_player) select 2)) / 7990) - 10 * overcast) * 10) / 10); + _textCenterLine3Left = Str(round((_playerAltitude call EFUNC(weather,calculateBarometricPressure)) * 10) / 10); _textCenterLine1Right = "C"; _textCenterLine2Right = "%"; _textCenterLine3Right = "hPA"; diff --git a/addons/kestrel4500/script_component.hpp b/addons/kestrel4500/script_component.hpp index b8db2edb78..90c338ebeb 100644 --- a/addons/kestrel4500/script_component.hpp +++ b/addons/kestrel4500/script_component.hpp @@ -10,5 +10,3 @@ #endif #include "\z\ace\addons\main\script_macros.hpp" - -#define GET_TEMPERATURE_AT_HEIGHT(h) (EGVAR(weather,currentTemperature) - 0.0065 * (h)) diff --git a/addons/mk6mortar/functions/fnc_handleFired.sqf b/addons/mk6mortar/functions/fnc_handleFired.sqf index e2b440c520..284560b775 100644 --- a/addons/mk6mortar/functions/fnc_handleFired.sqf +++ b/addons/mk6mortar/functions/fnc_handleFired.sqf @@ -42,8 +42,7 @@ if (_bisAirFriction != 0) exitWith {ERROR("Non zero base airFriction");}; //Calculate air density: _altitude = (getPosASL _vehicle) select 2; -#define GET_TEMPERATURE_AT_HEIGHT(h) (EGVAR(weather,currentTemperature) - 0.0065 * (h)) -_temperature = GET_TEMPERATURE_AT_HEIGHT(_altitude); +_temperature = _altitude call EFUNC(weather,calculateTemperatureAtHeight); _pressure = _altitude call EFUNC(weather,calculateBarometricPressure); _relativeHumidity = EGVAR(weather,currentHumidity); _airDensity = [_temperature, _pressure, _relativeHumidity] call EFUNC(weather,calculateAirDensity); diff --git a/addons/weather/XEH_preInit.sqf b/addons/weather/XEH_preInit.sqf index 6e6e008a67..85166ce356 100644 --- a/addons/weather/XEH_preInit.sqf +++ b/addons/weather/XEH_preInit.sqf @@ -6,6 +6,7 @@ ADDON = false; PREP(calculateAirDensity); PREP(calculateBarometricPressure); PREP(calculateRoughnessLength); +PREP(calculateTemperatureAtHeight); PREP(calculateWindSpeed); PREP(displayWindInfo); PREP(getMapData); diff --git a/addons/weather/functions/fnc_calculateBarometricPressure.sqf b/addons/weather/functions/fnc_calculateBarometricPressure.sqf index c65d343c93..1e1d47098c 100644 --- a/addons/weather/functions/fnc_calculateBarometricPressure.sqf +++ b/addons/weather/functions/fnc_calculateBarometricPressure.sqf @@ -14,7 +14,4 @@ */ #include "script_component.hpp" -private ["_altitude"]; -_altitude = _this; - -(1013.25 * exp(-(GVAR(Altitude) + _altitude) / 7990) - 10 * overcast) +(1013.25 * exp(-(GVAR(Altitude) + _this) / 7990) - 10 * overcast) diff --git a/addons/weather/functions/fnc_calculateTemperatureAtHeight.sqf b/addons/weather/functions/fnc_calculateTemperatureAtHeight.sqf new file mode 100644 index 0000000000..dd31dfe05e --- /dev/null +++ b/addons/weather/functions/fnc_calculateTemperatureAtHeight.sqf @@ -0,0 +1,17 @@ +/* + * Author: Ruthberg + * + * Calculates the temperature based on altitude and weather + * + * Arguments: + * 0: height - meters <NUMBER> + * + * Return Value: + * 0: temperature - degrees celsius <NUMBER> + * + * Return value: + * None + */ +#include "script_component.hpp" + +(GVAR(currentTemperature) - 0.0065 * _this) From 53bc8ca9e5e2674d872e4abf46b0857e02afb3ff Mon Sep 17 00:00:00 2001 From: KoffeinFlummi <koffeinflummi@gmail.com> Date: Thu, 14 May 2015 16:13:04 +0200 Subject: [PATCH 48/51] Change H1s to H2 --- documentation/feature/advanced_ballistics.md | 6 +++--- documentation/feature/ai.md | 2 +- documentation/feature/aircraft.md | 4 ++-- documentation/feature/apl.md | 6 +++--- documentation/feature/atragmx.md | 6 +++--- documentation/feature/attach.md | 4 ++-- documentation/feature/backpacks.md | 6 +++--- documentation/feature/ballistics.md | 6 +++--- documentation/feature/captives.md | 4 ++-- documentation/feature/difficulties.md | 6 +++--- documentation/feature/disarming.md | 6 +++--- documentation/feature/disposable.md | 6 +++--- documentation/feature/dragging.md | 6 +++--- documentation/feature/explosives.md | 6 +++--- documentation/feature/fcs.md | 6 +++--- documentation/feature/flashsuppressors.md | 6 +++--- documentation/feature/frag.md | 6 +++--- documentation/feature/gforces.md | 6 +++--- documentation/feature/goggles.md | 6 +++--- documentation/feature/grenades.md | 6 +++--- documentation/feature/hearing.md | 6 +++--- documentation/feature/hitreactions.md | 6 +++--- documentation/feature/interact_menu.md | 6 +++--- documentation/feature/interaction.md | 6 +++--- documentation/feature/inventory.md | 6 +++--- documentation/feature/javelin.md | 6 +++--- documentation/feature/kestrel4500.md | 6 +++--- documentation/feature/laser.md | 6 +++--- documentation/feature/laser_selfdesignate.md | 6 +++--- documentation/feature/laserpointer.md | 6 +++--- documentation/feature/logistics_uavbattery.md | 6 +++--- documentation/feature/logistics_wirecutter.md | 6 +++--- documentation/feature/magazinerepack.md | 6 +++--- documentation/feature/map.md | 6 +++--- documentation/feature/maptools.md | 6 +++--- documentation/feature/markers.md | 6 +++--- documentation/feature/microdagr.md | 6 +++--- documentation/feature/missileguidance.md | 6 +++--- documentation/feature/missionmodules.md | 6 +++--- documentation/feature/mk6mortar.md | 6 +++--- documentation/feature/movement.md | 6 +++--- documentation/feature/nametags.md | 6 +++--- documentation/feature/nightvision.md | 6 +++--- documentation/feature/noidle.md | 6 +++--- documentation/feature/noradio.md | 6 +++--- documentation/feature/norearm.md | 6 +++--- documentation/feature/optics.md | 6 +++--- documentation/feature/optionsmenu.md | 6 +++--- documentation/feature/ovepressure.md | 6 +++--- documentation/feature/overheating.md | 6 +++--- documentation/feature/parachute.md | 6 +++--- documentation/feature/protection.md | 6 +++--- documentation/feature/ragdolls.md | 6 +++--- documentation/feature/realisticnames.md | 6 +++--- documentation/feature/recoil.md | 6 +++--- documentation/feature/reload.md | 6 +++--- documentation/feature/reloadlaunchers.md | 6 +++--- documentation/feature/respawn.md | 6 +++--- documentation/feature/safemode.md | 6 +++--- documentation/feature/scopes.md | 6 +++--- documentation/feature/smallarms.md | 6 +++--- documentation/feature/switchunits.md | 6 +++--- documentation/feature/testmissions.md | 6 +++--- documentation/feature/thermals.md | 6 +++--- documentation/feature/vector.md | 6 +++--- documentation/feature/vehiclelock.md | 6 +++--- documentation/feature/vehicles.md | 6 +++--- documentation/feature/weaponselect.md | 6 +++--- documentation/feature/weather.md | 6 +++--- documentation/feature/windeflection.md | 6 +++--- 70 files changed, 205 insertions(+), 205 deletions(-) diff --git a/documentation/feature/advanced_ballistics.md b/documentation/feature/advanced_ballistics.md index 9b601aa397..d83487780b 100644 --- a/documentation/feature/advanced_ballistics.md +++ b/documentation/feature/advanced_ballistics.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,9 +14,9 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/ai.md b/documentation/feature/ai.md index a6ef524b25..a721a92360 100644 --- a/documentation/feature/ai.md +++ b/documentation/feature/ai.md @@ -6,7 +6,7 @@ order: 5 parent: wiki --- -# Overview +## Overview ### Adjusted AI skill values The idea here is to reduce the AI's godlike aiming capabilties while retaining it's high intelligence. The AI should be smart enough to move through a town, but also be 'human' in their reaction time and aim. diff --git a/documentation/feature/aircraft.md b/documentation/feature/aircraft.md index 094d328417..4893d0339e 100644 --- a/documentation/feature/aircraft.md +++ b/documentation/feature/aircraft.md @@ -6,7 +6,7 @@ order: 5 parent: wiki --- -# Overview +## Overview ### Adjusted flight behaviour Changes the flight behaviour of various aircraft. @@ -32,7 +32,7 @@ Adds a laser marker to the copilot seat of the Wildcat. Adds a HUD to the AH-9 based on the comanches HUD. -# Usage +## Usage ### Adjusted flight behaviour Changes the flight behaviour of various aircraft. diff --git a/documentation/feature/apl.md b/documentation/feature/apl.md index 9ac140018d..100184f6ff 100644 --- a/documentation/feature/apl.md +++ b/documentation/feature/apl.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -13,10 +13,10 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/atragmx.md b/documentation/feature/atragmx.md index 10a0a4e32e..5fb2545926 100644 --- a/documentation/feature/atragmx.md +++ b/documentation/feature/atragmx.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,10 +14,10 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/attach.md b/documentation/feature/attach.md index 359b9e5800..c18692383a 100644 --- a/documentation/feature/attach.md +++ b/documentation/feature/attach.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Attach items to uniform Enables player to attach IR grenades and chemlights to themselves. @@ -14,7 +14,7 @@ Enables player to attach IR grenades and chemlights to themselves. Adds an attachable IR strobe, which is only visible using night vision devices and offers better visibility than IR grenades. -# Usage +## Usage ### attaching to yourself - Press the self interaction key diff --git a/documentation/feature/backpacks.md b/documentation/feature/backpacks.md index b0ec4a31d1..81179d9673 100644 --- a/documentation/feature/backpacks.md +++ b/documentation/feature/backpacks.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Lock backpack Adds the ability to lock backpacks. Locked backpacks can't be accessed by others. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/ballistics.md b/documentation/feature/ballistics.md index c2748526db..65d06dd81f 100644 --- a/documentation/feature/ballistics.md +++ b/documentation/feature/ballistics.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Realistic rifle ammunition Changes include adjusted muzzle velocity, air friction and dispersion based on real life values. @@ -29,11 +29,11 @@ The M14 EBR now uses ammunition with decreased muzzle velocity and air friction Flash suppressors are similar to sound suppressors and prevent the muzzle flash reducing visibilty without decreasing combat effectiveness. Flash suppressors are available for the calibers 5.56mm, 6.5mm, 7.62mm, .45 ACP and 9mm. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/captives.md b/documentation/feature/captives.md index 0b04167f08..9dfd3592cd 100644 --- a/documentation/feature/captives.md +++ b/documentation/feature/captives.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Take captives Introduces a captivity system for taking and moving prisoners. @@ -20,7 +20,7 @@ You can frisk a restrained captive. You can surrender, while surrendering AI will cease fire. -# Usage +## Usage ### Capturing someone - You need cable ties. diff --git a/documentation/feature/difficulties.md b/documentation/feature/difficulties.md index 309725a252..10dd8b96f0 100644 --- a/documentation/feature/difficulties.md +++ b/documentation/feature/difficulties.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Elite mode adjustments Adjusts the default settings for the hardest difficulty to more closely resemble A2 settings. (No crosshair, stat screen, death messages...) -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/disarming.md b/documentation/feature/disarming.md index 10674a7626..5da00f427b 100644 --- a/documentation/feature/disarming.md +++ b/documentation/feature/disarming.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/disposable.md b/documentation/feature/disposable.md index dc072f2dc9..a0437e4e81 100644 --- a/documentation/feature/disposable.md +++ b/documentation/feature/disposable.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### NLAW disposable anti tank weapon Makes the NLAW disposable and provides the tools for other addons to do the same. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/dragging.md b/documentation/feature/dragging.md index 80eb6a5099..d4a177e4b5 100644 --- a/documentation/feature/dragging.md +++ b/documentation/feature/dragging.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -13,12 +13,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/explosives.md b/documentation/feature/explosives.md index 7971bf49fb..05b8cceac9 100644 --- a/documentation/feature/explosives.md +++ b/documentation/feature/explosives.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Advanced explosives placement Enables more precise placement of explosives. @@ -17,12 +17,12 @@ Offers different trigger types, like clackers and dead man switches. Enables attaching explosives to vehicles. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/fcs.md b/documentation/feature/fcs.md index 81a3c7553c..da7eaf4dee 100644 --- a/documentation/feature/fcs.md +++ b/documentation/feature/fcs.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Fire control system Offers a custom fire control system for tanks and helicopters. It enables engaging stationary and moving targets. @@ -17,13 +17,13 @@ Changes the default rangefinders, including those in vehicles, to require manual Anti air cannons can now use airburst ammunition. It will explode on the FCS' zeroed in range. -# Usage +## Usage To engage moving targets, place the crosshair on the enemy vehicle and press and hold tab. Follow the moving target with your crosshair for about 2 seconds and release tab. The optic will now be adjusted sideways to ensure a hit. To use manual lasing, place the crosshair on the object to range and press and hold tab. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/flashsuppressors.md b/documentation/feature/flashsuppressors.md index fc1ecb58cf..0231e8011e 100644 --- a/documentation/feature/flashsuppressors.md +++ b/documentation/feature/flashsuppressors.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/frag.md b/documentation/feature/frag.md index 99c1d6c922..1be27a7a87 100644 --- a/documentation/feature/frag.md +++ b/documentation/feature/frag.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/gforces.md b/documentation/feature/gforces.md index 6f6ad8dc83..00bd2fab17 100644 --- a/documentation/feature/gforces.md +++ b/documentation/feature/gforces.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/goggles.md b/documentation/feature/goggles.md index 991a063219..9f33dec1dc 100644 --- a/documentation/feature/goggles.md +++ b/documentation/feature/goggles.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Visual Effects for eyewear Adds color tint to sunglasses and other eyewear. Causes raindrops to appear on @@ -13,12 +13,12 @@ the screen in rain. Causes dirt to appear on the screen when dirt is kicked up nearby (e.g. explsions, rotor wash, bullet impacts). -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/grenades.md b/documentation/feature/grenades.md index 14a41c1757..eba0a7c7ec 100644 --- a/documentation/feature/grenades.md +++ b/documentation/feature/grenades.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Throw modes Provides different modes for throwing grenades (high throw, precision throw and drop mode). @@ -17,12 +17,12 @@ Adds throwable hand flares in the colors white, red, green and yellow. Additiona Adds stun grenade. This will also affect AI. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/hearing.md b/documentation/feature/hearing.md index 0ce0fbbc46..869c0b95ab 100644 --- a/documentation/feature/hearing.md +++ b/documentation/feature/hearing.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Hearing damage simulation Introduces hearing damage caused by nearby explosions and large-caliber weapons. @@ -15,12 +15,12 @@ Adds ear plugs to mitigate that effect. Soldiers with high caliber weapons or missile launchers will be equipped with those, but remember to put them in. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/hitreactions.md b/documentation/feature/hitreactions.md index 3263c7c01f..5e606e78c8 100644 --- a/documentation/feature/hitreactions.md +++ b/documentation/feature/hitreactions.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/interact_menu.md b/documentation/feature/interact_menu.md index 964ef31a0a..1d00b4d28f 100644 --- a/documentation/feature/interact_menu.md +++ b/documentation/feature/interact_menu.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/interaction.md b/documentation/feature/interaction.md index 86824f8c7e..0dfdd75478 100644 --- a/documentation/feature/interaction.md +++ b/documentation/feature/interaction.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/inventory.md b/documentation/feature/inventory.md index 151baf1ef7..ae68477030 100644 --- a/documentation/feature/inventory.md +++ b/documentation/feature/inventory.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Resized inventory UI Makes the inventory dialog bigger and increases the number of items that can be seen in the list at once. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/javelin.md b/documentation/feature/javelin.md index f6d98b398b..815a44de29 100644 --- a/documentation/feature/javelin.md +++ b/documentation/feature/javelin.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,7 +14,7 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. @@ -30,6 +30,6 @@ Steps to lock titan/Javelin: CTRL+TAB is default key to change firemode (configurable as a key) -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/kestrel4500.md b/documentation/feature/kestrel4500.md index a70b97eb17..f6ccfbae17 100644 --- a/documentation/feature/kestrel4500.md +++ b/documentation/feature/kestrel4500.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/laser.md b/documentation/feature/laser.md index e563aed749..db9bfadc4c 100644 --- a/documentation/feature/laser.md +++ b/documentation/feature/laser.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/laser_selfdesignate.md b/documentation/feature/laser_selfdesignate.md index d9a7cb375c..7bba862a8d 100644 --- a/documentation/feature/laser_selfdesignate.md +++ b/documentation/feature/laser_selfdesignate.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/laserpointer.md b/documentation/feature/laserpointer.md index d43b02978b..f1447f749c 100644 --- a/documentation/feature/laserpointer.md +++ b/documentation/feature/laserpointer.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/logistics_uavbattery.md b/documentation/feature/logistics_uavbattery.md index 448bd87d36..0e588a12d0 100644 --- a/documentation/feature/logistics_uavbattery.md +++ b/documentation/feature/logistics_uavbattery.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/logistics_wirecutter.md b/documentation/feature/logistics_wirecutter.md index bf19a60e35..bf1ffe7cc6 100644 --- a/documentation/feature/logistics_wirecutter.md +++ b/documentation/feature/logistics_wirecutter.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/magazinerepack.md b/documentation/feature/magazinerepack.md index eb66c4dace..8c20d47758 100644 --- a/documentation/feature/magazinerepack.md +++ b/documentation/feature/magazinerepack.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Repacking magazines Adds ability to repack magazines of the same type. An optional module provides @@ -13,12 +13,12 @@ options to adjust the repacking time of single rounds and whole magazines to the mission maker. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/map.md b/documentation/feature/map.md index 0df1cfcfb2..dbc9116fd9 100644 --- a/documentation/feature/map.md +++ b/documentation/feature/map.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/maptools.md b/documentation/feature/maptools.md index a3f94e0d57..25ca7f031d 100644 --- a/documentation/feature/maptools.md +++ b/documentation/feature/maptools.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/markers.md b/documentation/feature/markers.md index 821220997f..699ea521bb 100644 --- a/documentation/feature/markers.md +++ b/documentation/feature/markers.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Improved marker placement Expands the "Insert Marker" menu and allows to rotate map markers. Shows the currently selected channel to prevent misplacement. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/microdagr.md b/documentation/feature/microdagr.md index ee5126fb90..89d79decf9 100644 --- a/documentation/feature/microdagr.md +++ b/documentation/feature/microdagr.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/missileguidance.md b/documentation/feature/missileguidance.md index 6b66edb547..bb3e4802b1 100644 --- a/documentation/feature/missileguidance.md +++ b/documentation/feature/missileguidance.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/missionmodules.md b/documentation/feature/missionmodules.md index 358c00388a..79a2080b19 100644 --- a/documentation/feature/missionmodules.md +++ b/documentation/feature/missionmodules.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/mk6mortar.md b/documentation/feature/mk6mortar.md index 61a777c18c..9e3f8d0f5d 100644 --- a/documentation/feature/mk6mortar.md +++ b/documentation/feature/mk6mortar.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/movement.md b/documentation/feature/movement.md index 78a3f12d3c..86913c9e49 100644 --- a/documentation/feature/movement.md +++ b/documentation/feature/movement.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Jumping Adds the ability to jump when pressing the vault key while moving. (V - key) @@ -23,12 +23,12 @@ Adds a weight of the current loadout display in the inventory to estimate the fa The player can now use the sights of rifles and pistols in all prone stances. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/nametags.md b/documentation/feature/nametags.md index 1a7946f4e2..f3ffa9bc19 100644 --- a/documentation/feature/nametags.md +++ b/documentation/feature/nametags.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Nametag and rank display Adds nametags and soldier ranks to friendly players in multiplayer. This can be adjusted in the ACE Options Menu to not display the rank, display all nametags of nearby soldiers instead of those who are looked directly at, to require a button press to show the nametags or to disable them altogether. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/nightvision.md b/documentation/feature/nightvision.md index 35a42813a4..e1d476f03d 100644 --- a/documentation/feature/nightvision.md +++ b/documentation/feature/nightvision.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Multiple Generation NVGs Adds different night vision devices with varying image quality and field of @@ -22,10 +22,10 @@ Enables the user to manually adjust NVG brightness. -# Usage +## Usage Use Alt+PageUp and Alt+PageDown to adjust NVG brightness. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/noidle.md b/documentation/feature/noidle.md index b6b4261f7c..2b28005fb4 100644 --- a/documentation/feature/noidle.md +++ b/documentation/feature/noidle.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/noradio.md b/documentation/feature/noradio.md index a19fd60145..0353f8f16a 100644 --- a/documentation/feature/noradio.md +++ b/documentation/feature/noradio.md @@ -5,19 +5,19 @@ group: feature parent: wiki --- -# Overview +## Overview ### Silent avatar Mutes the player's automatic callouts ("Enemy man, 100 meters, front!"). Does not mute AI callouts. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/norearm.md b/documentation/feature/norearm.md index 559551eab9..fafb98f6af 100644 --- a/documentation/feature/norearm.md +++ b/documentation/feature/norearm.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/optics.md b/documentation/feature/optics.md index c9c6804109..8cf94fe16d 100644 --- a/documentation/feature/optics.md +++ b/documentation/feature/optics.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/optionsmenu.md b/documentation/feature/optionsmenu.md index 0630f894ca..f857158d64 100644 --- a/documentation/feature/optionsmenu.md +++ b/documentation/feature/optionsmenu.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/ovepressure.md b/documentation/feature/ovepressure.md index aa528afbf8..34a357ae0c 100644 --- a/documentation/feature/ovepressure.md +++ b/documentation/feature/ovepressure.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/overheating.md b/documentation/feature/overheating.md index 916d60af90..89e0781751 100644 --- a/documentation/feature/overheating.md +++ b/documentation/feature/overheating.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Weapon Jamming Adds a propability to jam a weapon when firing. Jams can be cleared by @@ -23,13 +23,13 @@ Adds the ability to changes barrels on machine guns to compensate for those effects. -# Usage +## Usage To clear a jammed weapon, press Shift+R. *needs documentation on swapping barrels* -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/parachute.md b/documentation/feature/parachute.md index a2a27a3228..544dbaa0f2 100644 --- a/documentation/feature/parachute.md +++ b/documentation/feature/parachute.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Altimeter Removes the altitude and descend speed UI elements when free-falling and @@ -19,12 +19,12 @@ Adds a non-steerable parachute variant for jet pilots. Smoothens parachute landing animation. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/protection.md b/documentation/feature/protection.md index ae370756b8..1e73cd4bd5 100644 --- a/documentation/feature/protection.md +++ b/documentation/feature/protection.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/ragdolls.md b/documentation/feature/ragdolls.md index b8d125b792..86480b5702 100644 --- a/documentation/feature/ragdolls.md +++ b/documentation/feature/ragdolls.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Adjusted Ragdolls Changes the ragdolls to react more to the force of shots and explosions. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/realisticnames.md b/documentation/feature/realisticnames.md index 9458f752a4..af434f7df2 100644 --- a/documentation/feature/realisticnames.md +++ b/documentation/feature/realisticnames.md @@ -5,19 +5,19 @@ group: feature parent: wiki --- -# Overview +## Overview ### Real names Changes the names of vehicles, magazines, weapons, grenades, explosive charges and mines to their respective real-world counterparts whenever possible. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/recoil.md b/documentation/feature/recoil.md index 23d49877bb..cdf9b20c3f 100644 --- a/documentation/feature/recoil.md +++ b/documentation/feature/recoil.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Recoil adjustment Overhauls the recoil system reducing upwards recoil. @@ -17,12 +17,12 @@ Introducing camshake when firing on foot or as vehicle gunner depending on stanc Firing in longer burst (> 3 rounds per burst) slightly reduces the accuracy. Firing machine guns in bursts is now useful. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/reload.md b/documentation/feature/reload.md index fac42ef365..6d85431b1d 100644 --- a/documentation/feature/reload.md +++ b/documentation/feature/reload.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Ammo count Hides the actual round count of magazines and removes the icon when the current magazine is emptied. The player can instead check the magazine weight, but that gives only estimated values for magazines with more than 10 rounds. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/reloadlaunchers.md b/documentation/feature/reloadlaunchers.md index 7000ff5fd0..395e6cf706 100644 --- a/documentation/feature/reloadlaunchers.md +++ b/documentation/feature/reloadlaunchers.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,11 +14,11 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/respawn.md b/documentation/feature/respawn.md index d07d179438..3acde74828 100644 --- a/documentation/feature/respawn.md +++ b/documentation/feature/respawn.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Respawn with same gear Requires the Respawn Gear module to be placed. Respawned soldiers now have their loadout when killed. @@ -17,12 +17,12 @@ Shows friendly fire warnings in system chat if the module is placed. Works even Adds rallypoints to all 3 sides to enable teleportation from base spawn to FOBs. Requires some setup from the mission maker. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/safemode.md b/documentation/feature/safemode.md index b0c006ef24..a24fc069c9 100644 --- a/documentation/feature/safemode.md +++ b/documentation/feature/safemode.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Safety You can now use the safety mode of any weapon. Switching weapon modes takes the safety off. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/scopes.md b/documentation/feature/scopes.md index cb1ac8fef6..611c0fdab8 100644 --- a/documentation/feature/scopes.md +++ b/documentation/feature/scopes.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sniper Scope Adjustment Enables snipers to adjust their scopes horizontally and vertically in mils. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/smallarms.md b/documentation/feature/smallarms.md index c714448283..bba205c28f 100644 --- a/documentation/feature/smallarms.md +++ b/documentation/feature/smallarms.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Magazine Names Unifies the name formatting of magazines similar to Arma 2 standards. @@ -17,12 +17,12 @@ Assault rifles no longer have tracer rounds in their non-tracer magazines. This All pistol and sub machine gun magazines now have adjusted capacaties to match their real life counterparts. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/switchunits.md b/documentation/feature/switchunits.md index 2102761f59..f3a695d63c 100644 --- a/documentation/feature/switchunits.md +++ b/documentation/feature/switchunits.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/testmissions.md b/documentation/feature/testmissions.md index 094fabbadb..95ac0106a0 100644 --- a/documentation/feature/testmissions.md +++ b/documentation/feature/testmissions.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/thermals.md b/documentation/feature/thermals.md index 295746ee1f..3312b2c547 100644 --- a/documentation/feature/thermals.md +++ b/documentation/feature/thermals.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Body Warmth Adjusts the thermal properties of humans making them less like torches. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/vector.md b/documentation/feature/vector.md index 206c6bfc37..83103ee61f 100644 --- a/documentation/feature/vector.md +++ b/documentation/feature/vector.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Vector IV Rangefinder Adds the Vector IV rangefinder, including all real-life usage modes (distance between two points, angle between two points etc.) -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/vehiclelock.md b/documentation/feature/vehiclelock.md index 6bd8d361ae..8054b680ef 100644 --- a/documentation/feature/vehiclelock.md +++ b/documentation/feature/vehiclelock.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/vehicles.md b/documentation/feature/vehicles.md index 14dba54d27..75aac8612c 100644 --- a/documentation/feature/vehicles.md +++ b/documentation/feature/vehicles.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Speedlimiter Adds ability to limit the max. speed of any vehicle. @@ -35,12 +35,12 @@ The rate of fire of vehicle mounted miniguns and machine guns is adjusted to mat MBT main guns and mortars can no longer lock on enemies. The AT rounds of both now have raised cost values to encourage the AI to not use those rounds against foot soldiers over their machine guns or HE rounds. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/weaponselect.md b/documentation/feature/weaponselect.md index 36d11d3c97..02ce3994d6 100644 --- a/documentation/feature/weaponselect.md +++ b/documentation/feature/weaponselect.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Weapon select The number key can be used to quickly switch between weapons. (1 key - pistol, 2 key - rifle, 3 key - grenade launcher, 4 key - rocket launcher, 5 key - binocular) @@ -23,12 +23,12 @@ Quickly switch between vehicle weapons (1-3 key) To prevent accidents a grenade has to be selected before it can be thrown. Toggles between explosive and non-explosive grenades. When spamming the throw key, the player won't automatically switch to frag grenades when all smokes are used up. Also shows an indicator to quickly see how many grenades are left when selecting and after throwing (6 key - switch between frag grenades, 7 key - switch between other grenades) -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/weather.md b/documentation/feature/weather.md index 89f180338f..bffe6bc8f5 100644 --- a/documentation/feature/weather.md +++ b/documentation/feature/weather.md @@ -5,7 +5,7 @@ group: feature parent: wiki --- -# Overview +## Overview ### Sub-feature 1 Short description of sub-feature 1. @@ -14,12 +14,12 @@ Short description of sub-feature 1. Short description of sub-feature 2. -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. diff --git a/documentation/feature/windeflection.md b/documentation/feature/windeflection.md index 6fad78614f..3668f7077c 100644 --- a/documentation/feature/windeflection.md +++ b/documentation/feature/windeflection.md @@ -5,18 +5,18 @@ group: feature parent: wiki --- -# Overview +## Overview ### Wind Deflection Adds ballistic influences of wind, air density and temperature -# Usage +## Usage Short overview of how to use the feature, e.g. menu options, key bindings, instructions. May not apply to all modules. -# Dependencies +## Dependencies List of modules that must be present for this module to work. From 20bd5957e3a27dc5f6aa9efc2a34423a28f31950 Mon Sep 17 00:00:00 2001 From: jaynus <jaynus@gmail.com> Date: Thu, 14 May 2015 07:15:52 -0700 Subject: [PATCH 49/51] Change to execNextFrame. --- addons/medical/functions/fnc_handleCreateLitter.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/medical/functions/fnc_handleCreateLitter.sqf b/addons/medical/functions/fnc_handleCreateLitter.sqf index 848bdb268c..681116f226 100644 --- a/addons/medical/functions/fnc_handleCreateLitter.sqf +++ b/addons/medical/functions/fnc_handleCreateLitter.sqf @@ -16,7 +16,7 @@ _litterObject = _litterClass createVehicleLocal _position; _litterObject setDir _direction; _litterObject setPosATL _position; // Move the litter next frame to get rid of HORRIBLE spacing, fixes #1112 -[{ (_this select 0) setPosATL (_this select 1); }, [_litterObject, _position], 0, 0] call EFUNC(common,waitAndExecute); +[{ (_this select 0) setPosATL (_this select 1); }, [_litterObject, _position]] call EFUNC(common,execNextFrame); _maxLitterCount = getArray (configFile >> "ACE_Settings" >> QGVAR(litterSimulationDetail) >> "_values") select GVAR(litterSimulationDetail); if((count GVAR(allCreatedLitter)) > _maxLitterCount ) then { From 99c04d0ed36406d7b8a1910469dbd38deab87207 Mon Sep 17 00:00:00 2001 From: jaynus <jaynus@gmail.com> Date: Thu, 14 May 2015 07:42:21 -0700 Subject: [PATCH 50/51] Fixed: shared_ptr vs. unique_ptr behavior in VS2013 --- extensions/common/p3d/compressed.cpp | 7 ++++++- extensions/common/p3d/compressed.hpp | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/extensions/common/p3d/compressed.cpp b/extensions/common/p3d/compressed.cpp index ac9909d039..d614e2b490 100644 --- a/extensions/common/p3d/compressed.cpp +++ b/extensions/common/p3d/compressed.cpp @@ -41,7 +41,12 @@ namespace ace { if (in.eof()) { in.clear(); } - _data = std::unique_ptr<uint8_t[]>(new uint8_t[expected_size + (expected_size % 8)]); +#if _MSC_VER == 1800 + _data = std::make_shared<uint8_t[]>(expected_size + (expected_size % 8)); +#else + _data = std::make_unique<uint8_t[]>(expected_size + (expected_size % 8)); +#endif + result = _mikero_lzo1x_decompress_safe(buffer, _data.get(), expected_size); if (result < 0) { LOG(ERROR) << "Decompression failed"; diff --git a/extensions/common/p3d/compressed.hpp b/extensions/common/p3d/compressed.hpp index 09113c928f..d9c3a5654b 100644 --- a/extensions/common/p3d/compressed.hpp +++ b/extensions/common/p3d/compressed.hpp @@ -12,7 +12,11 @@ namespace ace { protected: int _mikero_lzo1x_decompress_safe(const uint8_t*, uint8_t*, uint32_t); int _decompress_safe(std::istream &, uint32_t); +#if _MSC_VER == 1800 + std::shared_ptr<uint8_t[]> _data; +#else std::unique_ptr<uint8_t[]> _data; +#endif }; template<typename T> class compressed_base : public _compressed_base { From de4e41ffd52c61cf6b8c2d330ba0e7da6fb30596 Mon Sep 17 00:00:00 2001 From: bux578 <github@jonathandavid.de> Date: Thu, 14 May 2015 17:23:13 +0200 Subject: [PATCH 51/51] fix duplicate feature entry --- documentation/feature/ovepressure.md | 25 ------------------------- documentation/feature/overpressure.md | 2 +- 2 files changed, 1 insertion(+), 26 deletions(-) delete mode 100644 documentation/feature/ovepressure.md diff --git a/documentation/feature/ovepressure.md b/documentation/feature/ovepressure.md deleted file mode 100644 index 34a357ae0c..0000000000 --- a/documentation/feature/ovepressure.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -layout: wiki -title: Overpressure -group: feature -parent: wiki ---- - -## Overview - -### Sub-feature 1 -Short description of sub-feature 1. - -### Sub-feature 2 -Short description of sub-feature 2. - - -## Usage - -Short overview of how to use the feature, e.g. menu options, key bindings, -instructions. May not apply to all modules. - - -## Dependencies - -List of modules that must be present for this module to work. diff --git a/documentation/feature/overpressure.md b/documentation/feature/overpressure.md index ad6d426537..34a357ae0c 100644 --- a/documentation/feature/overpressure.md +++ b/documentation/feature/overpressure.md @@ -22,4 +22,4 @@ instructions. May not apply to all modules. ## Dependencies -`ace_common` +List of modules that must be present for this module to work.