Scene changes and Bug fixes #336
|
@ -1,4 +1,4 @@
|
|||
Start in Fullscreen: false
|
||||
Starting Scene ID: 97158628
|
||||
Starting Scene ID: 97086054
|
||||
Window Size: {x: 1920, y: 1080}
|
||||
Window Title: SHADE Engine
|
|
@ -1,16 +1,16 @@
|
|||
0 1
|
||||
1 2
|
||||
2 3
|
||||
3 4
|
||||
4 5
|
||||
5 6
|
||||
6 7
|
||||
7 8
|
||||
8 9
|
||||
9 10
|
||||
10 11
|
||||
11 12
|
||||
12 13
|
||||
13 14
|
||||
14 15
|
||||
15 16
|
||||
0 1 3
|
||||
1 2 65535
|
||||
2 3 65534
|
||||
3 4 65534
|
||||
4 5 65534
|
||||
5 6 65534
|
||||
6 7 65534
|
||||
7 8 65534
|
||||
8 9 65534
|
||||
9 10 65534
|
||||
10 11 65534
|
||||
11 12 65534
|
||||
12 13 65534
|
||||
13 14 65534
|
||||
14 15 65534
|
||||
15 16 65534
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Start Maximized: true
|
||||
Working Scene ID: 97086054
|
||||
Window Size: {x: 1920, y: 1013}
|
||||
Style: 0
|
|
@ -20,8 +20,8 @@ Size=400,400
|
|||
Collapsed=0
|
||||
|
||||
[Window][Inspector]
|
||||
Pos=1604,48
|
||||
Size=316,941
|
||||
Pos=1434,48
|
||||
Size=486,941
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
|
@ -76,7 +76,7 @@ DockId=0x0000000B,0
|
|||
|
||||
[Window][ Viewport]
|
||||
Pos=302,48
|
||||
Size=1300,836
|
||||
Size=1130,705
|
||||
Collapsed=0
|
||||
DockId=0x0000000B,0
|
||||
|
||||
|
@ -93,14 +93,14 @@ Collapsed=0
|
|||
DockId=0x0000000A,0
|
||||
|
||||
[Window][ Asset Browser]
|
||||
Pos=302,886
|
||||
Size=1300,103
|
||||
Pos=302,755
|
||||
Size=1130,234
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,0
|
||||
|
||||
[Window][Material Inspector]
|
||||
Pos=1604,48
|
||||
Size=316,941
|
||||
Pos=1434,48
|
||||
Size=486,941
|
||||
Collapsed=0
|
||||
DockId=0x00000006,1
|
||||
|
||||
|
@ -115,14 +115,16 @@ Size=464,144
|
|||
Collapsed=0
|
||||
|
||||
[Window][Collider Tag Panel]
|
||||
Pos=60,60
|
||||
Size=625,744
|
||||
Pos=302,48
|
||||
Size=1130,705
|
||||
Collapsed=0
|
||||
DockId=0x0000000B,1
|
||||
|
||||
[Window][Input Bindings Panel]
|
||||
Pos=60,60
|
||||
Size=154,204
|
||||
Pos=1434,48
|
||||
Size=486,941
|
||||
Collapsed=0
|
||||
DockId=0x00000006,2
|
||||
|
||||
[Window][Save Scene As]
|
||||
Pos=877,444
|
||||
|
@ -130,36 +132,36 @@ Size=165,120
|
|||
Collapsed=0
|
||||
|
||||
[Table][0x9D40AE32,17]
|
||||
Column 0 Weight=1.0000
|
||||
Column 1 Weight=1.0000
|
||||
Column 2 Weight=1.0000
|
||||
Column 3 Weight=1.0000
|
||||
Column 4 Weight=1.0000
|
||||
Column 5 Weight=1.0000
|
||||
Column 6 Weight=1.0000
|
||||
Column 7 Weight=1.0000
|
||||
Column 8 Weight=1.0000
|
||||
Column 9 Weight=1.0000
|
||||
Column 10 Weight=1.0000
|
||||
Column 11 Weight=1.0000
|
||||
Column 12 Weight=1.0000
|
||||
Column 13 Weight=1.0000
|
||||
Column 14 Weight=1.0000
|
||||
Column 15 Weight=1.0000
|
||||
Column 16 Weight=1.0000
|
||||
Column 0 Weight=0.9945
|
||||
Column 1 Weight=0.9945
|
||||
Column 2 Weight=0.9945
|
||||
Column 3 Weight=0.9945
|
||||
Column 4 Weight=0.9945
|
||||
Column 5 Weight=0.9945
|
||||
Column 6 Weight=0.9945
|
||||
Column 7 Weight=0.9945
|
||||
Column 8 Weight=0.9945
|
||||
Column 9 Weight=0.9945
|
||||
Column 10 Weight=0.9945
|
||||
Column 11 Weight=0.9945
|
||||
Column 12 Weight=1.0132
|
||||
Column 13 Weight=0.8444
|
||||
Column 14 Weight=0.9945
|
||||
Column 15 Weight=1.2009
|
||||
Column 16 Weight=1.0132
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=0,71 Size=1920,941 Split=X
|
||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1602,1036 Split=X
|
||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1432,1036 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=300,1036 Split=Y Selected=0x1E6EB881
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=225,863 Selected=0xE096E5AE
|
||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1300,1036 Split=Y Selected=0xB41284E7
|
||||
DockNode ID=0x00000002 Parent=0x00000005 SizeRef=1130,1036 Split=Y Selected=0xB41284E7
|
||||
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=1501,672 Split=Y Selected=0xB41284E7
|
||||
DockNode ID=0x00000009 Parent=0x00000007 SizeRef=1501,700 Split=Y Selected=0xB41284E7
|
||||
DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,836 CentralNode=1 Selected=0xB41284E7
|
||||
DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,103 Selected=0xB128252A
|
||||
DockNode ID=0x0000000B Parent=0x00000009 SizeRef=1501,705 CentralNode=1 Selected=0xB41284E7
|
||||
DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,234 Selected=0xB128252A
|
||||
DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6
|
||||
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532
|
||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=316,1036 Selected=0xE7039252
|
||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=486,1036 Selected=0xE7039252
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,210 @@
|
|||
- EID: 0
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 7, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 0.999999344, y: 0.999999821, z: 0.999999523}
|
||||
IsActive: true
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Drag: 0.00999999978
|
||||
Angular Drag: 0.100000001
|
||||
Use Gravity: false
|
||||
Interpolate: true
|
||||
Sleeping Enabled: true
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: false
|
||||
Freeze Rotation Y: false
|
||||
Freeze Rotation Z: false
|
||||
IsActive: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Collision Tag: 1
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Scripts:
|
||||
- Type: PhysicsTestObj
|
||||
Enabled: true
|
||||
forceAmount: 50
|
||||
torqueAmount: 500
|
||||
- EID: 1
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 4, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0.436332315}
|
||||
Scale: {x: 4.5999999, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Collision Tag: 1
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 2
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Camera Component:
|
||||
Position: {x: 0, y: 2, z: 7}
|
||||
Pitch: 0
|
||||
Yaw: 0
|
||||
Roll: 0
|
||||
Width: 1920
|
||||
Height: 1080
|
||||
Near: 0.00999999978
|
||||
Far: 10000
|
||||
Perspective: true
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 65539
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 2.70000005, y: 0.5, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: 0.436332315}
|
||||
Scale: {x: 4.5999999, y: 1, z: 1}
|
||||
IsActive: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Collision Tag: 1
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 4
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: -1.70000005, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: 0}
|
||||
Scale: {x: 10, y: 0.5, z: 10}
|
||||
IsActive: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Collision Tag: 1
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 5
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: -4.80000019, y: 3, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: 1.57079637}
|
||||
Scale: {x: 10, y: 0.5, z: 10}
|
||||
IsActive: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Collision Tag: 1
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 65542
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 4.80000019, y: 3, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: 1.57079637}
|
||||
Scale: {x: 10, y: 0.5, z: 10}
|
||||
IsActive: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Collision Tag: 1
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Scripts: ~
|
||||
- EID: 7
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 3}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
IsActive: true
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Drag: 0.00999999978
|
||||
Angular Drag: 0.100000001
|
||||
Use Gravity: true
|
||||
Interpolate: true
|
||||
Sleeping Enabled: true
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: false
|
||||
Freeze Rotation Y: false
|
||||
Freeze Rotation Z: false
|
||||
IsActive: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Collision Tag: 1
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Rotation Offset: {x: 0, y: 0, z: 0}
|
||||
IsActive: true
|
||||
Scripts: ~
|
|
@ -0,0 +1,3 @@
|
|||
Name: PhysicsTest
|
||||
ID: 97086054
|
||||
Type: 5
|
|
@ -159,7 +159,7 @@ public partial class LeafSearch : BehaviourTreeNode
|
|||
//Since transform position is often the raccoon's base and the ray needs to hit somewhere higher to be more reliable
|
||||
Vector3 rayDestination = plrT.GlobalPosition + plrT.GlobalScale * playerCollider.PositionOffset;
|
||||
Ray sightRay = new Ray(eyePosition, rayDestination - eyePosition);
|
||||
RaycastHit sightRayHit = Physics.Raycast(sightRay);
|
||||
RaycastHit sightRayHit = Physics.Raycast(sightRay, false, (ushort)65535)[0];
|
||||
//As of November 2022, RaycastHit contains only the FIRST object hit by
|
||||
//the ray in the Other GameObject data member
|
||||
//Diren may likely add ALL objects hit by the ray over December
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using SHADE;
|
||||
using SHADE_Scripting;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static PlayerController;
|
||||
using static Item;
|
||||
|
||||
|
@ -199,14 +200,25 @@ public class PickAndThrow : Script
|
|||
{
|
||||
if (pc != null)
|
||||
{
|
||||
Vector3 dirNor = pc.tranform.Forward;
|
||||
Vector3 playerRayPos = pc.tranform.GlobalPosition;
|
||||
playerRayPos.y += 0.05f;
|
||||
dirNor.Normalise();
|
||||
RaycastHit ray1 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(22.5f))), rayDistance);
|
||||
RaycastHit ray2 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(-22.5f))), rayDistance);
|
||||
RaycastHit ray3 = Physics.Raycast(new Ray(playerRayPos, dirNor), rayDistance * 0.75f);
|
||||
inRange = CheckForItem(ray1) || CheckForItem(ray2) || CheckForItem(ray3);
|
||||
Vector3 dirNor = pc.tranform.Forward;
|
||||
Vector3 playerRayPos = pc.tranform.GlobalPosition;
|
||||
playerRayPos.y += 0.05f;
|
||||
dirNor.Normalise();
|
||||
List<RaycastHit> rayList1 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(22.5f))), rayDistance, false, (ushort)65535);
|
||||
List<RaycastHit> rayList2 = Physics.Raycast(new Ray(playerRayPos, Vector3.RotateY(dirNor, SHADE.Math.DegreesToRadians(-22.5f))), rayDistance, false, (ushort)65535);
|
||||
List<RaycastHit> rayList3 = Physics.Raycast(new Ray(playerRayPos, dirNor), rayDistance * 0.75f, false, (ushort)65535);
|
||||
|
||||
if (rayList1.Count > 0 && rayList2.Count > 0 && rayList3.Count > 0)
|
||||
{
|
||||
RaycastHit ray1 = rayList1[0];
|
||||
RaycastHit ray2 = rayList2[0];
|
||||
RaycastHit ray3 = rayList3[0];
|
||||
inRange = CheckForItem(ray1) || CheckForItem(ray2) || CheckForItem(ray3);
|
||||
}
|
||||
else
|
||||
{
|
||||
inRange = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
using SHADE;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using static Item;
|
||||
|
||||
|
||||
public class PhysicsTestObj : Script
|
||||
{
|
||||
public RigidBody body { get; set; }
|
||||
public Collider collider { get; set; }
|
||||
|
||||
// Movement input booleans
|
||||
public enum Direction
|
||||
{
|
||||
UP,
|
||||
DOWN,
|
||||
FORWARD,
|
||||
BACK,
|
||||
LEFT,
|
||||
RIGHT
|
||||
};
|
||||
|
||||
internal bool[] move = new bool[6];
|
||||
internal bool[] rotate = new bool[6];
|
||||
|
||||
internal Vector3[] moveVec = new Vector3[6]
|
||||
{
|
||||
Vector3.Up,
|
||||
Vector3.Down,
|
||||
Vector3.Back,
|
||||
Vector3.Forward,
|
||||
Vector3.Left,
|
||||
Vector3.Right
|
||||
};
|
||||
|
||||
internal Vector3[] rotateVec = new Vector3[6]
|
||||
{
|
||||
Vector3.Right,
|
||||
Vector3.Left,
|
||||
Vector3.Forward,
|
||||
Vector3.Down,
|
||||
Vector3.Up,
|
||||
Vector3.Down
|
||||
};
|
||||
|
||||
internal Input.KeyCode[] moveInputKeys = new Input.KeyCode[6]
|
||||
{
|
||||
Input.KeyCode.Space,
|
||||
Input.KeyCode.LeftControl,
|
||||
Input.KeyCode.W,
|
||||
Input.KeyCode.S,
|
||||
Input.KeyCode.A,
|
||||
Input.KeyCode.D
|
||||
};
|
||||
|
||||
internal Input.KeyCode[] rotateInputKeys = new Input.KeyCode[6]
|
||||
{
|
||||
Input.KeyCode.I,
|
||||
Input.KeyCode.K,
|
||||
Input.KeyCode.U,
|
||||
Input.KeyCode.O,
|
||||
Input.KeyCode.J,
|
||||
Input.KeyCode.L
|
||||
};
|
||||
|
||||
public float forceAmount = 50.0f;
|
||||
public float torqueAmount = 500.0f;
|
||||
|
||||
protected override void awake()
|
||||
{
|
||||
body = GetComponent<RigidBody>();
|
||||
collider = GetComponent<Collider>();
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
move[i] = false;
|
||||
rotate[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void update()
|
||||
{
|
||||
Ray colliderRay = new Ray();
|
||||
colliderRay.Direction = Vector3.Right;
|
||||
Physics.ColliderRaycast(collider.Owner, colliderRay, false, 8);
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
if (Input.GetKeyDown(moveInputKeys[i]))
|
||||
move[i] = true;
|
||||
|
||||
if (Input.GetKeyDown(rotateInputKeys[i]))
|
||||
rotate[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void fixedUpdate()
|
||||
{
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
bool shouldMove = move[i];
|
||||
bool shouldRotate = rotate[i];
|
||||
|
||||
if (shouldMove)
|
||||
{
|
||||
//Vector3 offset = new Vector3(0.25f, 0.0f, 0.0f);
|
||||
//rb.AddForceAtLocalPos(moveVec[i] * forceAmount, offset);
|
||||
body.AddForce(moveVec[i] * forceAmount);
|
||||
move[i] = false;
|
||||
}
|
||||
|
||||
if (shouldRotate)
|
||||
{
|
||||
body.AddTorque(rotateVec[i] * torqueAmount);
|
||||
rotate[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
Name: PhysicsTestObj
|
||||
ID: 163401492
|
||||
Type: 9
|
|
@ -119,11 +119,11 @@ namespace Sandbox
|
|||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostLogicUpdate>();
|
||||
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPreUpdate>();
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsFixedUpdate>();
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsUpdate>();
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsSystem, SHPhysicsSystem::PhysicsPostUpdate>();
|
||||
|
||||
#ifndef _PUBLISH
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsDebugDrawSystem, SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine>();
|
||||
SHSystemManager::RegisterRoutine<SHPhysicsDebugDrawSystem, SHPhysicsDebugDrawSystem::PhysicsDebugDraw>();
|
||||
#endif
|
||||
|
||||
SHSystemManager::RegisterRoutine<SHTransformSystem, SHTransformSystem::TransformPostPhysicsUpdate>();
|
||||
|
@ -206,27 +206,6 @@ namespace Sandbox
|
|||
#else
|
||||
SHSystemManager::RunRoutines(false, SHFrameRateController::GetRawDeltaTime());
|
||||
#endif
|
||||
// TODO: Move into an Editor menu
|
||||
static bool drawContacts = false;
|
||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F9))
|
||||
{
|
||||
drawContacts = !drawContacts;
|
||||
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_POINTS, drawContacts);
|
||||
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACT_NORMALS, drawContacts);
|
||||
}
|
||||
static bool drawColliders = false;
|
||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
|
||||
{
|
||||
drawColliders = !drawColliders;
|
||||
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDER, drawColliders);
|
||||
}
|
||||
static bool drawRays = false;
|
||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F11))
|
||||
{
|
||||
drawRays = !drawRays;
|
||||
SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>()->SetDebugDrawFlag(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays);
|
||||
}
|
||||
|
||||
}
|
||||
// Finish all graphics jobs first
|
||||
graphicsSystem->AwaitGraphicsExecution();
|
||||
|
|
|
@ -44,23 +44,6 @@ namespace Sandbox
|
|||
{
|
||||
sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID);
|
||||
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (!physicsSystem)
|
||||
{
|
||||
SHLOGV_CRITICAL("Failed to get the physics system for building the scene!")
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SHEDITOR
|
||||
|
||||
physicsSystem->ForceBuild(SHSceneManager::GetCurrentSceneGraph());
|
||||
|
||||
#else
|
||||
|
||||
physicsSystem->BuildScene(SHSceneManager::GetCurrentSceneGraph());
|
||||
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* TESTING CODE */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
|
|
@ -92,7 +92,7 @@ namespace Sandbox
|
|||
|
||||
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
|
||||
|
||||
floorCollider.AddBoundingBox();
|
||||
//floorCollider.AddBoundingBox();
|
||||
|
||||
// Create blank entity with a script
|
||||
//testObj = SHADE::SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
|
@ -113,9 +113,9 @@ namespace Sandbox
|
|||
racoonTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
|
||||
racoonTransform.SetWorldPosition({ -3.0f, -2.0f, -5.0f });
|
||||
|
||||
racoonCollider.AddBoundingBox();
|
||||
//racoonCollider.AddBoundingBox();
|
||||
racoonCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f));
|
||||
racoonCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
|
||||
//racoonCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
|
||||
|
||||
auto racoonItemLocation = SHEntityManager::CreateEntity<SHTransformComponent>();
|
||||
auto& racoonItemLocationTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(racoonItemLocation);
|
||||
|
@ -138,15 +138,15 @@ namespace Sandbox
|
|||
itemTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
|
||||
itemTransform.SetWorldPosition({ 0.0f, -2.0f, -5.0f });
|
||||
|
||||
itemCollider.AddBoundingBox();
|
||||
itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f));
|
||||
//itemCollider.AddBoundingBox();
|
||||
//itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f));
|
||||
itemCollider.GetCollisionShape(1).SetIsTrigger(true);
|
||||
|
||||
itemCollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
|
||||
itemCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
|
||||
//itemCollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
|
||||
|
||||
itemCollider.GetCollisionShape(1).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
|
||||
itemCollider.GetCollisionShape(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f));
|
||||
//itemCollider.GetCollisionShape(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f));
|
||||
|
||||
itemRigidBody.SetInterpolate(false);
|
||||
itemRigidBody.SetFreezeRotationX(true);
|
||||
|
@ -167,9 +167,9 @@ namespace Sandbox
|
|||
AITransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
|
||||
AITransform.SetWorldPosition({ -8.0f, -2.0f, 2.5f });
|
||||
|
||||
AICollider.AddBoundingBox();
|
||||
//AICollider.AddBoundingBox();
|
||||
AICollider.GetCollisionShape(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
|
||||
AICollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
|
||||
//AICollider.GetCollisionShape(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
|
||||
|
||||
AIRigidBody.SetInterpolate(false);
|
||||
AIRigidBody.SetFreezeRotationX(true);
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "Scene/SHSceneManager.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Editor/SHEditor.h"
|
||||
#include "Math/Geometry/SHBox.h"
|
||||
#include "Math/SHRay.h"
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
|
||||
|
@ -162,9 +161,6 @@ namespace SHADE
|
|||
SHTransformComponent* transform = SHComponentManager::GetComponent_s<SHTransformComponent>(pivot.GetEID());
|
||||
auto physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
|
||||
|
||||
|
||||
|
||||
if (camera == nullptr || transform == nullptr)
|
||||
return;
|
||||
|
||||
|
@ -180,29 +176,28 @@ namespace SHADE
|
|||
camera->dirtyView = true;
|
||||
}*/
|
||||
|
||||
|
||||
pivot.ray.position = camera->GetPosition() + pivot.targetOffset;
|
||||
pivot.ray.direction = SHVec3::Normalise((camera->position + offset)- pivot.ray.position);
|
||||
|
||||
//SHLOG_INFO("Ray position: {},{},{} direction:{},{},{}",pivot.ray.position.x, pivot.ray.position.y, pivot.ray.position.z,pivot.ray.direction.x, pivot.ray.direction.y, pivot.ray.direction.z)
|
||||
//SHLOG_INFO("Ray position: {},{},{} direction:{},{},{}",pivot.ray.position.x, pivot.ray.position.y, pivot.ray.position.z,pivot.ray.direction.x, pivot.ray.direction.y, pivot.ray.direction.z)
|
||||
|
||||
auto result = physicsSystem->Raycast(pivot.ray );
|
||||
if (result && result.distance < pivot.GetArmLength())
|
||||
{
|
||||
|
||||
SHVec3 newOffset = SHVec3{ 0.0f,0.0f, result.distance * 0.8f };
|
||||
newOffset = SHVec3::RotateX(newOffset, -(SHMath::DegreesToRadians(pivot.GetPitch())));
|
||||
newOffset = SHVec3::RotateY(newOffset, (SHMath::DegreesToRadians(pivot.GetYaw())));
|
||||
pivot.offset = newOffset;
|
||||
//SHLOG_INFO("CAMERA COLLISION HIT, {}", result.distance);
|
||||
}
|
||||
else
|
||||
{
|
||||
//SHLOG_INFO("CAMERA COLLISION CANT HIT CAMERA");
|
||||
}
|
||||
//auto result = physicsSystem->Raycast(pivot.ray);
|
||||
//if (result && result.distance < pivot.GetArmLength())
|
||||
//{
|
||||
//
|
||||
// SHVec3 newOffset = SHVec3{ 0.0f,0.0f, result.distance * 0.8f };
|
||||
// newOffset = SHVec3::RotateX(newOffset, -(SHMath::DegreesToRadians(pivot.GetPitch())));
|
||||
// newOffset = SHVec3::RotateY(newOffset, (SHMath::DegreesToRadians(pivot.GetYaw())));
|
||||
// pivot.offset = newOffset;
|
||||
// //SHLOG_INFO("CAMERA COLLISION HIT, {}", result.distance);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// //SHLOG_INFO("CAMERA COLLISION CANT HIT CAMERA");
|
||||
//}
|
||||
|
||||
|
||||
|
||||
//
|
||||
//
|
||||
|
||||
// pivot.rtMatrix = SHMatrix::Inverse(pivot.rtMatrix);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHColliderTagPanel.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Physics/Collision/SHCollisionTagMatrix.h"
|
||||
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
|
||||
namespace SHADE
|
||||
|
@ -15,7 +15,7 @@ namespace SHADE
|
|||
ImGui::TableNextRow();
|
||||
ImGui::PushID("CollisionTagNames");
|
||||
|
||||
for (int i = SHCollisionTag::NUM_LAYERS; i >= 0; --i)
|
||||
for (int i = SHCollisionTag::NUM_LAYERS; i >= 1; --i)
|
||||
{
|
||||
ImGui::TableNextColumn();
|
||||
if(i == SHCollisionTag::NUM_LAYERS) continue;
|
||||
|
@ -29,7 +29,7 @@ namespace SHADE
|
|||
ImGui::PopID();
|
||||
}
|
||||
ImGui::PopID();
|
||||
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
|
||||
for (int i = 0; i < SHCollisionTag::NUM_LAYERS - 1; ++i)
|
||||
{
|
||||
std::string tagName = SHCollisionTagMatrix::GetTagName(i);
|
||||
auto tag = SHCollisionTagMatrix::GetTag(i);
|
||||
|
@ -53,8 +53,8 @@ namespace SHADE
|
|||
tagName2 = std::to_string(idx);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
//if(i == idx)
|
||||
// continue;
|
||||
if(i == idx)
|
||||
continue;
|
||||
std::string label = std::format("##{} vs {}", tagName, tagName2);
|
||||
SHEditorWidgets::CheckBox(label, [tag, &idx]{return tag->GetLayerState(idx);}, [tag, i, idx](bool const& value){tag->SetLayerState(idx, value); SHCollisionTagMatrix::GetTag(idx)->SetLayerState(i, value);}, label.substr(2));
|
||||
}
|
||||
|
|
|
@ -18,12 +18,13 @@
|
|||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
#include "Reflection/SHReflectionMetadata.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
#include "Physics/Collision/SHCollisionTagMatrix.h"
|
||||
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
|
||||
#include "Serialization/SHSerializationHelper.hpp"
|
||||
#include "Tools/Utilities/SHClipboardUtilities.h"
|
||||
#include "SHInspectorCommands.h"
|
||||
#include "Physics/Collision/SHCollisionTagMatrix.h"
|
||||
#include "Animation/SHAnimatorComponent.h"
|
||||
#include "Physics/Collision/Shapes/SHBox.h"
|
||||
#include "Physics/Collision/Shapes/SHSphere.h"
|
||||
#include "../SHEditorWindowManager.h"
|
||||
#include "../AssetBrowser/SHAssetBrowser.h"
|
||||
namespace SHADE
|
||||
|
@ -304,7 +305,7 @@ namespace SHADE
|
|||
{
|
||||
SHEditorWidgets::DragVec3("Force", { "X", "Y", "Z" }, [component] {return component->GetForce(); }, [](SHVec3 const& value) {}, false, "Force", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
||||
SHEditorWidgets::DragVec3("Torque", { "X", "Y", "Z" }, [component] {return component->GetTorque(); }, [](SHVec3 const& value) {}, false, "Torque", 0.1f, "%.3f", 0.0f, 0.0f, ImGuiSliderFlags_ReadOnly);
|
||||
SHEditorWidgets::CheckBox("Is Asleep", [component] {return component->GetIsSleeping(); }, [](bool value) {}, "If the Rigid Body is asleep");
|
||||
SHEditorWidgets::CheckBox("Is Asleep", [component] {return component->IsSleeping(); }, [](bool value) {}, "If the Rigid Body is asleep");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -336,6 +337,8 @@ namespace SHADE
|
|||
{
|
||||
DrawContextMenu(component);
|
||||
|
||||
SHEditorWidgets::CheckBox("Draw Colliders", [component] { return component->GetDebugDrawState(); }, [component](bool value) { component->SetDebugDrawState(value); });
|
||||
|
||||
auto& colliders = component->GetCollisionShapes();
|
||||
int const size = static_cast<int>(colliders.size());
|
||||
ImGui::BeginChild("Collision Shapes", { 0.0f, colliders.empty() ? 1.0f : 250.0f }, true);
|
||||
|
@ -343,57 +346,57 @@ namespace SHADE
|
|||
for (int i{}; i < size; ++i)
|
||||
{
|
||||
ImGui::PushID(i);
|
||||
SHCollisionShape* collider = &component->GetCollisionShape(i);
|
||||
SHCollisionShape* collisionShape = &component->GetCollisionShape(i);
|
||||
auto cursorPos = ImGui::GetCursorPos();
|
||||
|
||||
|
||||
if (collider->GetType() == SHCollisionShape::Type::BOX)
|
||||
if (collisionShape->GetType() == SHCollisionShape::Type::BOX)
|
||||
{
|
||||
SHEditorWidgets::BeginPanel(std::format("{} Box #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||
|
||||
const auto* BOX = reinterpret_cast<const SHBox*>(collider->GetShape());
|
||||
auto* boxShape = dynamic_cast<SHBox*>(collisionShape);
|
||||
SHEditorWidgets::DragVec3
|
||||
(
|
||||
"Half Extents", { "X", "Y", "Z" },
|
||||
[BOX] { return BOX->GetRelativeExtents(); },
|
||||
[collider](SHVec3 const& vec) { collider->SetBoundingBox(vec); });
|
||||
[boxShape] { return boxShape->GetRelativeExtents(); },
|
||||
[boxShape](SHVec3 const& vec) { boxShape->SetRelativeExtents(vec); });
|
||||
}
|
||||
else if (collider->GetType() == SHCollisionShape::Type::SPHERE)
|
||||
else if (collisionShape->GetType() == SHCollisionShape::Type::SPHERE)
|
||||
{
|
||||
SHEditorWidgets::BeginPanel(std::format("{} Sphere #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||
const auto* SPHERE = reinterpret_cast<const SHSphere*>(collider->GetShape());
|
||||
auto* sphereShape = dynamic_cast<SHSphere*>(collisionShape);
|
||||
SHEditorWidgets::DragFloat
|
||||
(
|
||||
"Radius",
|
||||
[SPHERE] { return SPHERE->GetRelativeRadius(); },
|
||||
[collider](float const& value) { collider->SetBoundingSphere(value); });
|
||||
[sphereShape] { return sphereShape->GetRelativeRadius(); },
|
||||
[sphereShape](float const& value) { sphereShape->SetRelativeRadius(value); });
|
||||
}
|
||||
else if (collider->GetType() == SHCollisionShape::Type::CAPSULE)
|
||||
{
|
||||
//else if (collisionShape->GetType() == SHCollisionShape::Type::CAPSULE)
|
||||
//{
|
||||
|
||||
}
|
||||
//}
|
||||
|
||||
{
|
||||
SHEditorWidgets::CheckBox("Is Trigger", [collider] { return collider->IsTrigger(); }, [collider](bool value) { collider->SetIsTrigger(value); });
|
||||
SHEditorWidgets::ComboBox("Tag", collisionTagNames, [collider]{return SHCollisionTagMatrix::GetTagIndex(collider->GetCollisionTag().GetName());}, [collider](int const& value){collider->SetCollisionTag(SHCollisionTagMatrix::GetTag(value));});
|
||||
SHEditorWidgets::CheckBox("Is Trigger", [collisionShape] { return collisionShape->IsTrigger(); }, [collisionShape](bool value) { collisionShape->SetIsTrigger(value); });
|
||||
SHEditorWidgets::ComboBox("Tag", collisionTagNames, [collisionShape]{return SHCollisionTagMatrix::GetTagIndex(collisionShape->GetCollisionTag().GetName());}, [collisionShape](int const& value){collisionShape->SetCollisionTag(SHCollisionTagMatrix::GetTag(value));});
|
||||
if(ImGui::CollapsingHeader("Physics Material"))
|
||||
{
|
||||
SHEditorWidgets::DragFloat("Friction", [collider] { return collider->GetFriction(); }, [collider](float value) { collider->SetFriction(value); }, "Friction", 0.05f, 0.0f, 1.0f);
|
||||
SHEditorWidgets::DragFloat("Bounciness", [collider] { return collider->GetBounciness(); }, [collider](float value) { collider->SetBounciness(value); }, "Bounciness", 0.05f, 0.0f, 1.0f);
|
||||
SHEditorWidgets::DragFloat("Mass Density", [collider] { return collider->GetDensity(); }, [collider](float value) { collider->SetDensity(value); }, "Mass Density", 0.1f, 0.0f);
|
||||
SHEditorWidgets::DragFloat("Friction", [collisionShape] { return collisionShape->GetFriction(); }, [collisionShape](float value) { collisionShape->SetFriction(value); }, "Friction", 0.05f, 0.0f, 1.0f);
|
||||
SHEditorWidgets::DragFloat("Bounciness", [collisionShape] { return collisionShape->GetBounciness(); }, [collisionShape](float value) { collisionShape->SetBounciness(value); }, "Bounciness", 0.05f, 0.0f, 1.0f);
|
||||
SHEditorWidgets::DragFloat("Mass Density", [collisionShape] { return collisionShape->GetDensity(); }, [collisionShape](float value) { collisionShape->SetDensity(value); }, "Mass Density", 0.1f, 0.0f);
|
||||
}
|
||||
|
||||
SHEditorWidgets::BeginPanel("Offsets",{ ImGui::GetContentRegionAvail().x, 30.0f });
|
||||
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collider] {return collider->GetPositionOffset(); }, [&collider](SHVec3 const& vec) {collider->SetPositionOffset(vec); });
|
||||
SHEditorWidgets::DragVec3("Position", { "X", "Y", "Z" }, [&collisionShape] {return collisionShape->GetPositionOffset(); }, [&collisionShape](SHVec3 const& vec) {collisionShape->SetPositionOffset(vec); });
|
||||
SHEditorWidgets::DragVec3("Rotation", { "X", "Y", "Z" },
|
||||
[&collider]
|
||||
[&collisionShape]
|
||||
{
|
||||
auto offset = collider->GetRotationOffset();
|
||||
auto offset = collisionShape->GetRotationOffset();
|
||||
return offset;
|
||||
},
|
||||
[&collider](SHVec3 const& vec)
|
||||
[&collisionShape](SHVec3 const& vec)
|
||||
{
|
||||
collider->SetRotationOffset(vec);
|
||||
collisionShape->SetRotationOffset(vec);
|
||||
}, true);
|
||||
SHEditorWidgets::EndPanel();
|
||||
}
|
||||
|
@ -408,7 +411,7 @@ namespace SHADE
|
|||
}
|
||||
if (colliderToDelete.has_value())
|
||||
{
|
||||
component->RemoveCollider(colliderToDelete.value());
|
||||
component->RemoveCollisionShape(colliderToDelete.value());
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
|
@ -418,11 +421,11 @@ namespace SHADE
|
|||
|
||||
if (ImGui::Selectable("Box Collider"))
|
||||
{
|
||||
newColl = component->AddBoundingBox();
|
||||
newColl = component->AddBoxCollisionShape(SHVec3::One);
|
||||
}
|
||||
if (ImGui::Selectable("Sphere Collider"))
|
||||
{
|
||||
newColl = component->AddBoundingSphere();
|
||||
newColl = component->AddSphereCollisionShape(1.0f);
|
||||
}
|
||||
|
||||
//No idea why this doesn't work
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "Serialization/SHSerialization.h"
|
||||
#include "Serialization/Configurations/SHConfigurationManager.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
||||
#include "Physics/System/SHPhysicsDebugDrawSystem.h"
|
||||
|
||||
const std::string LAYOUT_FOLDER_PATH{ std::string(ASSET_ROOT) + "/Editor/Layouts" };
|
||||
|
||||
|
@ -88,6 +89,7 @@ namespace SHADE
|
|||
DrawThemeMenu();
|
||||
DrawLayoutMenu();
|
||||
DrawApplicationConfig();
|
||||
DrawPhysicsSettings();
|
||||
|
||||
std::string const sceneName{std::format("Current Scene: {}",SHSceneManager::GetSceneName().data())};
|
||||
auto const size = ImGui::CalcTextSize(sceneName.data());
|
||||
|
@ -304,4 +306,27 @@ namespace SHADE
|
|||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
|
||||
void SHEditorMenuBar::DrawPhysicsSettings() noexcept
|
||||
{
|
||||
if (ImGui::BeginMenu("Physics Settings"))
|
||||
{
|
||||
if (auto* physicsDebugDraw = SHSystemManager::GetSystem<SHPhysicsDebugDrawSystem>())
|
||||
{
|
||||
bool drawColliders = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS);
|
||||
if (ImGui::Checkbox("Draw Colliders", &drawColliders))
|
||||
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::COLLIDERS, drawColliders);
|
||||
|
||||
bool drawContactPoints = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS);
|
||||
if (ImGui::Checkbox("Draw Contact Points", &drawContactPoints))
|
||||
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::CONTACTS, drawContactPoints);
|
||||
|
||||
bool drawRays = physicsDebugDraw->GetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS);
|
||||
if (ImGui::Checkbox("Draw Rays", &drawRays))
|
||||
physicsDebugDraw->SetFlagState(SHPhysicsDebugDrawSystem::DebugDrawFlags::RAYCASTS, drawRays);
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
}
|
||||
}//namespace SHADE
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace SHADE
|
|||
void DrawThemeMenu() noexcept;
|
||||
void DrawLayoutMenu() noexcept;
|
||||
void DrawApplicationConfig() noexcept;
|
||||
void DrawPhysicsSettings() noexcept;
|
||||
|
||||
float menuBarHeight = 20.0f;
|
||||
std::vector<std::filesystem::path> layoutPaths;
|
||||
|
|
|
@ -24,4 +24,5 @@ constexpr SHEventIdentifier SH_SCENE_EXIT_PRE { 15 };
|
|||
constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 };
|
||||
constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT { 17 };
|
||||
constexpr SHEventIdentifier SH_BUTTON_CLICK_EVENT { 18 };
|
||||
constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_DRAW_EVENT { 19 };
|
||||
|
||||
|
|
|
@ -1,250 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHBox.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a 3-Dimensional Axis Aligned Bounding Box
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHBox.h"
|
||||
// Project Headers
|
||||
#include "Math/SHMathHelpers.h"
|
||||
#include "Math/SHRay.h"
|
||||
|
||||
using namespace DirectX;
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHBox::SHBox() noexcept
|
||||
: RelativeExtents { SHVec3::One }
|
||||
{
|
||||
type = Type::BOX;
|
||||
}
|
||||
|
||||
SHBox::SHBox(const SHVec3& c, const SHVec3& hE) noexcept
|
||||
: RelativeExtents { SHVec3::One }
|
||||
{
|
||||
type = Type::BOX;
|
||||
|
||||
Center = c;
|
||||
Extents = hE;
|
||||
}
|
||||
|
||||
|
||||
SHBox::SHBox(const SHBox& rhs) noexcept
|
||||
{
|
||||
if (this == &rhs)
|
||||
return;
|
||||
|
||||
type = Type::BOX;
|
||||
|
||||
Center = rhs.Center;
|
||||
Extents = rhs.Extents;
|
||||
RelativeExtents = rhs.RelativeExtents;
|
||||
}
|
||||
|
||||
SHBox::SHBox(SHBox&& rhs) noexcept
|
||||
{
|
||||
type = Type::BOX;
|
||||
|
||||
Center = rhs.Center;
|
||||
Extents = rhs.Extents;
|
||||
RelativeExtents = rhs.RelativeExtents;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Operator Overload Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHBox& SHBox::operator=(const SHBox& rhs) noexcept
|
||||
{
|
||||
if (rhs.type != Type::BOX)
|
||||
{
|
||||
SHLOG_WARNING("Cannot assign a non-bounding box to a bounding box!")
|
||||
}
|
||||
else if (this != &rhs)
|
||||
{
|
||||
Center = rhs.Center;
|
||||
Extents = rhs.Extents;
|
||||
RelativeExtents = rhs.RelativeExtents;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SHBox& SHBox::operator=(SHBox&& rhs) noexcept
|
||||
{
|
||||
if (rhs.type != Type::BOX)
|
||||
{
|
||||
SHLOG_WARNING("Cannot assign a non-bounding box to a bounding box!")
|
||||
}
|
||||
else
|
||||
{
|
||||
Center = rhs.Center;
|
||||
Extents = rhs.Extents;
|
||||
RelativeExtents = rhs.RelativeExtents;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHVec3 SHBox::GetCenter() const noexcept
|
||||
{
|
||||
return Center;
|
||||
}
|
||||
|
||||
SHVec3 SHBox::GetWorldExtents() const noexcept
|
||||
{
|
||||
return Extents;
|
||||
}
|
||||
|
||||
const SHVec3& SHBox::GetRelativeExtents() const noexcept
|
||||
{
|
||||
return RelativeExtents;
|
||||
}
|
||||
|
||||
SHVec3 SHBox::GetMin() const noexcept
|
||||
{
|
||||
return SHVec3{ Center.x - Extents.x, Center.y - Extents.y, Center.z - Extents.z };
|
||||
}
|
||||
|
||||
SHVec3 SHBox::GetMax() const noexcept
|
||||
{
|
||||
return SHVec3{ Center.x + Extents.x, Center.y + Extents.y, Center.z + Extents.z };
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHBox::SetCenter(const SHVec3& newCenter) noexcept
|
||||
{
|
||||
Center = newCenter;
|
||||
}
|
||||
|
||||
void SHBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept
|
||||
{
|
||||
Extents = newWorldExtents;
|
||||
}
|
||||
|
||||
void SHBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept
|
||||
{
|
||||
RelativeExtents = newRelativeExtents;
|
||||
}
|
||||
|
||||
void SHBox::SetMin(const SHVec3& min) noexcept
|
||||
{
|
||||
const SHVec3 MAX = GetMax();
|
||||
|
||||
Center = SHVec3::Lerp(min, MAX, 0.5f);
|
||||
Extents = SHVec3::Abs((MAX - min) * 0.5f);
|
||||
}
|
||||
|
||||
void SHBox::SetMax(const SHVec3& max) noexcept
|
||||
{
|
||||
const SHVec3 MIN = GetMin();
|
||||
|
||||
Center = SHVec3::Lerp(MIN, max, 0.5f);
|
||||
Extents = SHVec3::Abs((max - MIN) * 0.5f);
|
||||
}
|
||||
|
||||
void SHBox::SetMinMax(const SHVec3& min, const SHVec3& max) noexcept
|
||||
{
|
||||
Center = SHVec3::Lerp(min, max, 0.5f);
|
||||
Extents = SHVec3::Abs((max - min) * 0.5f);
|
||||
}
|
||||
|
||||
std::vector<SHVec3> SHBox::GetVertices() const noexcept
|
||||
{
|
||||
std::vector<SHVec3> vertices{ 8 };
|
||||
GetCorners(vertices.data());
|
||||
return vertices;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHBox::TestPoint(const SHVec3& point) const noexcept
|
||||
{
|
||||
return BoundingBox::Contains(point);
|
||||
}
|
||||
|
||||
SHRaycastResult SHBox::Raycast(const SHRay& ray) const noexcept
|
||||
{
|
||||
SHRaycastResult result;
|
||||
|
||||
result.hit = Intersects(ray.position, ray.direction, result.distance);
|
||||
if (result.hit)
|
||||
{
|
||||
result.position = ray.position + ray.direction * result.distance;
|
||||
result.angle = SHVec3::Angle(ray.position, result.position);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SHBox::Contains(const SHBox& rhs) const noexcept
|
||||
{
|
||||
return BoundingBox::Contains(rhs);
|
||||
}
|
||||
|
||||
float SHBox::Volume() const noexcept
|
||||
{
|
||||
return 8.0f * (Extents.x * Extents.y * Extents.z);
|
||||
}
|
||||
|
||||
float SHBox::SurfaceArea() const noexcept
|
||||
{
|
||||
return 8.0f * ((Extents.x * Extents.y)
|
||||
+ (Extents.x * Extents.z)
|
||||
+ (Extents.y * Extents.z));
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHBox SHBox::Combine(const SHBox& lhs, const SHBox& rhs) noexcept
|
||||
{
|
||||
SHBox result;
|
||||
CreateMerged(result, lhs, rhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SHBox::Intersect(const SHBox& lhs, const SHBox& rhs) noexcept
|
||||
{
|
||||
return lhs.Intersects(rhs);
|
||||
}
|
||||
|
||||
SHBox SHBox::BuildFromBoxes(const SHBox* boxes, size_t numBoxes) noexcept
|
||||
{
|
||||
SHBox result;
|
||||
|
||||
for (size_t i = 1; i < numBoxes; ++i)
|
||||
CreateMerged(result, boxes[i - 1], boxes[i]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SHBox SHBox::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept
|
||||
{
|
||||
SHBox result;
|
||||
CreateFromPoints(result, numVertices, vertices, stride);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -1,105 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHBox.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a 3-Dimensional Axis Aligned Bounding Box
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <DirectXCollision.h>
|
||||
|
||||
// Project Headers
|
||||
#include "SHShape.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHBox : public SHShape,
|
||||
private DirectX::BoundingBox
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Static Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
static constexpr size_t NUM_VERTICES = 8;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
~SHBox () override = default;
|
||||
|
||||
SHBox () noexcept;
|
||||
SHBox (const SHVec3& center, const SHVec3& halfExtents) noexcept;
|
||||
SHBox (const SHBox& rhs) noexcept;
|
||||
SHBox (SHBox&& rhs) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHBox& operator= (const SHBox& rhs) noexcept;
|
||||
SHBox& operator= (SHBox&& rhs) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] SHVec3 GetCenter () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetWorldExtents () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetRelativeExtents () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetMin () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetMax () const noexcept;
|
||||
[[nodiscard]] std::vector<SHVec3> GetVertices () const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetCenter (const SHVec3& newCenter) noexcept;
|
||||
void SetWorldExtents (const SHVec3& newWorldExtents) noexcept;
|
||||
void SetRelativeExtents (const SHVec3& newRelativeExtents) noexcept;
|
||||
void SetMin (const SHVec3& min) noexcept;
|
||||
void SetMax (const SHVec3& max) noexcept;
|
||||
void SetMinMax (const SHVec3& min, const SHVec3& max) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept override;
|
||||
[[nodiscard]] SHRaycastResult Raycast(const SHRay& ray) const noexcept override;
|
||||
|
||||
[[nodiscard]] bool Contains (const SHBox& rhs) const noexcept;
|
||||
[[nodiscard]] float Volume () const noexcept;
|
||||
[[nodiscard]] float SurfaceArea () const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Static Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] static SHBox Combine (const SHBox& lhs, const SHBox& rhs) noexcept;
|
||||
[[nodiscard]] static bool Intersect (const SHBox& lhs, const SHBox& rhs) noexcept;
|
||||
[[nodiscard]] static SHBox BuildFromBoxes (const SHBox* boxes, size_t numBoxes) noexcept;
|
||||
[[nodiscard]] static SHBox BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHVec3 RelativeExtents;
|
||||
};
|
||||
|
||||
|
||||
} // namespace SHADE
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHBoundingSphere.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Bounding Sphere
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHSphere.h"
|
||||
// Project Headers
|
||||
#include "Math/SHMathHelpers.h"
|
||||
#include "Math/SHRay.h"
|
||||
|
||||
using namespace DirectX;
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHSphere::SHSphere() noexcept
|
||||
: RelativeRadius { 1.0f }
|
||||
{
|
||||
type = Type::SPHERE;
|
||||
}
|
||||
|
||||
SHSphere::SHSphere(const SHVec3& center, float radius) noexcept
|
||||
: RelativeRadius { 1.0f }
|
||||
{
|
||||
type = Type::SPHERE;
|
||||
|
||||
Center = center;
|
||||
Radius = radius;
|
||||
}
|
||||
|
||||
SHSphere::SHSphere(const SHSphere& rhs) noexcept
|
||||
{
|
||||
if (this == &rhs)
|
||||
return;
|
||||
|
||||
type = Type::SPHERE;
|
||||
|
||||
Center = rhs.Center;
|
||||
Radius = rhs.Radius;
|
||||
RelativeRadius = rhs.RelativeRadius;
|
||||
}
|
||||
|
||||
SHSphere::SHSphere(SHSphere&& rhs) noexcept
|
||||
{
|
||||
type = Type::SPHERE;
|
||||
|
||||
Center = rhs.Center;
|
||||
Radius = rhs.Radius;
|
||||
RelativeRadius = rhs.RelativeRadius;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Operator Overload Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHSphere& SHSphere::operator=(const SHSphere& rhs) noexcept
|
||||
{
|
||||
if (rhs.type != Type::SPHERE)
|
||||
{
|
||||
SHLOG_WARNING("Cannot assign a non-sphere to a sphere!")
|
||||
}
|
||||
else if (this != &rhs)
|
||||
{
|
||||
Center = rhs.Center;
|
||||
Radius = rhs.Radius;
|
||||
RelativeRadius = rhs.RelativeRadius;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SHSphere& SHSphere::operator=(SHSphere&& rhs) noexcept
|
||||
{
|
||||
if (rhs.type != Type::SPHERE)
|
||||
{
|
||||
SHLOG_WARNING("Cannot assign a non-sphere to a sphere!")
|
||||
}
|
||||
else
|
||||
{
|
||||
Center = rhs.Center;
|
||||
Radius = rhs.Radius;
|
||||
RelativeRadius = rhs.RelativeRadius;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHVec3 SHSphere::GetCenter() const noexcept
|
||||
{
|
||||
return Center;
|
||||
}
|
||||
|
||||
float SHSphere::GetWorldRadius() const noexcept
|
||||
{
|
||||
return Radius;
|
||||
}
|
||||
|
||||
float SHSphere::GetRelativeRadius() const noexcept
|
||||
{
|
||||
return RelativeRadius;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHSphere::SetCenter(const SHVec3& center) noexcept
|
||||
{
|
||||
Center = center;
|
||||
}
|
||||
|
||||
void SHSphere::SetWorldRadius(float newWorldRadius) noexcept
|
||||
{
|
||||
Radius = newWorldRadius;
|
||||
}
|
||||
|
||||
void SHSphere::SetRelativeRadius(float newRelativeRadius) noexcept
|
||||
{
|
||||
RelativeRadius = newRelativeRadius;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHSphere::TestPoint(const SHVec3& point) const noexcept
|
||||
{
|
||||
return BoundingSphere::Contains(point);
|
||||
}
|
||||
|
||||
SHRaycastResult SHSphere::Raycast(const SHRay& ray) const noexcept
|
||||
{
|
||||
SHRaycastResult result;
|
||||
|
||||
result.hit = Intersects(ray.position, ray.direction, result.distance);
|
||||
if (result.hit)
|
||||
{
|
||||
result.position = ray.position + ray.direction * result.distance;
|
||||
result.angle = SHVec3::Angle(ray.position, result.position);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SHSphere::Contains(const SHSphere& rhs) const noexcept
|
||||
{
|
||||
return BoundingSphere::Contains(rhs);
|
||||
}
|
||||
|
||||
float SHSphere::Volume() const noexcept
|
||||
{
|
||||
return (4.0f / 3.0f) * SHMath::PI * (Radius * Radius * Radius);
|
||||
}
|
||||
|
||||
float SHSphere::SurfaceArea() const noexcept
|
||||
{
|
||||
return 4.0f * SHMath::PI * (Radius * Radius);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHSphere SHSphere::Combine(const SHSphere& lhs, const SHSphere& rhs) noexcept
|
||||
{
|
||||
SHSphere result;
|
||||
CreateMerged(result, lhs, rhs);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SHSphere::Intersect(const SHSphere& lhs, const SHSphere& rhs) noexcept
|
||||
{
|
||||
return lhs.Intersects(rhs);
|
||||
}
|
||||
|
||||
SHSphere SHSphere::BuildFromSpheres(const SHSphere* spheres, size_t numSpheres) noexcept
|
||||
{
|
||||
SHSphere result;
|
||||
|
||||
for (size_t i = 1; i < numSpheres; ++i)
|
||||
CreateMerged(result, spheres[i - 1], spheres[i]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
SHSphere SHSphere::BuildFromVertices(const SHVec3* vertices, size_t numVertices, size_t stride) noexcept
|
||||
{
|
||||
SHSphere result;
|
||||
CreateFromPoints(result, numVertices, vertices, stride);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include <SHpch.h>
|
||||
|
||||
#include <reactphysics3d/mathematics/Ray.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHRay.h"
|
||||
|
||||
|
@ -30,7 +32,7 @@ namespace SHADE
|
|||
, direction { dir }
|
||||
{}
|
||||
|
||||
SHRay::SHRay(const reactphysics3d::Ray rp3dRay) noexcept
|
||||
SHRay::SHRay(const reactphysics3d::Ray& rp3dRay) noexcept
|
||||
: position { rp3dRay.point1 }
|
||||
, direction { SHVec3::Normalise(rp3dRay.point2 - rp3dRay.point1) }
|
||||
{}
|
||||
|
|
|
@ -16,8 +16,13 @@
|
|||
#include "SH_API.h"
|
||||
#include "Vector/SHVec3.h"
|
||||
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -40,7 +45,7 @@ namespace SHADE
|
|||
|
||||
SHRay () noexcept;
|
||||
SHRay (const SHVec3& pos, const SHVec3& dir) noexcept;
|
||||
SHRay (const reactphysics3d::Ray rp3dRay) noexcept;
|
||||
SHRay (const reactphysics3d::Ray& rp3dRay) noexcept;
|
||||
|
||||
SHRay (const SHRay&) noexcept = default;
|
||||
SHRay (SHRay&& ) noexcept = default;
|
||||
|
|
|
@ -246,8 +246,6 @@ namespace SHADE
|
|||
tf.world.position = SHVec3::Transform(tf.local.position, localToWorld);
|
||||
tf.world.scale = tf.local.scale * (parent ? parent->GetLocalScale() : SHVec3::One);
|
||||
|
||||
|
||||
|
||||
if (convertRotation)
|
||||
{
|
||||
tf.worldRotation = tf.localRotation + (parent ? parent->GetLocalRotation() : SHVec3::Zero);
|
||||
|
|
|
@ -14,18 +14,36 @@
|
|||
// Primary Header
|
||||
#include "SHCollisionTagMatrix.h"
|
||||
|
||||
#include "Tools/Utilities/SHUtilities.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Data Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHCollisionTag SHCollisionTagMatrix::collisionTags[SHCollisionTag::NUM_LAYERS];
|
||||
bool SHCollisionTagMatrix::dirty = true;
|
||||
SHCollisionTag SHCollisionTagMatrix::collisionTags[SHCollisionTag::NUM_LAYERS];
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHCollisionTagMatrix::IsDirty() noexcept
|
||||
{
|
||||
// Check if any collision tag is dirty
|
||||
for (auto& tag : collisionTags)
|
||||
{
|
||||
if (tag.IsDirty())
|
||||
{
|
||||
dirty = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return dirty;
|
||||
}
|
||||
|
||||
const std::string& SHCollisionTagMatrix::GetTagName(int tagIndex)
|
||||
{
|
||||
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
|
||||
|
@ -91,6 +109,8 @@ namespace SHADE
|
|||
if (collisionTag.GetName() != tagName)
|
||||
continue;
|
||||
|
||||
dirty = true;
|
||||
|
||||
collisionTag = newTag;
|
||||
return;
|
||||
}
|
||||
|
@ -105,6 +125,8 @@ namespace SHADE
|
|||
if (collisionTag.GetName() != tagName)
|
||||
continue;
|
||||
|
||||
dirty = true;
|
||||
|
||||
collisionTag.SetMask(mask);
|
||||
return;
|
||||
}
|
||||
|
@ -125,6 +147,8 @@ namespace SHADE
|
|||
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
|
||||
throw std::invalid_argument("Index out of range!");
|
||||
|
||||
dirty = true;
|
||||
|
||||
collisionTags[tagIndex] = newTag;
|
||||
}
|
||||
|
||||
|
@ -133,6 +157,8 @@ namespace SHADE
|
|||
if (tagIndex < 0 || tagIndex > SHCollisionTag::NUM_LAYERS)
|
||||
throw std::invalid_argument("Index out of range!");
|
||||
|
||||
dirty = true;
|
||||
|
||||
collisionTags[tagIndex].SetMask(mask);
|
||||
}
|
||||
|
||||
|
@ -145,8 +171,9 @@ namespace SHADE
|
|||
/**
|
||||
* I HATE FILE IO
|
||||
*
|
||||
* Each line in the file should be "index<space>tag name".
|
||||
* If the line fails to follow this format, use the default tag name (index + 1)
|
||||
* Each line in the file should be "index<space>tag name<space>mask".
|
||||
* If the line fails to follow this format, use the default tag name (index + 1) and default mask.
|
||||
* If no mask was read, use a default mask.
|
||||
*/
|
||||
|
||||
// Populate tag names with default
|
||||
|
@ -187,18 +214,40 @@ namespace SHADE
|
|||
{
|
||||
SHLOG_ERROR
|
||||
(
|
||||
"Collision tag file line {} does not match the required format of 'index<space>tag name'. Default tag used for index {}"
|
||||
"Collision tag file line {} does not match the required format of 'index<space>tag name<space>mask'. Default tag used for index {}"
|
||||
, linesRead + 1
|
||||
, tagIndex
|
||||
)
|
||||
|
||||
// Use default
|
||||
collisionTags[tagIndex].SetName(std::to_string(tagIndex + 1));
|
||||
collisionTags[tagIndex].SetMask(SHUtilities::ConvertEnum(SHCollisionTag::Layer::ALL));
|
||||
continue;
|
||||
}
|
||||
|
||||
collisionTags[tagIndex].SetName(tagName);
|
||||
|
||||
// Next element is the mask value
|
||||
std::string maskString;
|
||||
ss >> maskString;
|
||||
|
||||
uint16_t mask = std::numeric_limits<uint16_t>::max();
|
||||
if (maskString.empty())
|
||||
{
|
||||
SHLOG_ERROR
|
||||
(
|
||||
"Collision tag file line {} does not match the required format of 'index<space>tag name<space>mask'. Default mask used for index {}"
|
||||
, linesRead + 1
|
||||
, tagIndex
|
||||
)
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = static_cast<uint16_t>(std::stoi(maskString));
|
||||
}
|
||||
|
||||
collisionTags[tagIndex].SetMask(mask);
|
||||
|
||||
ss.clear();
|
||||
}
|
||||
|
||||
|
@ -215,9 +264,19 @@ namespace SHADE
|
|||
return;
|
||||
}
|
||||
|
||||
// Index Name Mask
|
||||
for (int i = 0; i < SHCollisionTag::NUM_LAYERS; ++i)
|
||||
collisionTagNamesFile << i << " " << collisionTags[i].GetName() << std::endl;
|
||||
collisionTagNamesFile << i << " " << collisionTags[i].GetName() << " " << collisionTags[i].GetMask() << std::endl;
|
||||
|
||||
collisionTagNamesFile.close();
|
||||
}
|
||||
|
||||
void SHCollisionTagMatrix::Clear() noexcept
|
||||
{
|
||||
dirty = false;
|
||||
|
||||
for (auto& tag : collisionTags)
|
||||
tag.dirty = false;
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -29,6 +29,7 @@ namespace SHADE
|
|||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] static bool IsDirty () noexcept;
|
||||
[[nodiscard]] static const std::string& GetTagName (int tagIndex);
|
||||
[[nodiscard]] static int GetTagIndex (const std::string& tagName) noexcept;
|
||||
|
||||
|
@ -39,29 +40,36 @@ namespace SHADE
|
|||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
static void SetTagName (const std::string& oldTagName, const std::string& newTagName) noexcept;
|
||||
static void SetTag (const std::string& tagName, const SHCollisionTag& newTag) noexcept;
|
||||
static void SetTag (const std::string& tagName, uint16_t mask) noexcept;
|
||||
static void SetTagName (const std::string& oldTagName, const std::string& newTagName) noexcept;
|
||||
static void SetTag (const std::string& tagName, const SHCollisionTag& newTag) noexcept;
|
||||
static void SetTag (const std::string& tagName, uint16_t mask) noexcept;
|
||||
|
||||
// Unsafe Setters: Can throw exceptions
|
||||
|
||||
static void SetTagName (int tagIndex, const std::string& newTagName);
|
||||
static void SetTag (int tagIndex, const SHCollisionTag& newTag);
|
||||
static void SetTag (int tagIndex, uint16_t mask);
|
||||
static void SetTagName (int tagIndex, const std::string& newTagName);
|
||||
static void SetTag (int tagIndex, const SHCollisionTag& newTag);
|
||||
static void SetTag (int tagIndex, uint16_t mask);
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
static void Init (const std::filesystem::path& tagNameFilePath) noexcept;
|
||||
static void Exit (const std::filesystem::path& tagNameFilePath) noexcept;
|
||||
static void Init (const std::filesystem::path& tagNameFilePath) noexcept;
|
||||
static void Exit (const std::filesystem::path& tagNameFilePath) noexcept;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Clears the dirty flag.
|
||||
*/
|
||||
static void Clear () noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
static bool dirty;
|
||||
static SHCollisionTag collisionTags[SHCollisionTag::NUM_LAYERS];
|
||||
};
|
||||
}
|
|
@ -23,15 +23,18 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHCollisionTag::SHCollisionTag() noexcept
|
||||
: mask { SHUtilities::ConvertEnum(Layer::ALL) }
|
||||
: dirty { true }
|
||||
, mask { SHUtilities::ConvertEnum(Layer::ALL) }
|
||||
{}
|
||||
|
||||
SHCollisionTag::SHCollisionTag(uint16_t _mask) noexcept
|
||||
: mask { _mask }
|
||||
: dirty { true }
|
||||
, mask { _mask }
|
||||
{}
|
||||
|
||||
SHCollisionTag::SHCollisionTag(Layer layer) noexcept
|
||||
: mask { SHUtilities::ConvertEnum(layer) }
|
||||
: dirty { true }
|
||||
, mask { SHUtilities::ConvertEnum(layer) }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -57,6 +60,11 @@ namespace SHADE
|
|||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHCollisionTag::IsDirty() const noexcept
|
||||
{
|
||||
return dirty;
|
||||
}
|
||||
|
||||
uint16_t SHCollisionTag::GetMask() const noexcept
|
||||
{
|
||||
return mask;
|
||||
|
@ -86,6 +94,7 @@ namespace SHADE
|
|||
|
||||
void SHCollisionTag::SetMask(uint16_t newMask) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
mask = newMask;
|
||||
}
|
||||
|
||||
|
@ -96,6 +105,8 @@ namespace SHADE
|
|||
|
||||
void SHCollisionTag::SetLayerState(Layer layer, bool state) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
|
||||
const auto VALUE = SHUtilities::ConvertEnum(layer);
|
||||
state ? mask |= VALUE : mask &= ~(VALUE);
|
||||
}
|
||||
|
@ -105,6 +116,8 @@ namespace SHADE
|
|||
if (layerIndex < 0 || layerIndex > NUM_LAYERS)
|
||||
throw std::invalid_argument("Index out of range!");
|
||||
|
||||
dirty = true;
|
||||
|
||||
const auto VALUE = 1U << layerIndex;
|
||||
state ? mask |= (VALUE) : mask &= ~(VALUE);
|
||||
}
|
|
@ -23,6 +23,13 @@ namespace SHADE
|
|||
|
||||
class SH_API SHCollisionTag
|
||||
{
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Friends */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHCollisionTagMatrix;
|
||||
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -82,6 +89,7 @@ namespace SHADE
|
|||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] bool IsDirty () const noexcept;
|
||||
[[nodiscard]] uint16_t GetMask () const noexcept;
|
||||
[[nodiscard]] const std::string& GetName () const noexcept;
|
||||
[[nodiscard]] bool GetLayerState (Layer layer) const noexcept;
|
||||
|
@ -101,6 +109,7 @@ namespace SHADE
|
|||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
bool dirty;
|
||||
uint16_t mask;
|
||||
std::string name;
|
||||
};
|
|
@ -1,350 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsRaycaster.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Physics Raycaster.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHPhysicsRaycaster.h"
|
||||
|
||||
/*
|
||||
* TODO(DIREN):
|
||||
* Once the physics engine has been rebuilt, this whole implementation should change
|
||||
* and just call PhysicsWorld.Raycast etc.
|
||||
*
|
||||
* SHRaycastResult can be converted to a bool when necessary.
|
||||
*/
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsRaycaster::SHPhysicsRaycaster() noexcept
|
||||
: world { nullptr }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
const SHPhysicsRaycaster::RaycastPairs& SHPhysicsRaycaster::GetRaycasts() const noexcept
|
||||
{
|
||||
return raycasts;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsRaycaster::SetObjectManager(SHPhysicsObjectManager* physicsObjectManager) noexcept
|
||||
{
|
||||
objectManager = physicsObjectManager;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsRaycaster::BindToWorld(rp3d::PhysicsWorld* physicsWorld) noexcept
|
||||
{
|
||||
world = physicsWorld;
|
||||
}
|
||||
|
||||
void SHPhysicsRaycaster::ClearFrame() noexcept
|
||||
{
|
||||
raycasts.clear();
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsRaycaster::Raycast(const SHRay& ray, float distance, const SHCollisionTag& collisionTag) noexcept
|
||||
{
|
||||
// Reset temp
|
||||
temp = SHPhysicsRaycastResult{};
|
||||
temp.distance = distance;
|
||||
|
||||
if (!world)
|
||||
{
|
||||
SHLOG_ERROR("Physics world missing for raycasting!")
|
||||
return temp;
|
||||
}
|
||||
|
||||
// If distance in infinity, cast to the default max distance of 2 km.
|
||||
if (distance == std::numeric_limits<float>::infinity())
|
||||
{
|
||||
world->raycast(ray, this, collisionTag);
|
||||
}
|
||||
else
|
||||
{
|
||||
const SHVec3 END_POINT = ray.position + ray.direction * distance;
|
||||
const rp3d::Ray RP3D_RAY{ ray.position, END_POINT };
|
||||
world->raycast(RP3D_RAY, this, collisionTag);
|
||||
}
|
||||
|
||||
// If a hit was found, populate temp info for return.
|
||||
if (temp.hit)
|
||||
{
|
||||
temp.distance = SHVec3::Distance(ray.position, temp.position);
|
||||
temp.angle = SHVec3::Angle(ray.position, temp.position);
|
||||
}
|
||||
|
||||
raycasts.emplace_back(ray, temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsRaycaster::Linecast(const SHVec3& start, const SHVec3& end, const SHCollisionTag& collisionTag) noexcept
|
||||
{
|
||||
temp = SHPhysicsRaycastResult{};
|
||||
temp.distance = SHVec3::Distance(start, end);
|
||||
|
||||
if (!world)
|
||||
{
|
||||
SHLOG_ERROR("Physics world missing for raycasting!")
|
||||
return temp;
|
||||
}
|
||||
|
||||
const rp3d::Ray RP3D_RAY{ start, end };
|
||||
world->raycast(RP3D_RAY, this, collisionTag);
|
||||
|
||||
if (temp.hit)
|
||||
{
|
||||
temp.distance = SHVec3::Distance(start, temp.position);
|
||||
temp.angle = SHVec3::Angle(start, temp.position);
|
||||
}
|
||||
|
||||
raycasts.emplace_back(RP3D_RAY, temp);
|
||||
return temp;
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderRaycast(EntityID eid, const SHRay& ray, float distance) noexcept
|
||||
{
|
||||
SHPhysicsRaycastResult result;
|
||||
result.distance = distance;
|
||||
|
||||
// Get a valid physics object with at least 1 collider.
|
||||
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
|
||||
if (!PHYSICS_OBJECT)
|
||||
return result;
|
||||
|
||||
auto* rp3dBody = PHYSICS_OBJECT->GetCollisionBody();
|
||||
|
||||
// Data to populate
|
||||
rp3d::RaycastInfo rp3dRaycastInfo;
|
||||
bool hit = false;
|
||||
|
||||
if (distance == std::numeric_limits<float>::infinity())
|
||||
{
|
||||
hit = rp3dBody->raycast(ray, rp3dRaycastInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
const SHVec3 END_POINT = ray.position + ray.direction * distance;
|
||||
const rp3d::Ray RP3D_RAY{ ray.position, END_POINT };
|
||||
hit = rp3dBody->raycast(RP3D_RAY, rp3dRaycastInfo);
|
||||
}
|
||||
|
||||
if (hit)
|
||||
{
|
||||
result.hit = true;
|
||||
result.position = rp3dRaycastInfo.worldPoint;
|
||||
result.normal = rp3dRaycastInfo.worldPoint;
|
||||
result.distance = SHVec3::Distance(ray.position, result.position);
|
||||
result.angle = SHVec3::Angle(ray.position, result.position);
|
||||
result.entityHit = eid;
|
||||
result.shapeIndex = findColliderIndex(rp3dBody, rp3dRaycastInfo.collider->getEntity());
|
||||
}
|
||||
|
||||
raycasts.emplace_back(ray, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderRaycast(EntityID eid, int shapeIndex, const SHRay& ray, float distance) noexcept
|
||||
{
|
||||
SHPhysicsRaycastResult result;
|
||||
result.distance = distance;
|
||||
|
||||
// Get a valid physics object with at least 1 collider.
|
||||
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
|
||||
if (!PHYSICS_OBJECT)
|
||||
return result;
|
||||
|
||||
// Boundary check for shape index
|
||||
if (shapeIndex < 0 || shapeIndex >= static_cast<int>(PHYSICS_OBJECT->GetCollisionBody()->getNbColliders()))
|
||||
{
|
||||
SHLOGV_WARNING("Invalid collision shape index passed in")
|
||||
return result;
|
||||
}
|
||||
|
||||
auto* rp3dCollider = PHYSICS_OBJECT->GetCollisionBody()->getCollider(shapeIndex);
|
||||
|
||||
rp3d::RaycastInfo rp3dRaycastInfo;
|
||||
bool hit = false;
|
||||
if (distance == std::numeric_limits<float>::infinity())
|
||||
{
|
||||
hit = rp3dCollider->raycast(ray, rp3dRaycastInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
const SHVec3 END_POINT = ray.position + ray.direction * distance;
|
||||
const rp3d::Ray RP3D_RAY{ ray.position, END_POINT };
|
||||
hit = rp3dCollider->raycast(RP3D_RAY, rp3dRaycastInfo);
|
||||
}
|
||||
|
||||
if (hit)
|
||||
{
|
||||
result.hit = true;
|
||||
result.position = rp3dRaycastInfo.worldPoint;
|
||||
result.normal = rp3dRaycastInfo.worldPoint;
|
||||
result.distance = SHVec3::Distance(ray.position, result.position);
|
||||
result.angle = SHVec3::Angle(ray.position, result.position);
|
||||
result.entityHit = eid;
|
||||
result.shapeIndex = shapeIndex;
|
||||
}
|
||||
|
||||
raycasts.emplace_back(ray, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderLinecast(EntityID eid, const SHVec3& start, const SHVec3& end) noexcept
|
||||
{
|
||||
SHPhysicsRaycastResult result;
|
||||
result.distance = SHVec3::Distance(start, end);
|
||||
|
||||
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
|
||||
if (!PHYSICS_OBJECT)
|
||||
return result;
|
||||
|
||||
auto* rp3dBody = PHYSICS_OBJECT->GetCollisionBody();
|
||||
|
||||
rp3d::RaycastInfo rp3dRaycastInfo;
|
||||
|
||||
const rp3d::Ray RP3D_RAY{ start, end };
|
||||
if (rp3dBody->raycast(RP3D_RAY, rp3dRaycastInfo))
|
||||
{
|
||||
result.hit = true;
|
||||
result.position = rp3dRaycastInfo.worldPoint;
|
||||
result.normal = rp3dRaycastInfo.worldPoint;
|
||||
result.distance = SHVec3::Distance(start, result.position);
|
||||
result.angle = SHVec3::Angle(end, result.position);
|
||||
result.entityHit = eid;
|
||||
result.shapeIndex = findColliderIndex(rp3dBody, rp3dRaycastInfo.collider->getEntity());
|
||||
}
|
||||
|
||||
raycasts.emplace_back(RP3D_RAY, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsRaycaster::ColliderLinecast(EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) noexcept
|
||||
{
|
||||
SHPhysicsRaycastResult result;
|
||||
result.distance = SHVec3::Distance(start, end);
|
||||
|
||||
const auto* PHYSICS_OBJECT = validateColliderRaycast(eid);
|
||||
if (!PHYSICS_OBJECT)
|
||||
return result;
|
||||
|
||||
if (shapeIndex < 0 || shapeIndex >= static_cast<int>(PHYSICS_OBJECT->GetCollisionBody()->getNbColliders()))
|
||||
{
|
||||
SHLOGV_WARNING("Invalid collision shape index passed in")
|
||||
return result;
|
||||
}
|
||||
|
||||
auto* rp3dCollider = PHYSICS_OBJECT->GetCollisionBody()->getCollider(shapeIndex);
|
||||
|
||||
rp3d::RaycastInfo rp3dRaycastInfo;
|
||||
|
||||
const rp3d::Ray RP3D_RAY{ start, end };
|
||||
if (rp3dCollider->raycast(RP3D_RAY, rp3dRaycastInfo))
|
||||
{
|
||||
result.hit = true;
|
||||
result.position = rp3dRaycastInfo.worldPoint;
|
||||
result.normal = rp3dRaycastInfo.worldPoint;
|
||||
result.distance = SHVec3::Distance(start, result.position);
|
||||
result.angle = SHVec3::Angle(end, result.position);
|
||||
result.entityHit = eid;
|
||||
result.shapeIndex = shapeIndex;
|
||||
}
|
||||
|
||||
raycasts.emplace_back(RP3D_RAY, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
rp3d::decimal SHPhysicsRaycaster::notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo)
|
||||
{
|
||||
temp.hit = true;
|
||||
temp.position = raycastInfo.worldPoint;
|
||||
temp.normal = raycastInfo.worldNormal;
|
||||
|
||||
if (!objectManager)
|
||||
{
|
||||
SHLOGV_ERROR("No physics object manager linked with raycaster to match bodies")
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
// Compare body IDs to find the matching physics object
|
||||
const auto HIT_BODY_EID = raycastInfo.body->getEntity();
|
||||
|
||||
for (const auto& [entityID, physicsObject] : objectManager->GetPhysicsObjects())
|
||||
{
|
||||
const auto RP3D_BODY = physicsObject.GetCollisionBody();
|
||||
|
||||
// Match rp3d bodies
|
||||
if (RP3D_BODY->getEntity() != HIT_BODY_EID)
|
||||
continue;
|
||||
|
||||
temp.entityHit = entityID;
|
||||
|
||||
// Find collider index
|
||||
if (const int INDEX = findColliderIndex(RP3D_BODY, raycastInfo.collider->getEntity()); INDEX > -1)
|
||||
{
|
||||
temp.shapeIndex = INDEX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject* SHPhysicsRaycaster::validateColliderRaycast(EntityID eid) noexcept
|
||||
{
|
||||
if (!objectManager)
|
||||
{
|
||||
SHLOGV_ERROR("No physics object manager linked with raycaster to match bodies")
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto* physicsObject = objectManager->GetPhysicsObject(eid);
|
||||
if (!physicsObject || physicsObject->GetCollisionBody()->getNbColliders() == 0)
|
||||
{
|
||||
SHLOGV_WARNING("Cannot cast ray at an entity without colliders!")
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return physicsObject;
|
||||
}
|
||||
|
||||
int SHPhysicsRaycaster::findColliderIndex(const rp3d::CollisionBody* rp3dBody, rp3d::Entity rp3dColliderEID) noexcept
|
||||
{
|
||||
const int NUM_COLLISION_SHAPES = static_cast<int>(rp3dBody->getNbColliders());
|
||||
for (int i = 0; i < NUM_COLLISION_SHAPES; ++i)
|
||||
{
|
||||
const auto COLLIDER_EID = rp3dBody->getCollider(i)->getEntity();
|
||||
if (COLLIDER_EID == rp3dColliderEID)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
} // namespace SHADE
|
|
@ -1,134 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsRaycaster.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a Physics Raycaster.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
||||
// Project Headers
|
||||
#include "Math/SHRay.h"
|
||||
#include "Physics/PhysicsObject/SHPhysicsObjectManager.h"
|
||||
#include "Physics/SHPhysicsWorld.h"
|
||||
#include "SH_API.h"
|
||||
#include "SHCollisionTags.h"
|
||||
#include "SHPhysicsRaycastResult.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHPhysicsRaycaster : public reactphysics3d::RaycastCallback
|
||||
{
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
using RaycastPair = std::pair<SHRay, SHPhysicsRaycastResult>;
|
||||
using RaycastPairs = std::vector<RaycastPair>;
|
||||
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsRaycaster() noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] const RaycastPairs& GetRaycasts() const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetObjectManager(SHPhysicsObjectManager* physicsObjectManager) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void BindToWorld (rp3d::PhysicsWorld* physicsWorld) noexcept;
|
||||
void ClearFrame () noexcept;
|
||||
|
||||
// TODO(Diren): Filtering, return all shades ray hits
|
||||
|
||||
SHPhysicsRaycastResult Raycast
|
||||
(
|
||||
const SHRay& ray
|
||||
, float distance = std::numeric_limits<float>::infinity()
|
||||
, const SHCollisionTag& collisionTag = SHCollisionTag{}
|
||||
) noexcept;
|
||||
|
||||
SHPhysicsRaycastResult Linecast
|
||||
(
|
||||
const SHVec3& start
|
||||
, const SHVec3& end
|
||||
, const SHCollisionTag& collisionTag = SHCollisionTag{}
|
||||
) noexcept;
|
||||
|
||||
SHPhysicsRaycastResult ColliderRaycast
|
||||
(
|
||||
EntityID eid
|
||||
, const SHRay& ray
|
||||
, float distance = std::numeric_limits<float>::infinity()
|
||||
) noexcept;
|
||||
|
||||
SHPhysicsRaycastResult ColliderRaycast
|
||||
(
|
||||
EntityID eid
|
||||
, int shapeIndex
|
||||
, const SHRay& ray
|
||||
, float distance = std::numeric_limits<float>::infinity()
|
||||
) noexcept;
|
||||
|
||||
SHPhysicsRaycastResult ColliderLinecast
|
||||
(
|
||||
EntityID eid
|
||||
, const SHVec3& start
|
||||
, const SHVec3& end
|
||||
) noexcept;
|
||||
|
||||
SHPhysicsRaycastResult ColliderLinecast
|
||||
(
|
||||
EntityID eid
|
||||
, int shapeIndex
|
||||
, const SHVec3& start
|
||||
, const SHVec3& end
|
||||
) noexcept;
|
||||
|
||||
rp3d::decimal notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo) override;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
rp3d::PhysicsWorld* world;
|
||||
SHPhysicsObjectManager* objectManager; // For
|
||||
SHPhysicsRaycastResult temp; // Holds the temporary result after casting into the world
|
||||
RaycastPairs raycasts; // Used for debug drawing
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject* validateColliderRaycast (EntityID eid) noexcept;
|
||||
static int findColliderIndex (const rp3d::CollisionBody* rp3dBody, rp3d::Entity rp3dColliderEID) noexcept;
|
||||
};
|
||||
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,120 @@
|
|||
/****************************************************************************************
|
||||
* \file SHBoxCollisionShape.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Box Collision Shape.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHBox.h"
|
||||
|
||||
// Project Headers
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHBox::SHBox() noexcept
|
||||
: SHCollisionShape (Type::BOX)
|
||||
, relativeExtents { SHVec3::One }
|
||||
, scale { SHVec3::One }
|
||||
{
|
||||
if (rp3dCollider)
|
||||
dynamic_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape())->setHalfExtents(SHVec3::One * 0.5f);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Operator Overload Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHVec3 SHBox::GetWorldExtents() const noexcept
|
||||
{
|
||||
if (rp3dCollider)
|
||||
return SHVec3{ dynamic_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape())->getHalfExtents() };
|
||||
|
||||
return relativeExtents * scale * 0.5f;
|
||||
}
|
||||
|
||||
SHVec3 SHBox::GetRelativeExtents() const noexcept
|
||||
{
|
||||
return relativeExtents;
|
||||
}
|
||||
|
||||
SHVec3 SHBox::GetWorldCentroid() const noexcept
|
||||
{
|
||||
const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset);
|
||||
const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position);
|
||||
return SHVec3::Transform(positionOffset, TRS);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHBox::SetWorldExtents(const SHVec3& newWorldExtents) noexcept
|
||||
{
|
||||
if (rp3dCollider)
|
||||
dynamic_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape())->setHalfExtents(newWorldExtents);
|
||||
|
||||
// Recompute Relative radius
|
||||
relativeExtents = 2.0f * newWorldExtents / scale;
|
||||
}
|
||||
|
||||
void SHBox::SetRelativeExtents(const SHVec3& newRelativeExtents) noexcept
|
||||
{
|
||||
relativeExtents = newRelativeExtents;
|
||||
|
||||
// Recompute world radius
|
||||
if (rp3dCollider)
|
||||
dynamic_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape())->setHalfExtents(relativeExtents * scale * 0.5f);
|
||||
}
|
||||
|
||||
void SHBox::SetScale(const SHVec3& newScale) noexcept
|
||||
{
|
||||
scale = SHVec3::Abs(newScale);
|
||||
|
||||
// Recompute world radius
|
||||
if (rp3dCollider)
|
||||
dynamic_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape())->setHalfExtents(relativeExtents * scale * 0.5f);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Member Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHBox::Update() noexcept
|
||||
{
|
||||
const SHTransform& PARENT_TRANSFORM = collider->GetTransform();
|
||||
SetScale(PARENT_TRANSFORM.scale);
|
||||
|
||||
SHCollisionShape::Update();
|
||||
}
|
||||
|
||||
|
||||
SHMatrix SHBox::GetTRS() const noexcept
|
||||
{
|
||||
const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset);
|
||||
const SHVec3 SCALE = GetWorldExtents() * 2.0f;
|
||||
|
||||
const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position);
|
||||
const SHVec3 POSITION = SHVec3::Transform(positionOffset, TRS);
|
||||
|
||||
return SHMatrix::Transform(POSITION, ROTATION, SCALE);
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************************
|
||||
* \file SHShape.h
|
||||
* \file SHBox.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a shape.
|
||||
* \brief Interface for a Box Collision Shape.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
|
@ -11,9 +11,7 @@
|
|||
#pragma once
|
||||
|
||||
// Project Headers
|
||||
#include "SH_API.h"
|
||||
#include "Math/SHRay.h"
|
||||
|
||||
#include "SHCollisionShape.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -21,62 +19,61 @@ namespace SHADE
|
|||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHShape
|
||||
/**
|
||||
* @brief
|
||||
* Encapsulate a Box Shape used for Physics Simulations.
|
||||
*/
|
||||
class SH_API SHBox final : public SHCollisionShape
|
||||
{
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Friends */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHColliderComponent;
|
||||
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
enum class Type
|
||||
{
|
||||
BOX
|
||||
, SPHERE
|
||||
, CAPSULE
|
||||
, CONVEX_HULL
|
||||
|
||||
, COUNT
|
||||
, NONE = -1
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
bool isIntersecting;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
virtual ~SHShape () = default;
|
||||
SHBox () noexcept;
|
||||
~SHBox () override = default;
|
||||
|
||||
SHShape (const SHShape&) = default;
|
||||
SHShape (SHShape&&) = default;
|
||||
|
||||
SHShape& operator=(const SHShape&) = default;
|
||||
SHShape& operator=(SHShape&&) = default;
|
||||
|
||||
SHShape();
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] Type GetType () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetWorldExtents () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetRelativeExtents () const noexcept;
|
||||
|
||||
[[nodiscard]] SHVec3 GetWorldCentroid () const noexcept override;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetWorldExtents (const SHVec3& newWorldExtents) noexcept;
|
||||
void SetRelativeExtents (const SHVec3& newRelativeExtents) noexcept;
|
||||
void SetScale (const SHVec3& newScale) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] virtual bool TestPoint (const SHVec3& point) const noexcept = 0;
|
||||
[[nodiscard]] virtual SHRaycastResult Raycast (const SHRay& ray) const noexcept = 0;
|
||||
void Update () noexcept override;
|
||||
[[nodiscard]] SHMatrix GetTRS () const noexcept override;
|
||||
|
||||
protected:
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
Type type;
|
||||
SHVec3 relativeExtents;
|
||||
SHVec3 scale;
|
||||
};
|
||||
} // namespace SHADE
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,232 @@
|
|||
/****************************************************************************************
|
||||
* \file SHCollider.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Collider.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHCollisionShape.h"
|
||||
|
||||
// Project Headers
|
||||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
|
||||
#include "Reflection/SHReflectionMetadata.h"
|
||||
#include "Tools/Utilities/SHUtilities.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHCollisionShape::SHCollisionShape(Type colliderType)
|
||||
: rp3dCollider { nullptr }
|
||||
, collider { nullptr }
|
||||
, collisionTag { SHCollisionTagMatrix::GetTag(0) }
|
||||
, flags { 0 }
|
||||
{
|
||||
flags |= 1U << SHUtilities::ConvertEnum(colliderType);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
float SHCollisionShape::GetFriction() const noexcept
|
||||
{
|
||||
return material.GetFriction();
|
||||
}
|
||||
|
||||
float SHCollisionShape::GetBounciness() const noexcept
|
||||
{
|
||||
return material.GetBounciness();
|
||||
}
|
||||
|
||||
float SHCollisionShape::GetDensity() const noexcept
|
||||
{
|
||||
return material.GetDensity();
|
||||
}
|
||||
|
||||
const SHPhysicsMaterial& SHCollisionShape::GetMaterial() const noexcept
|
||||
{
|
||||
return material;
|
||||
}
|
||||
|
||||
const SHVec3& SHCollisionShape::GetPositionOffset() const noexcept
|
||||
{
|
||||
return positionOffset;
|
||||
}
|
||||
|
||||
const SHVec3& SHCollisionShape::GetRotationOffset() const noexcept
|
||||
{
|
||||
return rotationOffset;
|
||||
}
|
||||
|
||||
SHCollisionShape::Type SHCollisionShape::GetType() const noexcept
|
||||
{
|
||||
for (int i = 0; i < SHUtilities::ConvertEnum(Type::COUNT); ++i)
|
||||
{
|
||||
const uint8_t FLAG_VALUE = 1U << SHUtilities::ConvertEnum(static_cast<Type>(i));
|
||||
|
||||
if (flags & FLAG_VALUE)
|
||||
return static_cast<Type>(i);
|
||||
}
|
||||
|
||||
return Type::INVALID;
|
||||
}
|
||||
|
||||
bool SHCollisionShape::IsTrigger() const noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 3;
|
||||
static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS;
|
||||
|
||||
return flags & FLAG_VALUE;
|
||||
}
|
||||
|
||||
bool SHCollisionShape::IsColliding() const noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 4;
|
||||
static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS;
|
||||
|
||||
return flags & FLAG_VALUE;
|
||||
}
|
||||
|
||||
const SHCollisionTag& SHCollisionShape::GetCollisionTag() const noexcept
|
||||
{
|
||||
return *collisionTag;
|
||||
}
|
||||
|
||||
SHVec3 SHCollisionShape::GetWorldCentroid() const noexcept
|
||||
{
|
||||
return collider->GetTransform().position;
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept
|
||||
{
|
||||
collisionTag = newCollisionTag;
|
||||
|
||||
if (rp3dCollider)
|
||||
rp3dCollider->setCollideWithMaskBits(collisionTag->GetMask());
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetFriction(float friction) noexcept
|
||||
{
|
||||
material.SetFriction(friction);
|
||||
|
||||
if (rp3dCollider)
|
||||
rp3dCollider->getMaterial().setFrictionCoefficient(material.GetFriction());
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetBounciness(float bounciness) noexcept
|
||||
{
|
||||
material.SetBounciness(bounciness);
|
||||
|
||||
if (rp3dCollider)
|
||||
rp3dCollider->getMaterial().setBounciness(material.GetBounciness());
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetDensity(float density) noexcept
|
||||
{
|
||||
material.SetDensity(density);
|
||||
|
||||
if (rp3dCollider)
|
||||
rp3dCollider->getMaterial().setMassDensity(material.GetDensity());
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept
|
||||
{
|
||||
material = newMaterial;
|
||||
|
||||
if (rp3dCollider)
|
||||
{
|
||||
auto& rp3dMaterial = rp3dCollider->getMaterial();
|
||||
rp3dMaterial.setFrictionCoefficient(material.GetFriction());
|
||||
rp3dMaterial.setBounciness(material.GetBounciness());
|
||||
rp3dMaterial.setMassDensity(material.GetDensity());
|
||||
}
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept
|
||||
{
|
||||
positionOffset = posOffset;
|
||||
Update();
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetRotationOffset(const SHVec3& rotOffset) noexcept
|
||||
{
|
||||
rotationOffset = rotOffset;
|
||||
Update();
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetIsTrigger(bool isTrigger) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 3;
|
||||
static constexpr uint8_t FLAG_VALUE = 1U << FLAG_POS;
|
||||
|
||||
isTrigger ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE;
|
||||
|
||||
if (rp3dCollider)
|
||||
rp3dCollider->setIsTrigger(isTrigger);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Member Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHCollisionShape::UpdateCollisionTags() noexcept
|
||||
{
|
||||
if (collisionTag->IsDirty())
|
||||
rp3dCollider->setCollideWithMaskBits(collisionTag->GetMask());
|
||||
}
|
||||
|
||||
|
||||
void SHCollisionShape::Update() noexcept
|
||||
{
|
||||
if (rp3dCollider)
|
||||
{
|
||||
const rp3d::Transform OFFSETS{ positionOffset, SHQuaternion::FromEuler(rotationOffset) };
|
||||
rp3dCollider->setLocalToBodyTransform(OFFSETS);
|
||||
}
|
||||
}
|
||||
|
||||
SHMatrix SHCollisionShape::GetTRS() const noexcept
|
||||
{
|
||||
return SHMatrix::Identity;
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
||||
|
||||
RTTR_REGISTRATION
|
||||
{
|
||||
using namespace SHADE;
|
||||
using namespace rttr;
|
||||
|
||||
registration::enumeration<SHCollisionShape::Type>("Collider Type")
|
||||
(
|
||||
value("Box", SHCollisionShape::Type::BOX),
|
||||
value("Sphere", SHCollisionShape::Type::SPHERE)
|
||||
// TODO(Diren): Add More Shapes
|
||||
);
|
||||
|
||||
registration::class_<SHCollisionShape>("Collider")
|
||||
.property("IsTrigger" , &SHCollisionShape::IsTrigger , &SHCollisionShape::SetIsTrigger )
|
||||
.property("Friction" , &SHCollisionShape::GetFriction , &SHCollisionShape::SetFriction )
|
||||
.property("Bounciness" , &SHCollisionShape::GetBounciness , &SHCollisionShape::SetBounciness )
|
||||
.property("Density" , &SHCollisionShape::GetDensity , &SHCollisionShape::SetDensity )
|
||||
.property("Position Offset" , &SHCollisionShape::GetPositionOffset, &SHCollisionShape::SetPositionOffset)
|
||||
.property("Rotation Offset" , &SHCollisionShape::GetRotationOffset, &SHCollisionShape::SetRotationOffset) (metadata(META::angleInRad, true));
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/****************************************************************************************
|
||||
* \file SHCollisionShape.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a Base CollisionShape Class.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rttr/registration>
|
||||
#include <reactphysics3d/collision/Collider.h>
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Entity/SHEntity.h"
|
||||
#include "Physics/Collision/CollisionTags/SHCollisionTags.h"
|
||||
#include "Physics/Collision/SHPhysicsMaterial.h"
|
||||
#include "Math/Transform/SHTransform.h"
|
||||
#include "Physics/Collision/SHPhysicsRaycastResult.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SHColliderComponent;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHCollisionShape
|
||||
{
|
||||
private:
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Friends */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHPhysicsSystem;
|
||||
friend class SHPhysicsObjectManager;
|
||||
friend class SHColliderComponent;
|
||||
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
enum class Type
|
||||
{
|
||||
SPHERE
|
||||
, BOX
|
||||
|
||||
, COUNT
|
||||
, INVALID = -1
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHCollisionShape(Type colliderType = Type::INVALID);
|
||||
|
||||
SHCollisionShape(const SHCollisionShape& rhs) noexcept = default;
|
||||
SHCollisionShape(SHCollisionShape&& rhs) noexcept = default;
|
||||
virtual ~SHCollisionShape() noexcept = default;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHCollisionShape& operator=(const SHCollisionShape& rhs) noexcept = default;
|
||||
SHCollisionShape& operator=(SHCollisionShape&& rhs) noexcept = default;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
// Material Properties
|
||||
// TODO: Remove individual setters once instanced materials are supported
|
||||
|
||||
[[nodiscard]] float GetFriction() const noexcept;
|
||||
[[nodiscard]] float GetBounciness() const noexcept;
|
||||
[[nodiscard]] float GetDensity() const noexcept;
|
||||
[[nodiscard]] const SHPhysicsMaterial& GetMaterial() const noexcept;
|
||||
|
||||
// Offsets
|
||||
|
||||
[[nodiscard]] const SHVec3& GetPositionOffset() const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetRotationOffset() const noexcept;
|
||||
|
||||
// Flags
|
||||
|
||||
[[nodiscard]] Type GetType() const noexcept;
|
||||
[[nodiscard]] bool IsTrigger() const noexcept;
|
||||
[[nodiscard]] bool IsColliding() const noexcept;
|
||||
|
||||
[[nodiscard]] const SHCollisionTag& GetCollisionTag() const noexcept;
|
||||
|
||||
[[nodiscard]] virtual SHVec3 GetWorldCentroid() const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept;
|
||||
|
||||
void SetFriction(float friction) noexcept;
|
||||
void SetBounciness(float bounciness) noexcept;
|
||||
void SetDensity(float density) noexcept;
|
||||
void SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept;
|
||||
|
||||
void SetPositionOffset(const SHVec3& posOffset) noexcept;
|
||||
void SetRotationOffset(const SHVec3& rotOffset) noexcept;
|
||||
|
||||
// Forces rigidbody to recompute mass if one exists
|
||||
void SetIsTrigger(bool isTrigger) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Member Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Re-sets the collision tags if it is dirty.
|
||||
*/
|
||||
void UpdateCollisionTags() noexcept;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Computes the transform of the shape.
|
||||
*/
|
||||
virtual void Update() noexcept;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Computes the TRS matrix for rendering the shape.
|
||||
* @return
|
||||
* The model-to-world matrix for rendering the shape.
|
||||
*/
|
||||
[[nodiscard]] virtual SHMatrix GetTRS() const noexcept;
|
||||
|
||||
protected:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
reactphysics3d::Collider* rp3dCollider;
|
||||
SHColliderComponent* collider; // The collider it belongs to.
|
||||
SHCollisionTag* collisionTag;
|
||||
SHPhysicsMaterial material; // TODO: Change to pointer once instancing is supported
|
||||
|
||||
SHVec3 positionOffset;
|
||||
SHVec3 rotationOffset;
|
||||
|
||||
uint8_t flags; // 0 0 0 trigger 0 capsule sphere box
|
||||
|
||||
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/****************************************************************************************
|
||||
* \file SHSphereCollisionShape.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Sphere Collision Shape.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHSphere.h"
|
||||
|
||||
// Project Headers
|
||||
#include "Math/SHMathHelpers.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHSphere::SHSphere() noexcept
|
||||
: SHCollisionShape (Type::SPHERE)
|
||||
, relativeRadius { 1.0f }
|
||||
, scale { 1.0f }
|
||||
{
|
||||
if (rp3dCollider)
|
||||
dynamic_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape())->setRadius(0.5f);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Operator Overload Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
float SHSphere::GetWorldRadius() const noexcept
|
||||
{
|
||||
if (rp3dCollider)
|
||||
return dynamic_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape())->getRadius();
|
||||
|
||||
return relativeRadius * scale * 0.5f;
|
||||
}
|
||||
|
||||
float SHSphere::GetRelativeRadius() const noexcept
|
||||
{
|
||||
return relativeRadius;
|
||||
}
|
||||
|
||||
SHVec3 SHSphere::GetWorldCentroid() const noexcept
|
||||
{
|
||||
const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset);
|
||||
const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position);
|
||||
return SHVec3::Transform(positionOffset, TRS);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHSphere::SetWorldRadius(float newWorldRadius) noexcept
|
||||
{
|
||||
if (rp3dCollider)
|
||||
dynamic_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape())->setRadius(newWorldRadius);
|
||||
|
||||
// Recompute Relative radius
|
||||
relativeRadius = 2.0f * newWorldRadius / scale;
|
||||
}
|
||||
|
||||
void SHSphere::SetRelativeRadius(float newRelativeRadius) noexcept
|
||||
{
|
||||
relativeRadius = newRelativeRadius;
|
||||
|
||||
// Recompute world radius
|
||||
if (rp3dCollider)
|
||||
dynamic_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape())->setRadius(relativeRadius * scale * 0.5f);
|
||||
}
|
||||
|
||||
void SHSphere::SetScale(float maxScale) noexcept
|
||||
{
|
||||
scale = std::fabs(maxScale);
|
||||
|
||||
// Recompute world radius
|
||||
if (rp3dCollider)
|
||||
dynamic_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape())->setRadius(relativeRadius * scale * 0.5f);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Member Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHSphere::Update() noexcept
|
||||
{
|
||||
const SHTransform& PARENT_TRANSFORM = collider->GetTransform();
|
||||
|
||||
const float SPHERE_SCALE = std::fabs(SHMath::Max({ PARENT_TRANSFORM.scale.x, PARENT_TRANSFORM.scale.y, PARENT_TRANSFORM.scale.z }));
|
||||
SetScale(SPHERE_SCALE);
|
||||
|
||||
SHCollisionShape::Update();
|
||||
}
|
||||
|
||||
|
||||
SHMatrix SHSphere::GetTRS() const noexcept
|
||||
{
|
||||
const SHQuaternion ROTATION = collider->GetTransform().orientation * SHQuaternion::FromEuler(rotationOffset);
|
||||
const SHVec3 SCALE = GetWorldRadius();
|
||||
|
||||
const SHMatrix TRS = SHMatrix::Rotate(ROTATION) * SHMatrix::Translate(collider->GetTransform().position);
|
||||
const SHVec3 POSITION = SHVec3::Transform(positionOffset, TRS);
|
||||
|
||||
return SHMatrix::Transform(POSITION, ROTATION, SCALE);
|
||||
}
|
||||
} // namespace SHADE
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************************
|
||||
* \file SHBoundingSphere.h
|
||||
* \file SHSphereCollisionShape.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a Bounding Sphere.
|
||||
* \brief Interface for a Sphere Collision Shape.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
|
@ -10,11 +10,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <DirectXCollision.h>
|
||||
|
||||
// Project Headers
|
||||
#include "SHShape.h"
|
||||
#include "SH_API.h"
|
||||
#include "SHCollisionShape.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -22,71 +19,61 @@ namespace SHADE
|
|||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHSphere : public SHShape,
|
||||
private DirectX::BoundingSphere
|
||||
/**
|
||||
* @brief
|
||||
* Encapsulate a Sphere Shape used for Physics Simulations.
|
||||
*/
|
||||
class SH_API SHSphere final : public SHCollisionShape
|
||||
{
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Friends */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHColliderComponent;
|
||||
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHSphere () noexcept;
|
||||
SHSphere (const SHVec3& center, float radius) noexcept;
|
||||
SHSphere (const SHSphere& rhs) noexcept;
|
||||
SHSphere (SHSphere&& rhs) noexcept;
|
||||
|
||||
SHSphere () noexcept;
|
||||
~SHSphere () override = default;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHSphere& operator= (const SHSphere& rhs) noexcept;
|
||||
SHSphere& operator= (SHSphere&& rhs) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] SHVec3 GetCenter () const noexcept;
|
||||
[[nodiscard]] float GetWorldRadius () const noexcept;
|
||||
[[nodiscard]] float GetRelativeRadius () const noexcept;
|
||||
|
||||
[[nodiscard]] SHVec3 GetWorldCentroid () const noexcept override;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetCenter (const SHVec3& center) noexcept;
|
||||
void SetWorldRadius (float newWorldRadius) noexcept;
|
||||
void SetRelativeRadius (float newRelativeRadius) noexcept;
|
||||
void SetScale (float maxScale) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] bool TestPoint (const SHVec3& point) const noexcept override;
|
||||
[[nodiscard]] SHRaycastResult Raycast(const SHRay& ray) const noexcept override;
|
||||
|
||||
[[nodiscard]] bool Contains (const SHSphere& rhs) const noexcept;
|
||||
[[nodiscard]] float Volume () const noexcept;
|
||||
[[nodiscard]] float SurfaceArea () const noexcept;
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Static Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] static SHSphere Combine (const SHSphere& lhs, const SHSphere& rhs) noexcept;
|
||||
[[nodiscard]] static bool Intersect (const SHSphere& lhs, const SHSphere& rhs) noexcept;
|
||||
[[nodiscard]] static SHSphere BuildFromSpheres (const SHSphere* spheres, size_t numSpheres) noexcept;
|
||||
[[nodiscard]] static SHSphere BuildFromVertices (const SHVec3* vertices, size_t numVertices, size_t stride = 0) noexcept;
|
||||
void Update () noexcept override;
|
||||
[[nodiscard]] SHMatrix GetTRS () const noexcept override;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
float RelativeRadius;
|
||||
|
||||
float relativeRadius;
|
||||
float scale;
|
||||
};
|
||||
} // namespace SHADE
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************************
|
||||
* \file SHShape.cpp
|
||||
* \file SHPhysicsObject.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a shape.
|
||||
* \brief Implementation for a Physics Object.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
|
@ -11,25 +11,25 @@
|
|||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHShape.h"
|
||||
#include "SHPhysicsObject.h"
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/* Constructor & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHShape::SHShape()
|
||||
: type { Type::NONE }
|
||||
SHPhysicsObject::SHPhysicsObject(EntityID eid) noexcept
|
||||
: entityID { eid }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHShape::Type SHShape::GetType() const noexcept
|
||||
SHPhysicsObject::~SHPhysicsObject() noexcept
|
||||
{
|
||||
return type;
|
||||
entityID = MAX_EID;
|
||||
body = nullptr;
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,48 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsObject.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a Physics Object.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Entity/SHEntity.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Encapsulates a rigid body and a collider tied to an Entity.
|
||||
*/
|
||||
struct SH_API SHPhysicsObject
|
||||
{
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
// We use a rigid body all the time. Colliders without rigid bodies have a static body.
|
||||
|
||||
EntityID entityID = MAX_EID;
|
||||
rp3d::RigidBody* body = nullptr;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject (EntityID eid) noexcept;
|
||||
~SHPhysicsObject () noexcept;
|
||||
|
||||
};
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,429 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsObjectManager.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Physics Object Manager.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHPhysicsObjectManager.h"
|
||||
|
||||
// Project Headers
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
|
||||
#include "Physics/Collision/Shapes/SHSphere.h"
|
||||
#include "Physics/Collision/Shapes/SHBox.h"
|
||||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||
#include "Tools/Utilities/SHUtilities.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObjectManager::SHPhysicsObjectManager() noexcept
|
||||
: factory { nullptr }
|
||||
, physicsWorld { nullptr }
|
||||
{}
|
||||
|
||||
|
||||
|
||||
SHPhysicsObjectManager::~SHPhysicsObjectManager() noexcept
|
||||
{
|
||||
RemoveAllObjects();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObjectManager::EntityObjectMap& SHPhysicsObjectManager::GetPhysicsObjects() noexcept
|
||||
{
|
||||
return physicsObjects;
|
||||
}
|
||||
|
||||
const SHPhysicsObject* SHPhysicsObjectManager::GetPhysicsObject(EntityID entityID) noexcept
|
||||
{
|
||||
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
|
||||
if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end())
|
||||
{
|
||||
SHLOG_ERROR("Cannot find physics object for entity {}!", entityID)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &PHYSICS_OBJECT_ITERATOR->second;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsObjectManager::SetFactory(rp3d::PhysicsCommon* physicsFactory) noexcept
|
||||
{
|
||||
factory = physicsFactory;
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::SetPhysicsWorld(rp3d::PhysicsWorld* world) noexcept
|
||||
{
|
||||
physicsWorld = world;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Member Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsObjectManager::AddRigidBody(EntityID entityID) noexcept
|
||||
{
|
||||
SHASSERT(physicsWorld, "Physics World Missing ffrom Physics Object Manager!")
|
||||
|
||||
SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID);
|
||||
|
||||
// Get the rigidbody and transform components
|
||||
auto* rigidBodyComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID);
|
||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
||||
|
||||
|
||||
|
||||
if (!physicsObject->body)
|
||||
{
|
||||
if (!transformComponent)
|
||||
{
|
||||
SHLOG_ERROR("Unable to create a rigid body for Entity {} with missing transform!", entityID)
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a new rigidbody in the physics object
|
||||
const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() };
|
||||
physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM);
|
||||
}
|
||||
|
||||
// Link with the component
|
||||
rigidBodyComponent->SetRigidBody(physicsObject->body);
|
||||
|
||||
// Reset the type
|
||||
const auto RIGID_BODY_TYPE = rigidBodyComponent->GetType();
|
||||
switch (RIGID_BODY_TYPE)
|
||||
{
|
||||
case SHRigidBodyComponent::Type::STATIC:
|
||||
physicsObject->body->setType(rp3d::BodyType::STATIC);
|
||||
break;
|
||||
case SHRigidBodyComponent::Type::KINEMATIC:
|
||||
physicsObject->body->setType(rp3d::BodyType::KINEMATIC);
|
||||
break;
|
||||
case SHRigidBodyComponent::Type::DYNAMIC:
|
||||
physicsObject->body->setType(rp3d::BodyType::DYNAMIC);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::RemoveRigidBody(EntityID entityID) noexcept
|
||||
{
|
||||
SHASSERT(physicsWorld, "Physics World Missing from Physics Object Manager!")
|
||||
|
||||
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
|
||||
if (PHYSICS_OBJECT_ITERATOR == physicsObjects.end())
|
||||
return;
|
||||
|
||||
SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
|
||||
|
||||
// If a collider component exists, we just set the body to static
|
||||
if (SHComponentManager::GetComponent_s<SHColliderComponent>(entityID))
|
||||
physicsObject->body->setType(rp3d::BodyType::STATIC);
|
||||
else
|
||||
{
|
||||
physicsWorld->destroyRigidBody(physicsObject->body);
|
||||
destroyPhysicsObject(entityID);
|
||||
}
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::AddCollider(EntityID entityID) noexcept
|
||||
{
|
||||
SHASSERT(physicsWorld, "Physics World Missing from Physics Object Manager!")
|
||||
|
||||
SHPhysicsObject* physicsObject = ensurePhysicsObject(entityID);
|
||||
|
||||
// Get the collider & transform component
|
||||
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
||||
|
||||
// Check if a body already exists. If it does, link it with the component
|
||||
if (!physicsObject->body)
|
||||
{
|
||||
if (!transformComponent)
|
||||
{
|
||||
SHLOG_ERROR("Unable to create a collider for Entity {} with missing transform!", entityID)
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a static body
|
||||
const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() };
|
||||
physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM);
|
||||
physicsObject->body->setType(rp3d::BodyType::STATIC);
|
||||
}
|
||||
|
||||
// Link with component
|
||||
colliderComponent->SetFactory(factory);
|
||||
colliderComponent->SetCollisionBody(physicsObject->body);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::RemoveCollider(EntityID entityID) noexcept
|
||||
{
|
||||
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
|
||||
if (PHYSICS_OBJECT_ITERATOR != physicsObjects.end())
|
||||
{
|
||||
SHPhysicsObject* physicsObject = &PHYSICS_OBJECT_ITERATOR->second;
|
||||
|
||||
// Remove all collision shapes from the body
|
||||
int32_t numShapes = static_cast<int32_t>(physicsObject->body->getNbColliders());
|
||||
while (--numShapes >= 0)
|
||||
{
|
||||
auto* rp3dCollider = physicsObject->body->getCollider(numShapes);
|
||||
physicsObject->body->removeCollider(rp3dCollider);
|
||||
}
|
||||
|
||||
// Destroy if no rigidbody component
|
||||
if (!SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID))
|
||||
destroyPhysicsObject(entityID);
|
||||
}
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::RemoveAllObjects() noexcept
|
||||
{
|
||||
// Physics objects itself will delete the object
|
||||
physicsObjects.clear();
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::AddRigidBodyDef(EntityID entityID) noexcept
|
||||
{
|
||||
auto* rigidBody = SHComponentManager::GetComponent<SHRigidBodyComponent>(entityID);
|
||||
|
||||
const SHRigidBodyDef RIGID_BODY_DEF
|
||||
{
|
||||
.entityID = rigidBody->GetEID()
|
||||
, .bodyType = rigidBody->type
|
||||
, .interpolate = rigidBody->interpolate
|
||||
, .drag = rigidBody->drag
|
||||
, .angularDrag = rigidBody->angularDrag
|
||||
};
|
||||
|
||||
rigidBodyQueue.push(RIGID_BODY_DEF);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::AddColliderDef(EntityID entityID) noexcept
|
||||
{
|
||||
auto* collider = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
||||
|
||||
SHColliderDef colliderDef
|
||||
{
|
||||
.entityID = collider->GetEID()
|
||||
};
|
||||
|
||||
for (const auto* shape : collider->shapes)
|
||||
{
|
||||
SHColliderDef::ShapeDef shapeDef
|
||||
{
|
||||
.type = shape->GetType()
|
||||
, .posOffset = shape->GetPositionOffset()
|
||||
, .rotOffset = shape->GetRotationOffset()
|
||||
};
|
||||
|
||||
switch (shape->GetType())
|
||||
{
|
||||
case SHCollisionShape::Type::SPHERE:
|
||||
shapeDef.size.x = dynamic_cast<const SHSphere*>(shape)->GetWorldRadius();
|
||||
break;
|
||||
case SHCollisionShape::Type::BOX:
|
||||
shapeDef.size = dynamic_cast<const SHBox*>(shape)->GetWorldExtents();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
colliderDef.shapes.emplace_back(shapeDef);
|
||||
}
|
||||
|
||||
colliderQueue.push(colliderDef);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::FlushDefinitions() noexcept
|
||||
{
|
||||
SHASSERT(physicsWorld, "Physics World Missing ffrom Physics Object Manager!")
|
||||
|
||||
// Flush all rigid bodies
|
||||
while (!rigidBodyQueue.empty())
|
||||
{
|
||||
const SHRigidBodyDef& DEF = rigidBodyQueue.front();
|
||||
|
||||
SHPhysicsObject* physicsObject = ensurePhysicsObject(DEF.entityID);
|
||||
|
||||
// Get transform component
|
||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(DEF.entityID);
|
||||
if (!transformComponent)
|
||||
{
|
||||
SHLOG_ERROR("Unable to create a rigid body for Entity {} with missing transform!", DEF.entityID)
|
||||
|
||||
rigidBodyQueue.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create a new rigidbody in the physics object
|
||||
const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() };
|
||||
physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM);
|
||||
|
||||
// Get rigidBody component
|
||||
auto* rigidBodyComponent = SHComponentManager::GetComponent<SHRigidBodyComponent>(DEF.entityID);
|
||||
rigidBodyComponent->SetRigidBody(physicsObject->body);
|
||||
|
||||
// Set type
|
||||
rigidBodyComponent->type = DEF.bodyType;
|
||||
switch (DEF.bodyType)
|
||||
{
|
||||
case SHRigidBodyComponent::Type::STATIC:
|
||||
physicsObject->body->setType(rp3d::BodyType::STATIC);
|
||||
break;
|
||||
case SHRigidBodyComponent::Type::KINEMATIC:
|
||||
physicsObject->body->setType(rp3d::BodyType::KINEMATIC);
|
||||
break;
|
||||
case SHRigidBodyComponent::Type::DYNAMIC:
|
||||
physicsObject->body->setType(rp3d::BodyType::DYNAMIC);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Re-set properties
|
||||
rigidBodyComponent->SetGravityEnabled (rigidBodyComponent->IsGravityEnabled());
|
||||
rigidBodyComponent->SetIsAllowedToSleep (rigidBodyComponent->IsAllowedToSleep());
|
||||
rigidBodyComponent->SetFreezePositionX (rigidBodyComponent->GetFreezePositionX());
|
||||
rigidBodyComponent->SetFreezePositionY (rigidBodyComponent->GetFreezePositionY());
|
||||
rigidBodyComponent->SetFreezePositionZ (rigidBodyComponent->GetFreezePositionZ());
|
||||
rigidBodyComponent->SetFreezeRotationX (rigidBodyComponent->GetFreezeRotationX());
|
||||
rigidBodyComponent->SetFreezeRotationY (rigidBodyComponent->GetFreezeRotationY());
|
||||
rigidBodyComponent->SetFreezeRotationZ (rigidBodyComponent->GetFreezeRotationZ());
|
||||
|
||||
rigidBodyComponent->SetInterpolate (DEF.interpolate);
|
||||
rigidBodyComponent->SetDrag (DEF.drag);
|
||||
rigidBodyComponent->SetAngularDrag (DEF.angularDrag);
|
||||
|
||||
rigidBodyQueue.pop();
|
||||
}
|
||||
|
||||
// Flush all colliders
|
||||
while (!colliderQueue.empty())
|
||||
{
|
||||
const SHColliderDef& DEF = colliderQueue.front();
|
||||
|
||||
SHPhysicsObject* physicsObject = ensurePhysicsObject(DEF.entityID);
|
||||
|
||||
// Get transform component
|
||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(DEF.entityID);
|
||||
if (!transformComponent)
|
||||
{
|
||||
SHLOG_ERROR("Unable to create a collider for Entity {} with missing transform!", DEF.entityID)
|
||||
|
||||
colliderQueue.pop();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!physicsObject->body)
|
||||
{
|
||||
// Create a static body
|
||||
const rp3d::Transform RP3D_TRANSFORM{ transformComponent->GetWorldPosition(), transformComponent->GetWorldOrientation() };
|
||||
physicsObject->body = physicsWorld->createRigidBody(RP3D_TRANSFORM);
|
||||
physicsObject->body->setType(rp3d::BodyType::STATIC);
|
||||
}
|
||||
|
||||
// Get rigidBody component
|
||||
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(DEF.entityID);
|
||||
|
||||
colliderComponent->SetFactory(factory);
|
||||
colliderComponent->SetCollisionBody(physicsObject->body);
|
||||
|
||||
// Add all shapes
|
||||
for (size_t i = 0; i < colliderComponent->shapes.size(); ++i)
|
||||
{
|
||||
// Get the currrent shape
|
||||
auto& collisionShape = colliderComponent->shapes[i];
|
||||
|
||||
// Add the rp3d collider to the shade collision shape
|
||||
switch (collisionShape->GetType())
|
||||
{
|
||||
case SHCollisionShape::Type::SPHERE:
|
||||
{
|
||||
auto* sphereShape = dynamic_cast<SHSphere*>(collisionShape);
|
||||
|
||||
const float SPHERE_SCALE = std::fabs(SHMath::Max({ colliderComponent->transform.scale.x, colliderComponent->transform.scale.y, colliderComponent->transform.scale.z }));
|
||||
|
||||
rp3d::SphereShape* rp3dSphere = factory->createSphereShape(sphereShape->GetRelativeRadius() * SPHERE_SCALE * 0.5f);
|
||||
|
||||
const rp3d::Transform OFFSETS{ sphereShape->GetPositionOffset(), SHQuaternion::FromEuler(sphereShape->GetRotationOffset()) };
|
||||
sphereShape->rp3dCollider = physicsObject->body->addCollider(rp3dSphere, OFFSETS);
|
||||
sphereShape->rp3dCollider->setIsTrigger(sphereShape->IsTrigger());
|
||||
|
||||
break;
|
||||
}
|
||||
case SHCollisionShape::Type::BOX:
|
||||
{
|
||||
auto* boxShape = dynamic_cast<SHBox*>(collisionShape);
|
||||
|
||||
rp3d::BoxShape* rp3dBox = factory->createBoxShape(boxShape->GetRelativeExtents() * colliderComponent->transform.scale * 0.5f);
|
||||
|
||||
const rp3d::Transform OFFSETS{ boxShape->GetPositionOffset(), SHQuaternion::FromEuler(boxShape->GetRotationOffset()) };
|
||||
boxShape->rp3dCollider = physicsObject->body->addCollider(rp3dBox, OFFSETS);
|
||||
boxShape->rp3dCollider->setIsTrigger(boxShape->IsTrigger());
|
||||
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
collisionShape->SetMaterial(collisionShape->GetMaterial());
|
||||
|
||||
const auto& COLLISION_TAG = collisionShape->GetCollisionTag();
|
||||
collisionShape->SetCollisionTag(SHCollisionTagMatrix::GetTag(COLLISION_TAG.GetName()));
|
||||
}
|
||||
|
||||
physicsObject->body->updateMassPropertiesFromColliders();
|
||||
|
||||
colliderQueue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Member Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject* SHPhysicsObjectManager::createPhysicsObject(EntityID entityID)
|
||||
{
|
||||
const auto& NEW_OBJECT = physicsObjects.emplace(entityID, SHPhysicsObject{entityID}).first;
|
||||
return &NEW_OBJECT->second;
|
||||
}
|
||||
|
||||
SHPhysicsObject* SHPhysicsObjectManager::ensurePhysicsObject(EntityID entityID)
|
||||
{
|
||||
const auto PHYSICS_OBJECT_ITERATOR = physicsObjects.find(entityID);
|
||||
|
||||
SHPhysicsObject* physicsObject = PHYSICS_OBJECT_ITERATOR == physicsObjects.end()
|
||||
? createPhysicsObject(entityID)
|
||||
: &PHYSICS_OBJECT_ITERATOR->second;
|
||||
|
||||
return physicsObject;
|
||||
}
|
||||
|
||||
|
||||
void SHPhysicsObjectManager::destroyPhysicsObject(EntityID entityID)
|
||||
{
|
||||
physicsObjects.erase(entityID);
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,182 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsObjectManager.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a Physics Object Manager.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
|
||||
// Project Headers
|
||||
#include "SHPhysicsObject.h"
|
||||
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Encapsulates a manager for physics objects that links raw physics components with the
|
||||
* engine's components.
|
||||
*/
|
||||
class SH_API SHPhysicsObjectManager
|
||||
{
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
using EntityObjectMap = std::unordered_map<EntityID, SHPhysicsObject>;
|
||||
|
||||
public:
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
struct SHRigidBodyDef
|
||||
{
|
||||
EntityID entityID = MAX_EID;
|
||||
SHRigidBodyComponent::Type bodyType = SHRigidBodyComponent::Type::STATIC;
|
||||
bool interpolate = true;
|
||||
float drag = 0.0f;
|
||||
float angularDrag = 0.0f;
|
||||
};
|
||||
|
||||
struct SHColliderDef
|
||||
{
|
||||
struct ShapeDef
|
||||
{
|
||||
SHCollisionShape::Type type = SHCollisionShape::Type::SPHERE;
|
||||
SHVec3 posOffset = SHVec3::Zero;
|
||||
SHVec3 rotOffset = SHVec3::Zero;
|
||||
SHVec3 size = SHVec3::Zero; // x for sphere radius, all 3 for box extents
|
||||
};
|
||||
|
||||
EntityID entityID = MAX_EID;
|
||||
std::vector<ShapeDef> shapes;
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObjectManager () noexcept;
|
||||
~SHPhysicsObjectManager () noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] EntityObjectMap& GetPhysicsObjects () noexcept;
|
||||
[[nodiscard]] const SHPhysicsObject* GetPhysicsObject (EntityID entityID) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SetFactory (rp3d::PhysicsCommon* physicsFactory) noexcept;
|
||||
void SetPhysicsWorld(rp3d::PhysicsWorld* world) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Member Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Creates a rigid body and links it with the rigid body component.
|
||||
* @param entityID
|
||||
* The entity to link the new rigid body to.
|
||||
*/
|
||||
void AddRigidBody (EntityID entityID) noexcept;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Destroys a rigid body and removes the link with the rigid body component.
|
||||
* @param entityID
|
||||
* The entity to destroy the rigid body of.
|
||||
*/
|
||||
void RemoveRigidBody (EntityID entityID) noexcept;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Creates a composite collider and links it with the collider component.
|
||||
* @param entityID
|
||||
* The entity to link the new collider to.
|
||||
*/
|
||||
void AddCollider (EntityID entityID) noexcept;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Destroys a composite collider and removes the link with the collider component.
|
||||
* @param entityID
|
||||
* The entity to destroy the collider of.
|
||||
*/
|
||||
void RemoveCollider (EntityID entityID) noexcept;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Removes all physics object in the manager. This is only meant to be called when
|
||||
* the world is being destroyed or the scene is being changed.
|
||||
*/
|
||||
void RemoveAllObjects () noexcept;
|
||||
|
||||
/**
|
||||
* @brief Adds a rigidbody definition to add to the physics world.
|
||||
* @param rigidBody
|
||||
* The rigidbody component
|
||||
*/
|
||||
void AddRigidBodyDef (EntityID entityID) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Adds a collider definition to add to the physics world.
|
||||
* @param collider
|
||||
* The collider component
|
||||
*/
|
||||
void AddColliderDef (EntityID entityID) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Adds all loaded definitions into the physics world.
|
||||
*/
|
||||
void FlushDefinitions () noexcept;
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
using RigidBodyQueue = std::queue<SHRigidBodyDef>;
|
||||
using ColliderQueue = std::queue<SHColliderDef>;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
rp3d::PhysicsCommon* factory;
|
||||
rp3d::PhysicsWorld* physicsWorld;
|
||||
EntityObjectMap physicsObjects;
|
||||
|
||||
RigidBodyQueue rigidBodyQueue;
|
||||
ColliderQueue colliderQueue;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Member Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject* createPhysicsObject (EntityID entityID);
|
||||
SHPhysicsObject* ensurePhysicsObject (EntityID entityID);
|
||||
void destroyPhysicsObject (EntityID entityID);
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace SHADE
|
|
@ -9,6 +9,7 @@
|
|||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHColliderComponent.h"
|
||||
|
@ -16,7 +17,9 @@
|
|||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Math/SHMathHelpers.h"
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
#include "Physics/SHPhysicsEvents.h"
|
||||
#include "Physics/Collision/Shapes/SHSphere.h"
|
||||
#include "Physics/Collision/Shapes/SHBox.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -25,185 +28,257 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHColliderComponent::SHColliderComponent() noexcept
|
||||
: system { nullptr }
|
||||
: flags { ACTIVE_FLAG | MOVED_FLAG }
|
||||
, factory { nullptr }
|
||||
, collisionBody { nullptr }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHColliderComponent::GetDebugDrawState() const noexcept
|
||||
{
|
||||
return flags & DRAW_FLAG;
|
||||
}
|
||||
|
||||
const SHTransform& SHColliderComponent::GetTransform() const noexcept
|
||||
{
|
||||
return transform;
|
||||
}
|
||||
|
||||
const SHVec3& SHColliderComponent::GetPosition() const noexcept
|
||||
{
|
||||
return position;
|
||||
return transform.position;
|
||||
}
|
||||
|
||||
const SHQuaternion& SHColliderComponent::GetOrientation() const noexcept
|
||||
{
|
||||
return orientation;
|
||||
}
|
||||
|
||||
SHVec3 SHColliderComponent::GetRotation() const noexcept
|
||||
{
|
||||
return orientation.ToEuler();
|
||||
return transform.orientation;
|
||||
}
|
||||
|
||||
const SHVec3& SHColliderComponent::GetScale() const noexcept
|
||||
{
|
||||
return scale;
|
||||
return transform.scale;
|
||||
}
|
||||
|
||||
const SHColliderComponent::CollisionShapes& SHColliderComponent::GetCollisionShapes() const noexcept
|
||||
{
|
||||
return collisionShapes;
|
||||
return shapes;
|
||||
}
|
||||
|
||||
SHCollisionShape& SHColliderComponent::GetCollisionShape(int index)
|
||||
{
|
||||
if (index < 0 || static_cast<size_t>(index) >= collisionShapes.size())
|
||||
throw std::invalid_argument("Out-of-range access!");
|
||||
const int NUM_SHAPES = static_cast<int>(shapes.size());
|
||||
|
||||
return collisionShapes[index];
|
||||
if (index < 0 || index >= NUM_SHAPES)
|
||||
throw std::invalid_argument("Out-of-range index!");
|
||||
|
||||
return *shapes[index];
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHColliderComponent::SetDebugDrawState(bool state) noexcept
|
||||
{
|
||||
state ? flags |= DRAW_FLAG : flags &= ~(DRAW_FLAG);
|
||||
|
||||
#ifdef SHEDITOR
|
||||
|
||||
// Broadcast event for the Debug Draw system to catch
|
||||
const SHColliderOnDebugDrawEvent EVENT_DATA
|
||||
{
|
||||
.entityID = GetEID()
|
||||
, .debugDrawState = state
|
||||
};
|
||||
|
||||
SHEventManager::BroadcastEvent<SHColliderOnDebugDrawEvent>(EVENT_DATA, SH_PHYSICS_COLLIDER_DRAW_EVENT);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void SHColliderComponent::SetFactory(rp3d::PhysicsCommon* physicsCommon) noexcept
|
||||
{
|
||||
factory = physicsCommon;
|
||||
}
|
||||
|
||||
void SHColliderComponent::SetCollisionBody(rp3d::CollisionBody* body) noexcept
|
||||
{
|
||||
collisionBody = body;
|
||||
}
|
||||
|
||||
void SHColliderComponent::SetTransform(const SHTransform& newTransform) noexcept
|
||||
{
|
||||
flags |= MOVED_FLAG;
|
||||
transform = newTransform;
|
||||
}
|
||||
|
||||
void SHColliderComponent::SetPosition(const SHVec3& newPosition) noexcept
|
||||
{
|
||||
flags |= MOVED_FLAG;
|
||||
transform.position = newPosition;
|
||||
}
|
||||
|
||||
void SHColliderComponent::SetOrientation(const SHQuaternion& newOrientation) noexcept
|
||||
{
|
||||
flags |= MOVED_FLAG;
|
||||
transform.orientation = newOrientation;
|
||||
}
|
||||
|
||||
void SHColliderComponent::SetScale(const SHVec3& newScale) noexcept
|
||||
{
|
||||
flags |= MOVED_FLAG;
|
||||
transform.scale = newScale;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHColliderComponent::OnCreate()
|
||||
{
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (!physicsSystem)
|
||||
{
|
||||
SHLOG_ERROR("Physics System does not exist to link with Physics Components!")
|
||||
return;
|
||||
}
|
||||
|
||||
system = physicsSystem;
|
||||
|
||||
// Sync with transform if one already exists
|
||||
if (auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(GetEID()); transformComponent)
|
||||
{
|
||||
position = transformComponent->GetWorldPosition();
|
||||
orientation = transformComponent->GetWorldOrientation();
|
||||
scale = transformComponent->GetWorldScale();
|
||||
}
|
||||
}
|
||||
|
||||
void SHColliderComponent::OnDestroy()
|
||||
{
|
||||
int32_t numShapes = static_cast<int32_t>(shapes.size());
|
||||
while (--numShapes >= 0)
|
||||
{
|
||||
delete shapes[numShapes];
|
||||
shapes[numShapes] = nullptr;
|
||||
}
|
||||
|
||||
shapes.clear();
|
||||
}
|
||||
|
||||
void SHColliderComponent::RecomputeCollisionShapes() noexcept
|
||||
const SHMatrix& SHColliderComponent::ComputeTRS() noexcept
|
||||
{
|
||||
for (auto& collisionShape : collisionShapes)
|
||||
return transform.ComputeTRS();
|
||||
}
|
||||
|
||||
int SHColliderComponent::AddSphereCollisionShape(float relativeRadius, const SHVec3& posOffset, const SHVec3& rotOffset)
|
||||
{
|
||||
const float SPHERE_SCALE = std::fabs(SHMath::Max({ transform.scale.x, transform.scale.y, transform.scale.z }));
|
||||
|
||||
const uint32_t NEW_INDEX = static_cast<uint32_t>(shapes.size());
|
||||
|
||||
// Create collision shape
|
||||
shapes.emplace_back(new SHSphere{});
|
||||
auto* newSphere = dynamic_cast<SHSphere*>(shapes.back());
|
||||
|
||||
newSphere->collider = this;
|
||||
newSphere->positionOffset = posOffset;
|
||||
newSphere->rotationOffset = rotOffset;
|
||||
newSphere->relativeRadius = relativeRadius;
|
||||
newSphere->scale = SPHERE_SCALE;
|
||||
|
||||
// Broadcast Event for adding a shape
|
||||
const SHPhysicsColliderAddedEvent EVENT_DATA
|
||||
{
|
||||
switch (collisionShape.GetType())
|
||||
.entityID = GetEID()
|
||||
, .colliderType = SHCollisionShape::Type::BOX
|
||||
, .colliderIndex = static_cast<int>(NEW_INDEX)
|
||||
};
|
||||
|
||||
SHEventManager::BroadcastEvent<SHPhysicsColliderAddedEvent>(EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT);
|
||||
|
||||
// Only link with react if a factory is present.
|
||||
// Otherwise, it will be linked through the physics object manager once the definitions are flushed.
|
||||
if (factory)
|
||||
{
|
||||
rp3d::SphereShape* rp3dSphere = factory->createSphereShape(relativeRadius * SPHERE_SCALE * 0.5f);
|
||||
|
||||
const rp3d::Transform OFFSETS{ posOffset, SHQuaternion::FromEuler(rotOffset) };
|
||||
newSphere->rp3dCollider = collisionBody->addCollider(rp3dSphere, OFFSETS);
|
||||
|
||||
dynamic_cast<rp3d::RigidBody*>(collisionBody)->updateMassPropertiesFromColliders();
|
||||
}
|
||||
|
||||
return static_cast<int>(NEW_INDEX);
|
||||
}
|
||||
|
||||
int SHColliderComponent::AddBoxCollisionShape(const SHVec3& relativeExtents, const SHVec3& posOffset, const SHVec3& rotOffset)
|
||||
{
|
||||
const uint32_t NEW_INDEX = static_cast<uint32_t>(shapes.size());
|
||||
|
||||
// Create collision shape
|
||||
shapes.emplace_back(new SHBox{});
|
||||
auto* newBox = dynamic_cast<SHBox*>(shapes.back());
|
||||
|
||||
newBox->collider = this;
|
||||
newBox->positionOffset = posOffset;
|
||||
newBox->rotationOffset = rotOffset;
|
||||
newBox->relativeExtents = relativeExtents;
|
||||
newBox->scale = SHVec3::Abs(transform.scale);
|
||||
|
||||
// Broadcast Event for adding a shape
|
||||
const SHPhysicsColliderAddedEvent EVENT_DATA
|
||||
{
|
||||
.entityID = GetEID()
|
||||
, .colliderType = SHCollisionShape::Type::BOX
|
||||
, .colliderIndex = static_cast<int>(NEW_INDEX)
|
||||
};
|
||||
|
||||
SHEventManager::BroadcastEvent<SHPhysicsColliderAddedEvent>(EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT);
|
||||
|
||||
if (factory)
|
||||
{
|
||||
rp3d::BoxShape* rp3dBox = factory->createBoxShape(relativeExtents * newBox->scale * 0.5f);
|
||||
|
||||
const rp3d::Transform OFFSETS{ posOffset, SHQuaternion::FromEuler(rotOffset) };
|
||||
newBox->rp3dCollider = collisionBody->addCollider(rp3dBox, OFFSETS);
|
||||
|
||||
dynamic_cast<rp3d::RigidBody*>(collisionBody)->updateMassPropertiesFromColliders();
|
||||
}
|
||||
|
||||
return static_cast<int>(NEW_INDEX);
|
||||
}
|
||||
|
||||
void SHColliderComponent::RemoveCollisionShape(int index)
|
||||
{
|
||||
const int NUM_SHAPES = static_cast<int>(shapes.size());
|
||||
|
||||
if (index < 0 || index >= NUM_SHAPES)
|
||||
throw std::invalid_argument("Out-of-range index!");
|
||||
|
||||
int i = 0;
|
||||
for (auto shapeIter = shapes.begin(); shapeIter != shapes.end(); ++i, ++shapeIter)
|
||||
{
|
||||
if (i == index)
|
||||
{
|
||||
case SHCollisionShape::Type::BOX:
|
||||
collisionBody->removeCollider((*shapeIter)->rp3dCollider);
|
||||
dynamic_cast<rp3d::RigidBody*>(collisionBody)->updateMassPropertiesFromColliders();
|
||||
|
||||
const SHPhysicsColliderRemovedEvent EVENT_DATA
|
||||
{
|
||||
auto* box = reinterpret_cast<SHBox*>(collisionShape.shape);
|
||||
const SHVec3& RELATIVE_EXTENTS = box->GetRelativeExtents();
|
||||
.entityID = GetEID()
|
||||
, .colliderType = (*shapeIter)->GetType()
|
||||
, .colliderIndex = index
|
||||
};
|
||||
|
||||
// Recompute world extents based on new scale and fixed relative extents
|
||||
// Broadcast Event for removing a shape
|
||||
SHEventManager::BroadcastEvent<SHPhysicsColliderRemovedEvent>(EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT);
|
||||
|
||||
const SHVec3 WORLD_EXTENTS = RELATIVE_EXTENTS * (scale * 0.5f);
|
||||
box->SetWorldExtents(WORLD_EXTENTS);
|
||||
SHLOG_INFO_D("Removing Collision Shape {} from Entity {}", index, GetEID())
|
||||
|
||||
continue;
|
||||
}
|
||||
case SHCollisionShape::Type::SPHERE:
|
||||
{
|
||||
auto* sphere = reinterpret_cast<SHSphere*>(collisionShape.shape);
|
||||
const float RELATIVE_RADIUS = sphere->GetRelativeRadius();
|
||||
|
||||
// Recompute world radius based on new scale and fixed radius
|
||||
|
||||
const float MAX_SCALE = SHMath::Max({ scale.x, scale.y, scale.z });
|
||||
const float WORLD_RADIUS = RELATIVE_RADIUS * MAX_SCALE * 0.5f;
|
||||
sphere->SetWorldRadius(WORLD_RADIUS);
|
||||
|
||||
continue;
|
||||
}
|
||||
default: continue;
|
||||
delete *shapeIter;
|
||||
shapeIter = shapes.erase(shapeIter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int SHColliderComponent::AddBoundingBox(const SHVec3& halfExtents, const SHVec3& posOffset, const SHVec3& rotOffset) noexcept
|
||||
void SHColliderComponent::Update() noexcept
|
||||
{
|
||||
if (!system)
|
||||
{
|
||||
SHLOG_ERROR("Physics system does not exist, unable to add Box Collider!")
|
||||
return -1;
|
||||
}
|
||||
|
||||
static constexpr auto TYPE = SHCollisionShape::Type::BOX;
|
||||
|
||||
auto& collider = collisionShapes.emplace_back(SHCollisionShape{ GetEID(), TYPE });
|
||||
|
||||
collider.entityID = GetEID();
|
||||
collider.SetPositionOffset(posOffset);
|
||||
collider.SetRotationOffset(rotOffset);
|
||||
collider.SetBoundingBox(halfExtents);
|
||||
|
||||
// Notify Physics System
|
||||
const int NEW_SHAPE_INDEX = static_cast<int>(collisionShapes.size()) - 1;
|
||||
|
||||
system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX);
|
||||
return NEW_SHAPE_INDEX;
|
||||
for (auto& shape : shapes)
|
||||
shape->Update();
|
||||
}
|
||||
|
||||
int SHColliderComponent::AddBoundingSphere(float radius, const SHVec3& posOffset) noexcept
|
||||
void SHColliderComponent::UpdateCollisionTags() noexcept
|
||||
{
|
||||
if (!system)
|
||||
{
|
||||
SHLOG_ERROR("Physics system does not exist, unable to add Sphere Collider!")
|
||||
return -1;
|
||||
}
|
||||
|
||||
static constexpr auto TYPE = SHCollisionShape::Type::SPHERE;
|
||||
|
||||
auto& collider = collisionShapes.emplace_back(SHCollisionShape{ GetEID(), TYPE });
|
||||
|
||||
collider.entityID = GetEID();
|
||||
collider.SetPositionOffset(posOffset);
|
||||
collider.SetBoundingSphere(radius);
|
||||
|
||||
// Notify Physics System
|
||||
const int NEW_SHAPE_INDEX = static_cast<int>(collisionShapes.size()) - 1;
|
||||
|
||||
system->AddCollisionShape(GetEID(), NEW_SHAPE_INDEX);
|
||||
return NEW_SHAPE_INDEX;
|
||||
for (auto& shape : shapes)
|
||||
shape->UpdateCollisionTags();
|
||||
}
|
||||
|
||||
void SHColliderComponent::RemoveCollider(int index)
|
||||
{
|
||||
if (index < 0 || static_cast<size_t>(index) >= collisionShapes.size())
|
||||
throw std::invalid_argument("Out-of-range access!");
|
||||
|
||||
int idx = 0;
|
||||
auto it = collisionShapes.begin();
|
||||
for (; it != collisionShapes.end(); ++it)
|
||||
{
|
||||
if (idx == index)
|
||||
break;
|
||||
|
||||
++idx;
|
||||
}
|
||||
|
||||
it = collisionShapes.erase(it);
|
||||
|
||||
// Notify Physics System
|
||||
if (!system)
|
||||
{
|
||||
SHLOG_ERROR("Physics system does not exist, unable to remove Collider!")
|
||||
return;
|
||||
}
|
||||
|
||||
system->RemoveCollisionShape(GetEID(), index);
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
||||
|
||||
|
|
|
@ -10,18 +10,24 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <rttr/registration>
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Components/SHComponent.h"
|
||||
#include "Math/Geometry/SHBox.h"
|
||||
#include "Math/Geometry/SHSphere.h"
|
||||
#include "SHCollisionShape.h"
|
||||
#include "Math/Transform/SHTransform.h"
|
||||
#include "Physics/Collision/Shapes/SHCollisionShape.h"
|
||||
|
||||
//namespace SHADE
|
||||
//{
|
||||
// class SHPhysicsSystem;
|
||||
//}
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
|
||||
namespace reactphysics3d
|
||||
{
|
||||
class PhysicsCommon;
|
||||
class CollisionBody;
|
||||
}
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -37,13 +43,13 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHPhysicsSystem;
|
||||
friend class SHPhysicsObject;
|
||||
friend class SHPhysicsObjectManager;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
using CollisionShapes = std::vector<SHCollisionShape>;
|
||||
using CollisionShapes = std::vector<SHCollisionShape*>;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -67,29 +73,96 @@ namespace SHADE
|
|||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] bool HasChanged () const noexcept;
|
||||
[[nodiscard]] bool GetDebugDrawState () const noexcept;
|
||||
|
||||
[[nodiscard]] const SHVec3& GetPosition () const noexcept;
|
||||
[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetScale () const noexcept;
|
||||
[[nodiscard]] const SHTransform& GetTransform () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetPosition () const noexcept;
|
||||
[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetScale () const noexcept;
|
||||
|
||||
[[nodiscard]] const CollisionShapes& GetCollisionShapes() const noexcept;
|
||||
[[nodiscard]] SHCollisionShape& GetCollisionShape (int index);
|
||||
[[nodiscard]] const CollisionShapes& GetCollisionShapes () const noexcept;
|
||||
[[nodiscard]] SHCollisionShape& GetCollisionShape (int index);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetDebugDrawState (bool state) noexcept;
|
||||
|
||||
void SetFactory (reactphysics3d::PhysicsCommon* physicsCommon) noexcept;
|
||||
void SetCollisionBody (reactphysics3d::CollisionBody* body) noexcept;
|
||||
|
||||
void SetTransform (const SHTransform& newTransform) noexcept;
|
||||
void SetPosition (const SHVec3& newPosition) noexcept;
|
||||
void SetOrientation (const SHQuaternion& newOrientation) noexcept;
|
||||
void SetScale (const SHVec3& newScale) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void OnCreate () override;
|
||||
void OnDestroy () override;
|
||||
void OnDestroy() override;
|
||||
|
||||
void RecomputeCollisionShapes () noexcept;
|
||||
/**
|
||||
* @brief
|
||||
* Computes the TRS for the collider's transform
|
||||
* @return
|
||||
* The computed TRS.
|
||||
*/
|
||||
const SHMatrix& ComputeTRS() noexcept;
|
||||
|
||||
void RemoveCollider (int index);
|
||||
/**
|
||||
* @brief
|
||||
* Adds a sphere collision shape.
|
||||
* @param relativeRadius
|
||||
* The relative radius is constructed with respect to the world scale. <br/>
|
||||
* Radius = max(scale.x, scale.y, scale.z) * 0.5 * relativeRadius
|
||||
* @param posOffset
|
||||
* The position offset of the sphere from the center of the collider. Defaults to a Zero Vector.
|
||||
* @param rotOffset
|
||||
* The rotation offset of the sphere from the rotation of the collider. Defaults to a Zero Vector.
|
||||
* @return
|
||||
* The index of the newly added shape.
|
||||
*/
|
||||
int AddSphereCollisionShape (float relativeRadius, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero);
|
||||
|
||||
int AddBoundingBox (const SHVec3& halfExtents = SHVec3::One, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero) noexcept;
|
||||
int AddBoundingSphere (float radius = 1.0f, const SHVec3& posOffset = SHVec3::Zero) noexcept;
|
||||
/**
|
||||
* @brief
|
||||
* Adds a box collision shape.
|
||||
* @param relativeExtents
|
||||
* The relative extents are constructed with respect to the world scale. <br/>
|
||||
* Extents = scale * 0.5 * relativeExtents
|
||||
* @param posOffset
|
||||
* The position offset of the box from the center of the collider. Defaults to a Zero Vector.
|
||||
* @param rotOffset
|
||||
* The rotation offset of the box from the rotation of the collider. Defaults to a Zero Vector.
|
||||
* @return
|
||||
* The index of the newly added shape.
|
||||
*/
|
||||
int AddBoxCollisionShape (const SHVec3& relativeExtents, const SHVec3& posOffset = SHVec3::Zero, const SHVec3& rotOffset = SHVec3::Zero);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Removes a shape from the container. Removal reduces the size of the container.
|
||||
* If removing all, perform removal from back to front.
|
||||
* @param index
|
||||
* The index of the shape to remove.
|
||||
* @throws
|
||||
* Invalid argument for out-of-range indices.
|
||||
*/
|
||||
void RemoveCollisionShape (int index);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Recomputes the transforms for all shapes in this composite collider.
|
||||
*/
|
||||
void Update () noexcept;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Re-sets any dirty collision tags on collision shapes.
|
||||
*/
|
||||
void UpdateCollisionTags () noexcept;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -97,12 +170,15 @@ namespace SHADE
|
|||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsSystem* system;
|
||||
static constexpr uint8_t ACTIVE_FLAG = 1U << 0;
|
||||
static constexpr uint8_t DRAW_FLAG = 1U << 1;
|
||||
static constexpr uint8_t MOVED_FLAG = 1U << 2;
|
||||
|
||||
SHVec3 position;
|
||||
SHQuaternion orientation;
|
||||
SHVec3 scale;
|
||||
CollisionShapes collisionShapes;
|
||||
uint8_t flags; // 0 0 0 0 0 hasMoved debugDraw active
|
||||
reactphysics3d::PhysicsCommon* factory;
|
||||
reactphysics3d::CollisionBody* collisionBody;
|
||||
SHTransform transform;
|
||||
CollisionShapes shapes;
|
||||
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
|
|
|
@ -1,368 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHCollider.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Collider.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHCollisionShape.h"
|
||||
// Project Headers
|
||||
#include "Math/Geometry/SHBox.h"
|
||||
#include "Math/Geometry/SHSphere.h"
|
||||
#include "Math/SHMathHelpers.h"
|
||||
#include "Physics/Collision/SHCollisionTagMatrix.h"
|
||||
#include "Reflection/SHReflectionMetadata.h"
|
||||
#include "SHColliderComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHCollisionShape::SHCollisionShape(EntityID eid, Type colliderType, const SHPhysicsMaterial& physicsMaterial)
|
||||
: type { colliderType }
|
||||
, entityID { eid }
|
||||
, isTrigger { false }
|
||||
, dirty { true }
|
||||
, shape { nullptr }
|
||||
, material { physicsMaterial }
|
||||
, collisionTag { SHCollisionTagMatrix::GetTag(0) }
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Type::BOX:
|
||||
{
|
||||
shape = new SHBox{ SHVec3::Zero, SHVec3::One };
|
||||
break;
|
||||
}
|
||||
case Type::SPHERE:
|
||||
{
|
||||
shape = new SHSphere{ SHVec3::Zero, 0.5f };
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
SHCollisionShape::SHCollisionShape(const SHCollisionShape& rhs) noexcept
|
||||
: type { rhs.type}
|
||||
, entityID { rhs.entityID }
|
||||
, isTrigger { rhs.isTrigger }
|
||||
, dirty { true }
|
||||
, shape { nullptr }
|
||||
, material { rhs.material }
|
||||
, positionOffset { rhs.positionOffset }
|
||||
, rotationOffset { rhs.rotationOffset }
|
||||
, collisionTag { rhs.collisionTag }
|
||||
{
|
||||
CopyShape(rhs.shape);
|
||||
}
|
||||
|
||||
SHCollisionShape::SHCollisionShape(SHCollisionShape&& rhs) noexcept
|
||||
: type { rhs.type}
|
||||
, entityID { rhs.entityID }
|
||||
, isTrigger { rhs.isTrigger }
|
||||
, dirty { true }
|
||||
, shape { nullptr }
|
||||
, material { rhs.material }
|
||||
, positionOffset { rhs.positionOffset }
|
||||
, rotationOffset { rhs.rotationOffset }
|
||||
, collisionTag { rhs.collisionTag }
|
||||
{
|
||||
CopyShape(rhs.shape);
|
||||
}
|
||||
|
||||
SHCollisionShape::~SHCollisionShape() noexcept
|
||||
{
|
||||
shape = nullptr;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Operator Overload Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHCollisionShape& SHCollisionShape::operator=(const SHCollisionShape& rhs) noexcept
|
||||
{
|
||||
if (this == &rhs)
|
||||
return *this;
|
||||
|
||||
type = rhs.type;
|
||||
entityID = rhs.entityID;
|
||||
isTrigger = rhs.isTrigger;
|
||||
dirty = true;
|
||||
material = rhs.material;
|
||||
positionOffset = rhs.positionOffset;
|
||||
rotationOffset = rhs.rotationOffset;
|
||||
collisionTag = rhs.collisionTag;
|
||||
|
||||
delete shape;
|
||||
CopyShape(rhs.shape);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
SHCollisionShape& SHCollisionShape::operator=(SHCollisionShape&& rhs) noexcept
|
||||
{
|
||||
type = rhs.type;
|
||||
entityID = rhs.entityID;
|
||||
isTrigger = rhs.isTrigger;
|
||||
dirty = true;
|
||||
material = rhs.material;
|
||||
positionOffset = rhs.positionOffset;
|
||||
rotationOffset = rhs.rotationOffset;
|
||||
collisionTag = rhs.collisionTag;
|
||||
|
||||
delete shape;
|
||||
CopyShape(rhs.shape);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHCollisionShape::HasChanged() const noexcept
|
||||
{
|
||||
return dirty;
|
||||
}
|
||||
|
||||
bool SHCollisionShape::IsTrigger() const noexcept
|
||||
{
|
||||
return isTrigger;
|
||||
}
|
||||
|
||||
SHCollisionShape::Type SHCollisionShape::GetType() const noexcept
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
const SHCollisionTag& SHCollisionShape::GetCollisionTag() const noexcept
|
||||
{
|
||||
return *collisionTag;
|
||||
}
|
||||
|
||||
float SHCollisionShape::GetFriction() const noexcept
|
||||
{
|
||||
return material.GetFriction();
|
||||
}
|
||||
|
||||
float SHCollisionShape::GetBounciness() const noexcept
|
||||
{
|
||||
return material.GetBounciness();
|
||||
}
|
||||
|
||||
float SHCollisionShape::GetDensity() const noexcept
|
||||
{
|
||||
return material.GetDensity();
|
||||
}
|
||||
|
||||
const SHPhysicsMaterial& SHCollisionShape::GetMaterial() const noexcept
|
||||
{
|
||||
return material;
|
||||
}
|
||||
|
||||
const SHVec3& SHCollisionShape::GetPositionOffset() const noexcept
|
||||
{
|
||||
return positionOffset;
|
||||
}
|
||||
|
||||
const SHVec3& SHCollisionShape::GetRotationOffset() const noexcept
|
||||
{
|
||||
return rotationOffset;
|
||||
}
|
||||
|
||||
const SHShape* SHCollisionShape::GetShape() const noexcept
|
||||
{
|
||||
return shape;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHCollisionShape::SetBoundingBox(const SHVec3& halfExtents)
|
||||
{
|
||||
dirty = true;
|
||||
|
||||
const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
||||
auto* box = reinterpret_cast<SHBox*>(shape);
|
||||
|
||||
SHVec3 correctedHalfExtents = halfExtents;
|
||||
|
||||
// Get current relative halfExtents for error checking. 0 is ignored
|
||||
const SHVec3& CURRENT_RELATIVE_EXTENTS = box->GetRelativeExtents();
|
||||
for (size_t i = 0; i < SHVec3::SIZE; ++i)
|
||||
{
|
||||
if (SHMath::CompareFloat(halfExtents[i], 0.0f))
|
||||
correctedHalfExtents[i] = CURRENT_RELATIVE_EXTENTS[i];
|
||||
}
|
||||
|
||||
// Set the half extents relative to world scale
|
||||
const SHVec3 WORLD_EXTENTS = correctedHalfExtents * COLLIDER->GetScale() * 0.5f;
|
||||
|
||||
if (type != Type::BOX)
|
||||
{
|
||||
type = Type::BOX;
|
||||
|
||||
delete shape;
|
||||
shape = new SHBox{ positionOffset, WORLD_EXTENTS };
|
||||
}
|
||||
|
||||
box->SetWorldExtents(WORLD_EXTENTS);
|
||||
box->SetRelativeExtents(correctedHalfExtents);
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetBoundingSphere(float radius)
|
||||
{
|
||||
dirty = true;
|
||||
|
||||
auto* sphere = reinterpret_cast<SHSphere*>(shape);
|
||||
const auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
||||
|
||||
// Get current relative halfExtents for error checking. 0 is ignored
|
||||
const float CURRENT_RELATIVE_RADIUS = sphere->GetRelativeRadius();
|
||||
if (SHMath::CompareFloat(radius, 0.0f))
|
||||
radius = CURRENT_RELATIVE_RADIUS;
|
||||
|
||||
// Set the radius relative to world scale
|
||||
const SHVec3 WORLD_SCALE = COLLIDER->GetScale();
|
||||
const float MAX_SCALE = SHMath::Max({ WORLD_SCALE.x, WORLD_SCALE.y, WORLD_SCALE.z });
|
||||
const float WORLD_RADIUS = radius * MAX_SCALE * 0.5f;
|
||||
|
||||
if (type != Type::SPHERE)
|
||||
{
|
||||
type = Type::SPHERE;
|
||||
|
||||
delete shape;
|
||||
shape = new SHSphere{ positionOffset, WORLD_RADIUS };
|
||||
}
|
||||
|
||||
sphere->SetWorldRadius(WORLD_RADIUS);
|
||||
sphere->SetRelativeRadius(radius);
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetIsTrigger(bool trigger) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
isTrigger = trigger;
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetCollisionTag(SHCollisionTag* newCollisionTag) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
collisionTag = newCollisionTag;
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetFriction(float friction) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
material.SetFriction(friction);
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetBounciness(float bounciness) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
material.SetBounciness(bounciness);
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetDensity(float density) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
material.SetDensity(density);
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetMaterial(const SHPhysicsMaterial& newMaterial) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
material = newMaterial;
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetPositionOffset(const SHVec3& posOffset) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
positionOffset = posOffset;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case Type::BOX:
|
||||
{
|
||||
reinterpret_cast<SHBox*>(shape)->SetCenter(positionOffset);
|
||||
break;
|
||||
}
|
||||
case Type::SPHERE:
|
||||
{
|
||||
reinterpret_cast<SHSphere*>(shape)->SetCenter(positionOffset);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void SHCollisionShape::SetRotationOffset(const SHVec3& rotOffset) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
rotationOffset = rotOffset;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHCollisionShape::CopyShape(const SHShape* rhs)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Type::BOX:
|
||||
{
|
||||
const auto* RHS_BOX = reinterpret_cast<const SHBox*>(rhs);
|
||||
|
||||
shape = new SHBox{ positionOffset, RHS_BOX->GetWorldExtents() };
|
||||
auto* lhsBox = reinterpret_cast<SHBox*>(shape);
|
||||
lhsBox->SetRelativeExtents(RHS_BOX->GetRelativeExtents());
|
||||
|
||||
break;
|
||||
}
|
||||
case Type::SPHERE:
|
||||
{
|
||||
const auto* RHS_SPHERE = reinterpret_cast<const SHSphere*>(rhs);
|
||||
|
||||
shape = new SHSphere{ positionOffset, RHS_SPHERE->GetWorldRadius() };
|
||||
auto* lhsSphere = reinterpret_cast<SHSphere*>(shape);
|
||||
lhsSphere->SetRelativeRadius(RHS_SPHERE->GetRelativeRadius());
|
||||
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
||||
|
||||
RTTR_REGISTRATION
|
||||
{
|
||||
using namespace SHADE;
|
||||
using namespace rttr;
|
||||
|
||||
registration::enumeration<SHCollisionShape::Type>("Collider Type")
|
||||
(
|
||||
value("Box", SHCollisionShape::Type::BOX),
|
||||
value("Sphere", SHCollisionShape::Type::SPHERE)
|
||||
// TODO(Diren): Add More Shapes
|
||||
);
|
||||
|
||||
registration::class_<SHCollisionShape>("Collider")
|
||||
.property("IsTrigger" , &SHCollisionShape::IsTrigger , &SHCollisionShape::SetIsTrigger )
|
||||
.property("Friction" , &SHCollisionShape::GetFriction , &SHCollisionShape::SetFriction )
|
||||
.property("Bounciness" , &SHCollisionShape::GetBounciness , &SHCollisionShape::SetBounciness )
|
||||
.property("Density" , &SHCollisionShape::GetDensity , &SHCollisionShape::SetDensity )
|
||||
.property("Position Offset" , &SHCollisionShape::GetPositionOffset, &SHCollisionShape::SetPositionOffset)
|
||||
.property("Rotation Offset" , &SHCollisionShape::GetRotationOffset, &SHCollisionShape::SetRotationOffset) (metadata(META::angleInRad, true));
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHCollider.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a Collider.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <rttr/registration>
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Entity/SHEntity.h"
|
||||
#include "Math/Geometry/SHShape.h"
|
||||
#include "Math/SHQuaternion.h"
|
||||
#include "SHPhysicsMaterial.h"
|
||||
#include "Physics/Collision/SHCollisionTags.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHCollisionShape
|
||||
{
|
||||
private:
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Friends */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHColliderComponent;
|
||||
friend class SHPhysicsObject;
|
||||
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
enum class Type
|
||||
{
|
||||
BOX
|
||||
, SPHERE
|
||||
, CAPSULE
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHCollisionShape (EntityID eid, Type colliderType = Type::BOX, const SHPhysicsMaterial& physicsMaterial = SHPhysicsMaterial::DEFAULT);
|
||||
|
||||
SHCollisionShape (const SHCollisionShape& rhs) noexcept;
|
||||
SHCollisionShape (SHCollisionShape&& rhs) noexcept;
|
||||
~SHCollisionShape () noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHCollisionShape& operator=(const SHCollisionShape& rhs) noexcept;
|
||||
SHCollisionShape& operator=(SHCollisionShape&& rhs) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] bool HasChanged () const noexcept;
|
||||
|
||||
[[nodiscard]] bool IsTrigger () const noexcept;
|
||||
|
||||
[[nodiscard]] Type GetType () const noexcept;
|
||||
|
||||
[[nodiscard]] const SHCollisionTag& GetCollisionTag () const noexcept;
|
||||
|
||||
[[nodiscard]] float GetFriction () const noexcept;
|
||||
[[nodiscard]] float GetBounciness () const noexcept;
|
||||
[[nodiscard]] float GetDensity () const noexcept;
|
||||
[[nodiscard]] const SHPhysicsMaterial& GetMaterial () const noexcept;
|
||||
|
||||
[[nodiscard]] const SHVec3& GetPositionOffset () const noexcept;
|
||||
[[nodiscard]] const SHVec3& GetRotationOffset () const noexcept;
|
||||
|
||||
[[nodiscard]] const SHShape* GetShape () const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetBoundingBox (const SHVec3& halfExtents);
|
||||
void SetBoundingSphere (float radius);
|
||||
|
||||
void SetIsTrigger (bool isTrigger) noexcept;
|
||||
void SetCollisionTag (SHCollisionTag* newCollisionTag) noexcept;
|
||||
void SetFriction (float friction) noexcept;
|
||||
void SetBounciness (float bounciness) noexcept;
|
||||
void SetDensity (float density) noexcept;
|
||||
void SetMaterial (const SHPhysicsMaterial& newMaterial) noexcept;
|
||||
|
||||
void SetPositionOffset (const SHVec3& posOffset) noexcept;
|
||||
void SetRotationOffset (const SHVec3& rotOffset) noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
Type type;
|
||||
EntityID entityID; // The entity this collider belongs to
|
||||
bool isTrigger;
|
||||
bool dirty;
|
||||
|
||||
SHShape* shape;
|
||||
SHPhysicsMaterial material;
|
||||
|
||||
SHVec3 positionOffset;
|
||||
SHVec3 rotationOffset;
|
||||
|
||||
SHCollisionTag* collisionTag;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void CopyShape(const SHShape* rhs);
|
||||
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
|
||||
} // namespace SHADE
|
|
@ -20,6 +20,7 @@
|
|||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Math/SHMathHelpers.h"
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
#include "Tools/Utilities/SHUtilities.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -29,99 +30,78 @@ namespace SHADE
|
|||
|
||||
SHRigidBodyComponent::SHRigidBodyComponent() noexcept
|
||||
: type { Type::DYNAMIC }
|
||||
, interpolate { true }
|
||||
, flags { 0 }
|
||||
, dirtyFlags { std::numeric_limits<uint16_t>::max() }
|
||||
, mass { 1.0f }
|
||||
, drag { 0.01f }
|
||||
, angularDrag { 0.01f }
|
||||
, system { nullptr }
|
||||
, angularDrag { 0.1f }
|
||||
, rigidBody { nullptr }
|
||||
{
|
||||
// Initialise default flags
|
||||
flags |= 1U << 0; // Gravity set to true
|
||||
flags |= 1U << 1; // Sleeping allowed
|
||||
flags |= 1U << 8; // Interpolate by default
|
||||
// Default flags
|
||||
flags |= 1U << 0; // enable gravity
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 0;
|
||||
return flags & (1U << FLAG_POS);
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 1;
|
||||
return flags & (1U << FLAG_POS);
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::IsInterpolating() const noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 8;
|
||||
return flags & (1U << FLAG_POS);
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::GetIsSleeping() const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
return physicsObject->GetRigidBody()->isSleeping();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
SHRigidBodyComponent::Type SHRigidBodyComponent::GetType() const noexcept
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::IsGravityEnabled() const noexcept
|
||||
{
|
||||
return flags & SHUtilities::ConvertEnum(Flags::GRAVITY);
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::IsAllowedToSleep() const noexcept
|
||||
{
|
||||
return flags & SHUtilities::ConvertEnum(Flags::SLEEPING);
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::IsInterpolating() const noexcept
|
||||
{
|
||||
return interpolate;
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::IsSleeping() const noexcept
|
||||
{
|
||||
return rigidBody ? rigidBody->isSleeping() : false;
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::GetFreezePositionX() const noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 2;
|
||||
return flags & (1U << FLAG_POS);
|
||||
return flags & SHUtilities::ConvertEnum(Flags::LINEAR_X);
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::GetFreezePositionY() const noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 3;
|
||||
return flags & (1U << FLAG_POS);
|
||||
return flags & SHUtilities::ConvertEnum(Flags::LINEAR_Y);
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::GetFreezePositionZ() const noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 4;
|
||||
return flags & (1U << FLAG_POS);
|
||||
return flags & SHUtilities::ConvertEnum(Flags::LINEAR_Z);
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::GetFreezeRotationX() const noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 5;
|
||||
return flags & (1U << FLAG_POS);
|
||||
return flags & SHUtilities::ConvertEnum(Flags::ANGULAR_X);
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::GetFreezeRotationY() const noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 6;
|
||||
return flags & (1U << FLAG_POS);
|
||||
return flags & SHUtilities::ConvertEnum(Flags::ANGULAR_Y);
|
||||
}
|
||||
|
||||
bool SHRigidBodyComponent::GetFreezeRotationZ() const noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 7;
|
||||
return flags & (1U << FLAG_POS);
|
||||
return flags & SHUtilities::ConvertEnum(Flags::ANGULAR_Z);
|
||||
}
|
||||
|
||||
//bool SHRigidBodyComponent::GetAutoMass() const noexcept
|
||||
//{
|
||||
// static constexpr int FLAG_POS = 9;
|
||||
// return flags & (1U << FLAG_POS);
|
||||
//}
|
||||
|
||||
float SHRigidBodyComponent::GetMass() const noexcept
|
||||
float SHRigidBodyComponent::GetMass() const noexcept
|
||||
{
|
||||
return mass;
|
||||
return rigidBody ? rigidBody->getMass() : 0.0f;
|
||||
}
|
||||
|
||||
float SHRigidBodyComponent::GetDrag() const noexcept
|
||||
|
@ -136,49 +116,32 @@ namespace SHADE
|
|||
|
||||
SHVec3 SHRigidBodyComponent::GetForce() const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
return physicsObject->GetRigidBody()->getForce();
|
||||
|
||||
return SHVec3::Zero;
|
||||
return rigidBody ? SHVec3{ rigidBody->getForce() } : SHVec3::Zero;
|
||||
}
|
||||
|
||||
SHVec3 SHRigidBodyComponent::GetTorque() const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
return physicsObject->GetRigidBody()->getTorque();
|
||||
|
||||
return SHVec3::Zero;
|
||||
return rigidBody ? SHVec3{ rigidBody->getTorque() } : SHVec3::Zero;
|
||||
}
|
||||
|
||||
SHVec3 SHRigidBodyComponent::GetLinearVelocity() const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
return physicsObject->GetRigidBody()->getLinearVelocity();
|
||||
|
||||
return SHVec3::Zero;
|
||||
return rigidBody ? SHVec3{ rigidBody->getLinearVelocity() } : SHVec3::Zero;
|
||||
}
|
||||
|
||||
SHVec3 SHRigidBodyComponent::GetAngularVelocity() const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
return physicsObject->GetRigidBody()->getAngularVelocity();
|
||||
|
||||
return SHVec3::Zero;
|
||||
return rigidBody ? SHVec3{ rigidBody->getAngularVelocity() } : SHVec3::Zero;
|
||||
}
|
||||
|
||||
const SHVec3& SHRigidBodyComponent::GetPosition() const noexcept
|
||||
SHVec3 SHRigidBodyComponent::GetPosition() const noexcept
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
const SHQuaternion& SHRigidBodyComponent::GetOrientation() const noexcept
|
||||
{
|
||||
return orientation;
|
||||
return rigidBody ? SHVec3{ rigidBody->getTransform().getPosition() } : SHVec3::Zero;
|
||||
}
|
||||
|
||||
SHVec3 SHRigidBodyComponent::GetRotation() const noexcept
|
||||
{
|
||||
return orientation.ToEuler();
|
||||
return rigidBody ? SHQuaternion{ rigidBody->getTransform().getOrientation() }.ToEuler() : SHVec3::Zero;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -187,224 +150,175 @@ namespace SHADE
|
|||
|
||||
void SHRigidBodyComponent::SetType(Type newType) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 8;
|
||||
|
||||
if (type == newType)
|
||||
return;
|
||||
|
||||
type = newType;
|
||||
dirtyFlags |= 1U << FLAG_POS;
|
||||
|
||||
if (rigidBody)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Type::STATIC:
|
||||
rigidBody->setType(rp3d::BodyType::STATIC);
|
||||
break;
|
||||
case Type::KINEMATIC:
|
||||
rigidBody->setType(rp3d::BodyType::KINEMATIC);
|
||||
break;
|
||||
case Type::DYNAMIC:
|
||||
rigidBody->setType(rp3d::BodyType::DYNAMIC);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetRigidBody(rp3d::RigidBody* body) noexcept
|
||||
{
|
||||
rigidBody = body;
|
||||
}
|
||||
|
||||
|
||||
void SHRigidBodyComponent::SetGravityEnabled(bool enableGravity) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 0;
|
||||
constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::GRAVITY);
|
||||
enableGravity ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE;
|
||||
|
||||
if (type != Type::DYNAMIC)
|
||||
{
|
||||
SHLOG_WARNING("Cannot enable gravity of a non-dynamic object {}", GetEID())
|
||||
return;
|
||||
}
|
||||
|
||||
dirtyFlags |= 1U << FLAG_POS;
|
||||
enableGravity ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||
if (rigidBody)
|
||||
rigidBody->enableGravity(enableGravity);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetIsAllowedToSleep(bool isAllowedToSleep) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 1;
|
||||
constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::SLEEPING);
|
||||
isAllowedToSleep ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE;
|
||||
|
||||
if (type != Type::DYNAMIC)
|
||||
{
|
||||
SHLOG_WARNING("Cannot enable sleeping of a non-dynamic object {}", GetEID())
|
||||
return;
|
||||
}
|
||||
|
||||
dirtyFlags |= 1U << FLAG_POS;
|
||||
isAllowedToSleep ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||
if (rigidBody)
|
||||
rigidBody->setIsAllowedToSleep(isAllowedToSleep);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetFreezePositionX(bool freezePositionX) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 2;
|
||||
constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::LINEAR_X);
|
||||
freezePositionX ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE;
|
||||
|
||||
if (type == Type::STATIC)
|
||||
if (rigidBody)
|
||||
{
|
||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||
return;
|
||||
rp3d::Vector3 linearLock = rigidBody->getLinearLockAxisFactor();
|
||||
linearLock.x = freezePositionX ? 0.0f : 1.0f;
|
||||
rigidBody->setLinearLockAxisFactor(linearLock);
|
||||
}
|
||||
|
||||
dirtyFlags |= 1U << FLAG_POS;
|
||||
freezePositionX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetFreezePositionY(bool freezePositionY) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 3;
|
||||
constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::LINEAR_Y);
|
||||
freezePositionY ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE;
|
||||
|
||||
if (type == Type::STATIC)
|
||||
if (rigidBody)
|
||||
{
|
||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||
return;
|
||||
rp3d::Vector3 linearLock = rigidBody->getLinearLockAxisFactor();
|
||||
linearLock.y = freezePositionY ? 0.0f : 1.0f;
|
||||
rigidBody->setLinearLockAxisFactor(linearLock);
|
||||
}
|
||||
|
||||
dirtyFlags |= 1U << FLAG_POS;
|
||||
freezePositionY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetFreezePositionZ(bool freezePositionZ) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 4;
|
||||
constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::LINEAR_Z);
|
||||
freezePositionZ ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE;
|
||||
|
||||
if (type == Type::STATIC)
|
||||
if (rigidBody)
|
||||
{
|
||||
SHLOG_WARNING("Cannot set linear constraints of a static object {}", GetEID())
|
||||
return;
|
||||
rp3d::Vector3 linearLock = rigidBody->getLinearLockAxisFactor();
|
||||
linearLock.z = freezePositionZ ? 0.0f : 1.0f;
|
||||
rigidBody->setLinearLockAxisFactor(linearLock);
|
||||
}
|
||||
|
||||
dirtyFlags |= 1U << FLAG_POS;
|
||||
freezePositionZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetFreezeRotationX(bool freezeRotationX) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 5;
|
||||
constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::ANGULAR_X);
|
||||
freezeRotationX ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE;
|
||||
|
||||
if (type == Type::STATIC)
|
||||
if (rigidBody)
|
||||
{
|
||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||
return;
|
||||
rp3d::Vector3 angularLock = rigidBody->getAngularLockAxisFactor();
|
||||
angularLock.x = freezeRotationX ? 0.0f : 1.0f;
|
||||
rigidBody->setAngularLockAxisFactor(angularLock);
|
||||
}
|
||||
|
||||
dirtyFlags |= 1U << FLAG_POS;
|
||||
freezeRotationX ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetFreezeRotationY(bool freezeRotationY) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 6;
|
||||
constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::ANGULAR_Y);
|
||||
freezeRotationY ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE;
|
||||
|
||||
if (type == Type::STATIC)
|
||||
if (rigidBody)
|
||||
{
|
||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||
return;
|
||||
rp3d::Vector3 angularLock = rigidBody->getAngularLockAxisFactor();
|
||||
angularLock.y = freezeRotationY ? 0.0f : 1.0f;
|
||||
rigidBody->setAngularLockAxisFactor(angularLock);
|
||||
}
|
||||
|
||||
dirtyFlags |= 1U << FLAG_POS;
|
||||
freezeRotationY ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetFreezeRotationZ(bool freezeRotationZ) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 7;
|
||||
constexpr uint8_t FLAG_VALUE = SHUtilities::ConvertEnum(Flags::ANGULAR_Z);
|
||||
freezeRotationZ ? flags |= FLAG_VALUE : flags &= ~FLAG_VALUE;
|
||||
|
||||
if (type == Type::STATIC)
|
||||
if (rigidBody)
|
||||
{
|
||||
SHLOG_WARNING("Cannot set angular constraints of a static object {}", GetEID())
|
||||
return;
|
||||
rp3d::Vector3 angularLock = rigidBody->getAngularLockAxisFactor();
|
||||
angularLock.z = freezeRotationZ ? 0.0f : 1.0f;
|
||||
rigidBody->setAngularLockAxisFactor(angularLock);
|
||||
}
|
||||
|
||||
dirtyFlags |= 1U << FLAG_POS;
|
||||
freezeRotationZ ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetInterpolate(bool allowInterpolation) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 8;
|
||||
allowInterpolation ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||
interpolate = allowInterpolation;
|
||||
}
|
||||
|
||||
//void SHRigidBodyComponent::SetAutoMass(bool autoMass) noexcept
|
||||
//{
|
||||
// static constexpr int FLAG_POS = 9;
|
||||
// autoMass ? flags |= 1U << FLAG_POS : flags &= ~(1U << FLAG_POS);
|
||||
|
||||
// dirtyFlags |= 1U << FLAG_POS;
|
||||
//}
|
||||
|
||||
//void SHRigidBodyComponent::SetMass(float newMass) noexcept
|
||||
//{
|
||||
// static constexpr int FLAG_POS = 9;
|
||||
|
||||
// if (newMass < 0.0f)
|
||||
// return;
|
||||
|
||||
// if (type != Type::DYNAMIC)
|
||||
// {
|
||||
// SHLOG_WARNING("Cannot set mass of a non-dynamic object {}", GetEID())
|
||||
// return;
|
||||
// }
|
||||
|
||||
// dirtyFlags |= 1U << FLAG_POS;
|
||||
// mass = newMass;
|
||||
|
||||
// // Turn off automass
|
||||
// flags &= ~(1U << FLAG_POS);
|
||||
//}
|
||||
|
||||
void SHRigidBodyComponent::SetDrag(float newDrag) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 10;
|
||||
|
||||
if (type != Type::DYNAMIC)
|
||||
{
|
||||
SHLOG_WARNING("Cannot set drag of a non-dynamic object {}", GetEID())
|
||||
return;
|
||||
}
|
||||
|
||||
dirtyFlags |= 1U << FLAG_POS;
|
||||
drag = newDrag;
|
||||
|
||||
if (rigidBody)
|
||||
rigidBody->setLinearDamping(newDrag);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetAngularDrag(float newAngularDrag) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 11;
|
||||
|
||||
if (type != Type::DYNAMIC)
|
||||
{
|
||||
SHLOG_WARNING("Cannot set angular drag of a non-dynamic object {}", GetEID())
|
||||
return;
|
||||
}
|
||||
|
||||
dirtyFlags |= 1U << FLAG_POS;
|
||||
angularDrag = newAngularDrag;
|
||||
|
||||
if (rigidBody)
|
||||
rigidBody->setAngularDamping(newAngularDrag);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetLinearVelocity(const SHVec3& newLinearVelocity) noexcept
|
||||
{
|
||||
|
||||
if (type == Type::STATIC)
|
||||
{
|
||||
SHLOG_WARNING("Cannot set linear velocity of a static object {}", GetEID())
|
||||
return;
|
||||
}
|
||||
|
||||
auto* physicsObject = system->GetPhysicsObject(GetEID());
|
||||
if (!physicsObject)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to retrieve physics object of Entity {}", GetEID())
|
||||
return;
|
||||
}
|
||||
physicsObject->GetRigidBody()->setLinearVelocity(newLinearVelocity);
|
||||
if (rigidBody)
|
||||
rigidBody->setLinearVelocity(newLinearVelocity);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::SetAngularVelocity(const SHVec3& newAngularVelocity) noexcept
|
||||
{
|
||||
static constexpr int FLAG_POS = 13;
|
||||
|
||||
if (type == Type::STATIC)
|
||||
{
|
||||
SHLOG_WARNING("Cannot set angular velocity of a static object {}", GetEID())
|
||||
return;
|
||||
}
|
||||
|
||||
auto* physicsObject = system->GetPhysicsObject(GetEID());
|
||||
if (!physicsObject)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to retrieve physics object of Entity {}", GetEID())
|
||||
return;
|
||||
}
|
||||
physicsObject->GetRigidBody()->setAngularVelocity(newAngularVelocity);
|
||||
if (rigidBody)
|
||||
rigidBody->setAngularVelocity(newAngularVelocity);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -413,81 +327,67 @@ namespace SHADE
|
|||
|
||||
void SHRigidBodyComponent::OnCreate()
|
||||
{
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (!physicsSystem)
|
||||
{
|
||||
SHLOG_ERROR("Physics System does not exist to link with Physics Components!")
|
||||
return;
|
||||
}
|
||||
|
||||
system = physicsSystem;
|
||||
|
||||
// Sync with transform if one already exists
|
||||
if (auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(GetEID()); transformComponent)
|
||||
{
|
||||
position = transformComponent->GetWorldPosition();
|
||||
orientation = transformComponent->GetWorldOrientation();
|
||||
}
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::AddForce(const SHVec3& force) const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
physicsObject->GetRigidBody()->applyWorldForceAtCenterOfMass(force);
|
||||
if (rigidBody)
|
||||
rigidBody->applyWorldForceAtCenterOfMass(force);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::AddForceAtLocalPos(const SHVec3& force, const SHVec3& localPos) const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
physicsObject->GetRigidBody()->applyWorldForceAtLocalPosition(force, localPos);
|
||||
if (rigidBody)
|
||||
rigidBody->applyWorldForceAtLocalPosition(force, localPos);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::AddForceAtWorldPos(const SHVec3& force, const SHVec3& worldPos) const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
physicsObject->GetRigidBody()->applyWorldForceAtWorldPosition(force, worldPos);
|
||||
if (rigidBody)
|
||||
rigidBody->applyWorldForceAtWorldPosition(force, worldPos);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::AddRelativeForce(const SHVec3& relativeForce) const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
physicsObject->GetRigidBody()->applyLocalForceAtCenterOfMass(relativeForce);
|
||||
if (rigidBody)
|
||||
rigidBody->applyLocalForceAtCenterOfMass(relativeForce);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::AddRelativeForceAtLocalPos(const SHVec3& relativeForce, const SHVec3& localPos) const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
physicsObject->GetRigidBody()->applyLocalForceAtLocalPosition(relativeForce, localPos);
|
||||
if (rigidBody)
|
||||
rigidBody->applyLocalForceAtLocalPosition(relativeForce, localPos);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::AddRelativeForceAtWorldPos(const SHVec3& relativeForce, const SHVec3& worldPos) const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
physicsObject->GetRigidBody()->applyLocalForceAtWorldPosition(relativeForce, worldPos);
|
||||
if (rigidBody)
|
||||
rigidBody->applyLocalForceAtWorldPosition(relativeForce, worldPos);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::AddTorque(const SHVec3& torque) const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
physicsObject->GetRigidBody()->applyWorldTorque(torque);
|
||||
if (rigidBody)
|
||||
rigidBody->applyWorldTorque(torque);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::AddRelativeTorque(const SHVec3& relativeTorque) const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
physicsObject->GetRigidBody()->applyLocalTorque(relativeTorque);
|
||||
if (rigidBody)
|
||||
rigidBody->applyLocalTorque(relativeTorque);
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::ClearForces() const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
physicsObject->GetRigidBody()->resetForce();
|
||||
if (rigidBody)
|
||||
rigidBody->resetForce();
|
||||
}
|
||||
|
||||
void SHRigidBodyComponent::ClearTorque() const noexcept
|
||||
{
|
||||
if (auto* physicsObject = system->GetPhysicsObject(GetEID()); physicsObject)
|
||||
physicsObject->GetRigidBody()->resetTorque();
|
||||
if (rigidBody)
|
||||
rigidBody->resetTorque();
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
||||
|
@ -506,13 +406,11 @@ RTTR_REGISTRATION
|
|||
|
||||
registration::class_<SHRigidBodyComponent>("RigidBody Component")
|
||||
.property("Type" , &SHRigidBodyComponent::GetType , &SHRigidBodyComponent::SetType )
|
||||
//.property("Mass" , &SHRigidBodyComponent::GetMass , &SHRigidBodyComponent::SetMass )
|
||||
.property("Drag" , &SHRigidBodyComponent::GetDrag , &SHRigidBodyComponent::SetDrag )
|
||||
.property("Angular Drag" , &SHRigidBodyComponent::GetAngularDrag , &SHRigidBodyComponent::SetAngularDrag )
|
||||
.property("Use Gravity" , &SHRigidBodyComponent::IsGravityEnabled , &SHRigidBodyComponent::SetGravityEnabled )
|
||||
.property("Interpolate" , &SHRigidBodyComponent::IsInterpolating , &SHRigidBodyComponent::SetInterpolate )
|
||||
.property("Sleeping Enabled" , &SHRigidBodyComponent::IsAllowedToSleep , &SHRigidBodyComponent::SetIsAllowedToSleep)
|
||||
//.property("Auto Mass" , &SHRigidBodyComponent::GetAutoMass , &SHRigidBodyComponent::SetAutoMass )
|
||||
.property("Freeze Position X" , &SHRigidBodyComponent::GetFreezePositionX , &SHRigidBodyComponent::SetFreezePositionX )
|
||||
.property("Freeze Position Y" , &SHRigidBodyComponent::GetFreezePositionY , &SHRigidBodyComponent::SetFreezePositionY )
|
||||
.property("Freeze Position Z" , &SHRigidBodyComponent::GetFreezePositionZ , &SHRigidBodyComponent::SetFreezePositionZ )
|
||||
|
|
|
@ -17,6 +17,15 @@
|
|||
#include "Math/Vector/SHVec3.h"
|
||||
#include "Math/SHQuaternion.h"
|
||||
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
|
||||
namespace reactphysics3d
|
||||
{
|
||||
class RigidBody;
|
||||
}
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -31,7 +40,7 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHPhysicsSystem;
|
||||
friend class SHPhysicsObject;
|
||||
friend class SHPhysicsObjectManager;
|
||||
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -67,35 +76,31 @@ namespace SHADE
|
|||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] bool IsGravityEnabled () const noexcept;
|
||||
[[nodiscard]] bool IsAllowedToSleep () const noexcept;
|
||||
[[nodiscard]] bool IsInterpolating () const noexcept;
|
||||
[[nodiscard]] Type GetType () const noexcept;
|
||||
|
||||
[[nodiscard]] bool GetIsSleeping () const noexcept;
|
||||
[[nodiscard]] bool IsGravityEnabled () const noexcept;
|
||||
[[nodiscard]] bool IsAllowedToSleep () const noexcept;
|
||||
[[nodiscard]] bool IsInterpolating () const noexcept;
|
||||
[[nodiscard]] bool IsSleeping () const noexcept;
|
||||
|
||||
[[nodiscard]] Type GetType () const noexcept;
|
||||
[[nodiscard]] bool GetFreezePositionX () const noexcept;
|
||||
[[nodiscard]] bool GetFreezePositionY () const noexcept;
|
||||
[[nodiscard]] bool GetFreezePositionZ () const noexcept;
|
||||
[[nodiscard]] bool GetFreezeRotationX () const noexcept;
|
||||
[[nodiscard]] bool GetFreezeRotationY () const noexcept;
|
||||
[[nodiscard]] bool GetFreezeRotationZ () const noexcept;
|
||||
|
||||
[[nodiscard]] bool GetFreezePositionX () const noexcept;
|
||||
[[nodiscard]] bool GetFreezePositionY () const noexcept;
|
||||
[[nodiscard]] bool GetFreezePositionZ () const noexcept;
|
||||
[[nodiscard]] bool GetFreezeRotationX () const noexcept;
|
||||
[[nodiscard]] bool GetFreezeRotationY () const noexcept;
|
||||
[[nodiscard]] bool GetFreezeRotationZ () const noexcept;
|
||||
[[nodiscard]] float GetMass () const noexcept;
|
||||
[[nodiscard]] float GetDrag () const noexcept;
|
||||
[[nodiscard]] float GetAngularDrag () const noexcept;
|
||||
|
||||
//[[nodiscard]] bool GetAutoMass () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetForce () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetTorque () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetLinearVelocity () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetAngularVelocity () const noexcept;
|
||||
|
||||
[[nodiscard]] float GetMass () const noexcept;
|
||||
[[nodiscard]] float GetDrag () const noexcept;
|
||||
[[nodiscard]] float GetAngularDrag () const noexcept;
|
||||
|
||||
[[nodiscard]] SHVec3 GetForce () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetTorque () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetLinearVelocity () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetAngularVelocity () const noexcept;
|
||||
|
||||
[[nodiscard]] const SHVec3& GetPosition () const noexcept;
|
||||
[[nodiscard]] const SHQuaternion& GetOrientation () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetPosition () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
|
@ -103,8 +108,11 @@ namespace SHADE
|
|||
|
||||
void SetType (Type newType) noexcept;
|
||||
|
||||
void SetRigidBody (reactphysics3d::RigidBody* body) noexcept;
|
||||
|
||||
void SetGravityEnabled (bool enableGravity) noexcept;
|
||||
void SetIsAllowedToSleep (bool isAllowedToSleep) noexcept;
|
||||
|
||||
void SetFreezePositionX (bool freezePositionX) noexcept;
|
||||
void SetFreezePositionY (bool freezePositionY) noexcept;
|
||||
void SetFreezePositionZ (bool freezePositionZ) noexcept;
|
||||
|
@ -112,9 +120,7 @@ namespace SHADE
|
|||
void SetFreezeRotationY (bool freezeRotationY) noexcept;
|
||||
void SetFreezeRotationZ (bool freezeRotationZ) noexcept;
|
||||
void SetInterpolate (bool allowInterpolation) noexcept;
|
||||
//void SetAutoMass (bool autoMass) noexcept;
|
||||
|
||||
//void SetMass (float newMass) noexcept;
|
||||
void SetDrag (float newDrag) noexcept;
|
||||
void SetAngularDrag (float newAngularDrag) noexcept;
|
||||
|
||||
|
@ -140,29 +146,42 @@ namespace SHADE
|
|||
void ClearTorque () const noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
enum class Flags : uint8_t
|
||||
{
|
||||
GRAVITY = 0x1
|
||||
, SLEEPING = 0x2
|
||||
, LINEAR_X = 0x4
|
||||
, LINEAR_Y = 0x8
|
||||
, LINEAR_Z = 0x10
|
||||
, ANGULAR_X = 0x20
|
||||
, ANGULAR_Y = 0x40
|
||||
, ANGULAR_Z = 0x80
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
static constexpr size_t NUM_FLAGS = 8;
|
||||
static constexpr size_t NUM_DIRTY_FLAGS = 12;
|
||||
static constexpr size_t NUM_FLAGS = 8;
|
||||
|
||||
Type type;
|
||||
Type type;
|
||||
bool interpolate;
|
||||
|
||||
uint16_t flags; // 0 0 0 0 0 0 am ip aZ aY aX lZ lY lX slp g
|
||||
uint16_t dirtyFlags; // 0 0 0 0 aD d m t aZ aY aX lZ lY lX slp g
|
||||
// Used for storing serialised data
|
||||
uint8_t flags; // aZ aY aX lZ lY lX sleepEnabled gravity
|
||||
float drag;
|
||||
float angularDrag;
|
||||
|
||||
float mass;
|
||||
float drag;
|
||||
float angularDrag;
|
||||
// For interpolation
|
||||
|
||||
SHVec3 linearVelocity;
|
||||
SHVec3 angularVelocity;
|
||||
SHVec3 position;
|
||||
SHQuaternion orientation;
|
||||
|
||||
SHPhysicsSystem* system;
|
||||
|
||||
SHVec3 position;
|
||||
SHQuaternion orientation;
|
||||
reactphysics3d::RigidBody* rigidBody;
|
||||
|
||||
RTTR_ENABLE()
|
||||
};
|
||||
|
|
|
@ -1,431 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsObject.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Physics Object.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHPhysicsObject.h"
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject::SHPhysicsObject(EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept
|
||||
: entityID { eid }
|
||||
, collidersActive { true }
|
||||
, factory { physicsFactory }
|
||||
, world { physicsWorld }
|
||||
, rp3dBody { nullptr }
|
||||
{
|
||||
// Implicitly create a static body.
|
||||
|
||||
const auto* TRANSFORM = SHComponentManager::GetComponent<SHTransformComponent>(eid);
|
||||
|
||||
const rp3d::Transform RP3D_TRANSFORM { TRANSFORM->GetWorldPosition(), TRANSFORM->GetWorldOrientation() };
|
||||
|
||||
rp3dBody = world->createRigidBody(RP3D_TRANSFORM);
|
||||
rp3dBody->setType(rp3d::BodyType::STATIC);
|
||||
}
|
||||
|
||||
SHPhysicsObject::~SHPhysicsObject() noexcept
|
||||
{
|
||||
factory = nullptr;
|
||||
world = nullptr;
|
||||
rp3dBody = nullptr;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHVec3 SHPhysicsObject::GetPosition() const noexcept
|
||||
{
|
||||
return rp3dBody->getTransform().getPosition();
|
||||
}
|
||||
|
||||
SHQuaternion SHPhysicsObject::GetOrientation() const noexcept
|
||||
{
|
||||
return rp3dBody->getTransform().getOrientation();
|
||||
}
|
||||
|
||||
SHVec3 SHPhysicsObject::GetRotation() const noexcept
|
||||
{
|
||||
return SHQuaternion{ rp3dBody->getTransform().getOrientation() }.ToEuler();
|
||||
}
|
||||
|
||||
rp3d::CollisionBody* SHPhysicsObject::GetCollisionBody() const noexcept
|
||||
{
|
||||
return rp3dBody;
|
||||
}
|
||||
|
||||
rp3d::RigidBody* SHPhysicsObject::GetRigidBody() const noexcept
|
||||
{
|
||||
return rp3dBody;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsObject::SetStaticBody() const noexcept
|
||||
{
|
||||
if (!rp3dBody)
|
||||
return;
|
||||
|
||||
rp3dBody->setType(rp3d::BodyType::STATIC);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
int SHPhysicsObject::AddCollisionShape(int index)
|
||||
{
|
||||
// Get collider component
|
||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
||||
if (!colliderComponent)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to add Collision Shape to Entity {} due to Missing Collider Component!", entityID)
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto& collisionShape = colliderComponent->GetCollisionShape(index);
|
||||
switch (collisionShape.GetType())
|
||||
{
|
||||
// TODO(Diren): Add more collider shapes
|
||||
|
||||
case SHCollisionShape::Type::BOX:
|
||||
{
|
||||
addBoxShape(collisionShape);
|
||||
break;
|
||||
}
|
||||
|
||||
case SHCollisionShape::Type::SPHERE:
|
||||
{
|
||||
addSphereShape(collisionShape);
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
|
||||
auto* rp3dCollider = rp3dBody->getCollider(rp3dBody->getNbColliders() - 1);
|
||||
syncColliderProperties(collisionShape, rp3dCollider);
|
||||
|
||||
if (rp3dBody->getType() == rp3d::BodyType::DYNAMIC)
|
||||
{
|
||||
rp3dBody->updateMassPropertiesFromColliders();
|
||||
|
||||
if (auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID); rigidBodyComponent)
|
||||
rigidBodyComponent->mass = rp3dBody->getMass();
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void SHPhysicsObject::RemoveCollisionShape(int index)
|
||||
{
|
||||
const int NUM_COLLIDERS = static_cast<int>(rp3dBody->getNbColliders());
|
||||
if (NUM_COLLIDERS == 0)
|
||||
return;
|
||||
|
||||
if (index < 0 || index >= NUM_COLLIDERS)
|
||||
throw std::invalid_argument("Index out of range!");
|
||||
|
||||
auto* collider = rp3dBody->getCollider(index);
|
||||
rp3dBody->removeCollider(collider);
|
||||
|
||||
if (rp3dBody->getType() == rp3d::BodyType::DYNAMIC)
|
||||
{
|
||||
rp3dBody->updateMassPropertiesFromColliders();
|
||||
|
||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
||||
if (rigidBodyComponent)
|
||||
rigidBodyComponent->mass = rp3dBody->getMass();
|
||||
}
|
||||
}
|
||||
|
||||
void SHPhysicsObject::RemoveAllCollisionShapes() const noexcept
|
||||
{
|
||||
int numColliders = static_cast<int>(rp3dBody->getNbColliders());
|
||||
if (numColliders == 0)
|
||||
return;
|
||||
|
||||
while (numColliders - 1 >= 0)
|
||||
{
|
||||
auto* collider = rp3dBody->getCollider(numColliders - 1);
|
||||
rp3dBody->removeCollider(collider);
|
||||
|
||||
--numColliders;
|
||||
}
|
||||
}
|
||||
|
||||
void SHPhysicsObject::SyncRigidBody(SHRigidBodyComponent& component) const noexcept
|
||||
{
|
||||
// This state is synced in the pre-update routine
|
||||
if (!rp3dBody->isActive())
|
||||
return;
|
||||
|
||||
if (component.dirtyFlags == 0)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; i < SHRigidBodyComponent::NUM_DIRTY_FLAGS; ++i)
|
||||
{
|
||||
if (const bool IS_DIRTY = component.dirtyFlags & (1U << i); IS_DIRTY)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
case 0: // Gravity
|
||||
{
|
||||
const bool IS_ENABLED = component.flags & (1U << i);
|
||||
rp3dBody->enableGravity(IS_ENABLED);
|
||||
|
||||
break;
|
||||
}
|
||||
case 1: // Sleeping
|
||||
{
|
||||
const bool IS_ENABLED = component.flags & (1U << i);
|
||||
rp3dBody->setIsAllowedToSleep(IS_ENABLED);
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: // Lock Position X
|
||||
{
|
||||
const bool IS_ENABLED = component.flags & (1U << i);
|
||||
|
||||
auto positionLock = rp3dBody->getLinearLockAxisFactor();
|
||||
positionLock.x = IS_ENABLED ? 0.0f : 1.0f;
|
||||
rp3dBody->setLinearLockAxisFactor(positionLock);
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: // Lock Position Y
|
||||
{
|
||||
const bool IS_ENABLED = component.flags & (1U << i);
|
||||
|
||||
auto positionLock = rp3dBody->getLinearLockAxisFactor();
|
||||
positionLock.y = IS_ENABLED ? 0.0f : 1.0f;
|
||||
rp3dBody->setLinearLockAxisFactor(positionLock);
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: // Lock Position Z
|
||||
{
|
||||
const bool IS_ENABLED = component.flags & (1U << i);
|
||||
|
||||
auto positionLock = rp3dBody->getLinearLockAxisFactor();
|
||||
positionLock.z = IS_ENABLED ? 0.0f : 1.0f;
|
||||
rp3dBody->setLinearLockAxisFactor(positionLock);
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: // Lock Rotation X
|
||||
{
|
||||
const bool IS_ENABLED = component.flags & (1U << i);
|
||||
|
||||
auto rotationLock = rp3dBody->getAngularLockAxisFactor();
|
||||
rotationLock.x = IS_ENABLED ? 0.0f : 1.0f;
|
||||
rp3dBody->setAngularLockAxisFactor(rotationLock);
|
||||
|
||||
break;
|
||||
}
|
||||
case 6: // Lock Rotation Y
|
||||
{
|
||||
const bool IS_ENABLED = component.flags & (1U << i);
|
||||
|
||||
auto rotationLock = rp3dBody->getAngularLockAxisFactor();
|
||||
rotationLock.y = IS_ENABLED ? 0.0f : 1.0f;
|
||||
rp3dBody->setAngularLockAxisFactor(rotationLock);
|
||||
|
||||
break;
|
||||
}
|
||||
case 7: // Lock Rotation Z
|
||||
{
|
||||
const bool IS_ENABLED = component.flags & (1U << i);
|
||||
|
||||
auto rotationLock = rp3dBody->getAngularLockAxisFactor();
|
||||
rotationLock.z = IS_ENABLED ? 0.0f : 1.0f;
|
||||
rp3dBody->setAngularLockAxisFactor(rotationLock);
|
||||
|
||||
break;
|
||||
}
|
||||
case 8: // Type
|
||||
{
|
||||
rp3dBody->setType(static_cast<rp3d::BodyType>(component.type));
|
||||
|
||||
break;
|
||||
}
|
||||
case 9: // Mass
|
||||
{
|
||||
//rp3dBody->setMass(component.mass);
|
||||
|
||||
//if (component.GetAutoMass())
|
||||
//{
|
||||
// rp3dBody->updateMassPropertiesFromColliders();
|
||||
// component.mass = rp3dBody->getMass();
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// rp3dBody->setMass(component.mass);
|
||||
// rp3dBody->updateLocalCenterOfMassFromColliders();
|
||||
// rp3dBody->updateLocalInertiaTensorFromColliders();
|
||||
//}
|
||||
|
||||
break;
|
||||
}
|
||||
case 10: // Drag
|
||||
{
|
||||
rp3dBody->setLinearDamping(component.drag);
|
||||
|
||||
break;
|
||||
}
|
||||
case 11: // Angular Drag
|
||||
{
|
||||
rp3dBody->setAngularDamping(component.angularDrag);
|
||||
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component.dirtyFlags = 0;
|
||||
}
|
||||
|
||||
void SHPhysicsObject::SyncColliders(SHColliderComponent& component) const noexcept
|
||||
{
|
||||
// This state is synced in the pre-update routine
|
||||
if (!rp3dBody->isActive())
|
||||
return;
|
||||
|
||||
const int NUM_SHAPES = static_cast<int>(rp3dBody->getNbColliders());
|
||||
for (int i = 0; i < NUM_SHAPES; ++i)
|
||||
{
|
||||
auto& collisionShape = component.collisionShapes[i];
|
||||
|
||||
if (!collisionShape.dirty)
|
||||
continue;
|
||||
|
||||
switch (collisionShape.GetType())
|
||||
{
|
||||
case SHCollisionShape::Type::BOX: syncBoxShape(i, collisionShape); break;
|
||||
case SHCollisionShape::Type::SPHERE: syncSphereShape(i, collisionShape); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
auto* rp3dCollider = rp3dBody->getCollider(i);
|
||||
syncColliderProperties(collisionShape, rp3dCollider);
|
||||
|
||||
collisionShape.dirty = false;
|
||||
}
|
||||
|
||||
// Set rigidbody mass if dynamic
|
||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
||||
if (rigidBodyComponent)
|
||||
{
|
||||
// This is generally expensive, will be optimised in the future with my own engine.
|
||||
rp3dBody->updateMassPropertiesFromColliders();
|
||||
rigidBodyComponent->mass = rp3dBody->getMass();
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsObject::syncColliderProperties(const SHCollisionShape& collisionShape, rp3d::Collider* rp3dCollider) const noexcept
|
||||
{
|
||||
rp3dCollider->setIsTrigger(collisionShape.IsTrigger());
|
||||
|
||||
auto& rp3dMaterial = rp3dCollider->getMaterial();
|
||||
|
||||
rp3dMaterial.setFrictionCoefficient(collisionShape.GetFriction());
|
||||
rp3dMaterial.setBounciness(collisionShape.GetBounciness());
|
||||
rp3dMaterial.setMassDensity(collisionShape.GetDensity());
|
||||
|
||||
const unsigned short MASK_BITS = collisionShape.GetCollisionTag();
|
||||
rp3dCollider->setCollisionCategoryBits(MASK_BITS);
|
||||
rp3dCollider->setCollideWithMaskBits(MASK_BITS);
|
||||
}
|
||||
|
||||
void SHPhysicsObject::addBoxShape(const SHCollisionShape& boxShape) const noexcept
|
||||
{
|
||||
const rp3d::Transform OFFSETS
|
||||
{
|
||||
boxShape.GetPositionOffset()
|
||||
, boxShape.GetRotationOffset()
|
||||
};
|
||||
|
||||
const auto* BOX = reinterpret_cast<const SHBox*>(boxShape.GetShape());
|
||||
rp3d::BoxShape* newBox = factory->createBoxShape(BOX->GetWorldExtents());
|
||||
|
||||
rp3dBody->addCollider(newBox, OFFSETS);
|
||||
}
|
||||
|
||||
void SHPhysicsObject::syncBoxShape(int index, const SHCollisionShape& boxShape) const noexcept
|
||||
{
|
||||
const auto* BOX = reinterpret_cast<const SHBox*>(boxShape.GetShape());
|
||||
|
||||
auto* rp3dCollider = rp3dBody->getCollider(index);
|
||||
auto* rp3dBox = reinterpret_cast<rp3d::BoxShape*>(rp3dCollider->getCollisionShape());
|
||||
|
||||
const rp3d::Transform OFFSETS
|
||||
{
|
||||
boxShape.GetPositionOffset()
|
||||
, boxShape.GetRotationOffset()
|
||||
};
|
||||
|
||||
rp3dCollider->setIsTrigger(boxShape.IsTrigger());
|
||||
rp3dCollider->setLocalToBodyTransform(OFFSETS);
|
||||
|
||||
rp3dBox->setHalfExtents(BOX->GetWorldExtents());
|
||||
}
|
||||
|
||||
void SHPhysicsObject::addSphereShape(const SHCollisionShape& sphereShape) const noexcept
|
||||
{
|
||||
const rp3d::Transform OFFSETS
|
||||
{
|
||||
sphereShape.GetPositionOffset()
|
||||
, sphereShape.GetRotationOffset()
|
||||
};
|
||||
|
||||
const auto* SPHERE = reinterpret_cast<const SHSphere*>(sphereShape.GetShape());
|
||||
rp3d::SphereShape* newSphere = factory->createSphereShape(SPHERE->GetWorldRadius());
|
||||
|
||||
rp3dBody->addCollider(newSphere, OFFSETS);
|
||||
}
|
||||
|
||||
void SHPhysicsObject::syncSphereShape(int index, const SHCollisionShape& sphereShape) const noexcept
|
||||
{
|
||||
const auto* SPHERE = reinterpret_cast<const SHSphere*>(sphereShape.GetShape());
|
||||
|
||||
auto* rp3dCollider = rp3dBody->getCollider(index);
|
||||
auto* rp3dSphere = reinterpret_cast<rp3d::SphereShape*>(rp3dCollider->getCollisionShape());
|
||||
|
||||
const rp3d::Transform OFFSETS
|
||||
{
|
||||
sphereShape.GetPositionOffset()
|
||||
, sphereShape.GetRotationOffset()
|
||||
};
|
||||
|
||||
rp3dCollider->setIsTrigger(sphereShape.IsTrigger());
|
||||
rp3dCollider->setLocalToBodyTransform(OFFSETS);
|
||||
|
||||
rp3dSphere->setRadius(SPHERE->GetWorldRadius());
|
||||
}
|
||||
} // namespace SHADE
|
|
@ -1,111 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsObject.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a Physics Object.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
||||
// Project Headers
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHPhysicsObject
|
||||
{
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Friends */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHPhysicsSystem;
|
||||
friend class SHPhysicsObjectManager;
|
||||
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject (EntityID eid, rp3d::PhysicsCommon* physicsFactory, rp3d::PhysicsWorld* physicsWorld) noexcept;
|
||||
SHPhysicsObject (const SHPhysicsObject& rhs) noexcept = default;
|
||||
SHPhysicsObject (SHPhysicsObject&& rhs) noexcept = default;
|
||||
virtual ~SHPhysicsObject () noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject& operator=(const SHPhysicsObject& rhs) noexcept = default;
|
||||
SHPhysicsObject& operator=(SHPhysicsObject&& rhs) noexcept = default;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] SHVec3 GetPosition () const noexcept;
|
||||
[[nodiscard]] SHQuaternion GetOrientation () const noexcept;
|
||||
[[nodiscard]] SHVec3 GetRotation () const noexcept;
|
||||
|
||||
[[nodiscard]] rp3d::CollisionBody* GetCollisionBody () const noexcept;
|
||||
[[nodiscard]] rp3d::RigidBody* GetRigidBody () const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetStaticBody () const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
int AddCollisionShape (int index);
|
||||
void RemoveCollisionShape (int index);
|
||||
void RemoveAllCollisionShapes () const noexcept;
|
||||
|
||||
void SyncRigidBody (SHRigidBodyComponent& component) const noexcept;
|
||||
void SyncColliders (SHColliderComponent& component) const noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
EntityID entityID;
|
||||
bool collidersActive; // Only used to sync with SHADE components
|
||||
|
||||
rp3d::PhysicsCommon* factory;
|
||||
rp3d::PhysicsWorld* world;
|
||||
|
||||
rp3d::RigidBody* rp3dBody;
|
||||
rp3d::Transform prevTransform; // Cached transform for interpolation
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void syncColliderProperties (const SHCollisionShape& collisionShape, rp3d::Collider* rp3dCollider) const noexcept;
|
||||
|
||||
// Box Shapes
|
||||
|
||||
void addBoxShape (const SHCollisionShape& boxShape) const noexcept;
|
||||
void syncBoxShape (int index, const SHCollisionShape& boxShape) const noexcept;
|
||||
|
||||
// Sphere Shapes
|
||||
|
||||
void addSphereShape (const SHCollisionShape& sphereShape) const noexcept;
|
||||
void syncSphereShape (int index, const SHCollisionShape& sphereShape) const noexcept;
|
||||
};
|
||||
} // namespace SHADE
|
|
@ -1,309 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsObjectManager.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Physics Object Manager.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHPhysicsObjectManager.h"
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "Tools/Utilities/SHUtilities.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Data Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObjectManager::CommandFunctionPtr SHPhysicsObjectManager::componentFunc[3][2]
|
||||
{
|
||||
addRigidBody , addCollider , addCollisionShape
|
||||
, removeRigidBody , removeCollider , removeCollisionShape
|
||||
};
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsObjectManager::SetFactory(rp3d::PhysicsCommon& physicsFactory) noexcept
|
||||
{
|
||||
factory = &physicsFactory;
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::SetWorld(rp3d::PhysicsWorld* physicsWorld) noexcept
|
||||
{
|
||||
world = physicsWorld;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject* SHPhysicsObjectManager::GetPhysicsObject(EntityID eid) noexcept
|
||||
{
|
||||
const auto it = physicsObjects.find(eid);
|
||||
if (it == physicsObjects.end())
|
||||
return nullptr;
|
||||
|
||||
return &it->second;
|
||||
}
|
||||
|
||||
const SHPhysicsObjectManager::PhysicsObjectEntityMap SHPhysicsObjectManager::GetPhysicsObjects() const noexcept
|
||||
{
|
||||
return physicsObjects;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsObjectManager::AddRigidBody(EntityID eid) noexcept
|
||||
{
|
||||
const QueueCommand NEW_QUEUE_COMMAND
|
||||
{
|
||||
.eid = eid
|
||||
, .command = QueueCommand::Command::ADD
|
||||
, .component = PhysicsComponents::RIGID_BODY
|
||||
};
|
||||
|
||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::AddCollider(EntityID eid) noexcept
|
||||
{
|
||||
const QueueCommand NEW_QUEUE_COMMAND
|
||||
{
|
||||
.eid = eid
|
||||
, .command = QueueCommand::Command::ADD
|
||||
, .component = PhysicsComponents::COLLIDER
|
||||
};
|
||||
|
||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::AddCollisionShape(EntityID eid, int shapeIndex) noexcept
|
||||
{
|
||||
const QueueCommand NEW_QUEUE_COMMAND
|
||||
{
|
||||
.eid = eid
|
||||
, .command = QueueCommand::Command::ADD
|
||||
, .component = PhysicsComponents::COLLISION_SHAPE
|
||||
, .shapeIndex = shapeIndex
|
||||
};
|
||||
|
||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::RemoveRigidBody(EntityID eid) noexcept
|
||||
{
|
||||
const QueueCommand NEW_QUEUE_COMMAND
|
||||
{
|
||||
.eid = eid
|
||||
, .command = QueueCommand::Command::REMOVE
|
||||
, .component = PhysicsComponents::RIGID_BODY
|
||||
};
|
||||
|
||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::RemoveCollider(EntityID eid) noexcept
|
||||
{
|
||||
const QueueCommand NEW_QUEUE_COMMAND
|
||||
{
|
||||
.eid = eid
|
||||
, .command = QueueCommand::Command::REMOVE
|
||||
, .component = PhysicsComponents::COLLIDER
|
||||
};
|
||||
|
||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::RemoveCollisionShape(EntityID eid, int shapeIndex) noexcept
|
||||
{
|
||||
const QueueCommand NEW_QUEUE_COMMAND
|
||||
{
|
||||
.eid = eid
|
||||
, .command = QueueCommand::Command::REMOVE
|
||||
, .component = PhysicsComponents::COLLISION_SHAPE
|
||||
, .shapeIndex = shapeIndex
|
||||
};
|
||||
|
||||
commandQueue.push(NEW_QUEUE_COMMAND);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::UpdateCommands()
|
||||
{
|
||||
if (commandQueue.empty())
|
||||
return;
|
||||
|
||||
while (!commandQueue.empty())
|
||||
{
|
||||
const QueueCommand COMMAND = commandQueue.front();
|
||||
commandQueue.pop();
|
||||
|
||||
// Check validity of command
|
||||
if (COMMAND.command == QueueCommand::Command::INVALID || COMMAND.component == PhysicsComponents::INVALID)
|
||||
continue;
|
||||
|
||||
// Get physics components
|
||||
const PhysicsComponentGroup COMPONENT_GROUP
|
||||
{
|
||||
.eid = COMMAND.eid
|
||||
, .rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(COMMAND.eid)
|
||||
, .colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(COMMAND.eid)
|
||||
};
|
||||
|
||||
// Delete any object that is missing both components
|
||||
// We infer that a remove command has been pushed for these, but we will ignore those if both components have already been removed.
|
||||
if (!COMPONENT_GROUP.rigidBodyComponent && !COMPONENT_GROUP.colliderComponent)
|
||||
{
|
||||
destroyPhysicsObject(COMMAND.eid);
|
||||
wakeAllObjects();
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find the physics Object. If none found and attempting to add, create an object.
|
||||
SHPhysicsObject* physicsObject = GetPhysicsObject(COMMAND.eid);
|
||||
if (!physicsObject && COMMAND.command == QueueCommand::Command::ADD)
|
||||
physicsObject = createPhysicsObject(COMMAND.eid);
|
||||
|
||||
componentFunc[SHUtilities::ConvertEnum(COMMAND.command)][SHUtilities::ConvertEnum(COMMAND.component)](COMMAND, physicsObject, COMPONENT_GROUP);
|
||||
|
||||
// If any removal was done, wake all objects
|
||||
if (COMMAND.command == QueueCommand::Command::REMOVE)
|
||||
wakeAllObjects();
|
||||
}
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::RemoveAllObjects()
|
||||
{
|
||||
// Destroy all objects and clear
|
||||
for (auto& physicsObject : physicsObjects | std::views::values)
|
||||
{
|
||||
world->destroyRigidBody(physicsObject.GetRigidBody());
|
||||
physicsObject.rp3dBody = nullptr;
|
||||
}
|
||||
|
||||
physicsObjects.clear();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject* SHPhysicsObjectManager::createPhysicsObject(EntityID eid) noexcept
|
||||
{
|
||||
// Force transforms to sync
|
||||
SHVec3 worldPos = SHVec3::Zero;
|
||||
SHQuaternion worldRot = SHQuaternion::Identity;
|
||||
|
||||
const SHTransformComponent* TRANSFORM = nullptr;
|
||||
if (SHEntityManager::IsValidEID(eid))
|
||||
TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||
|
||||
if (TRANSFORM)
|
||||
{
|
||||
worldPos = TRANSFORM->GetWorldPosition();
|
||||
worldRot = TRANSFORM->GetWorldOrientation();
|
||||
}
|
||||
|
||||
const rp3d::Transform RP3D_TRANSFORM{ worldPos, worldRot };
|
||||
|
||||
auto& newPhysicsObject = physicsObjects.emplace(eid, SHPhysicsObject{ eid, factory, world }).first->second;
|
||||
newPhysicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM);
|
||||
newPhysicsObject.prevTransform = RP3D_TRANSFORM;
|
||||
|
||||
return &newPhysicsObject;
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::destroyPhysicsObject(EntityID eid) noexcept
|
||||
{
|
||||
const auto ITER = physicsObjects.find(eid);
|
||||
if (ITER == physicsObjects.end())
|
||||
{
|
||||
// Assume the object has already been successfully destroyed
|
||||
return;
|
||||
}
|
||||
|
||||
world->destroyRigidBody(ITER->second.GetRigidBody());
|
||||
ITER->second.rp3dBody = nullptr;
|
||||
|
||||
physicsObjects.erase(eid);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::addRigidBody(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup)
|
||||
{
|
||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to add body!")
|
||||
|
||||
if (!componentGroup.rigidBodyComponent)
|
||||
{
|
||||
SHLOG_ERROR("Entity {} is missing a Rigidbody Component. Unable to update physics object!", componentGroup.eid)
|
||||
return;
|
||||
}
|
||||
|
||||
// A static rigid body is implicitly created on creation of a physics object.
|
||||
// Nothing is needed here.
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::addCollider(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup)
|
||||
{
|
||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to add collider!")
|
||||
|
||||
if (!componentGroup.colliderComponent)
|
||||
{
|
||||
SHLOG_ERROR("Entity {} is missing a Rigidbody Component. Unable to update physics object!", componentGroup.eid)
|
||||
return;
|
||||
}
|
||||
|
||||
//const int NUM_SHAPES = static_cast<int>(componentGroup.colliderComponent->GetCollisionShapes().size());
|
||||
//for (int i = 0; i < NUM_SHAPES; ++i)
|
||||
// physicsObject->AddCollisionShape(i);
|
||||
|
||||
physicsObject->SyncColliders(*componentGroup.colliderComponent);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::removeRigidBody(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup)
|
||||
{
|
||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove body!")
|
||||
|
||||
if (componentGroup.colliderComponent)
|
||||
physicsObject->SetStaticBody();
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::removeCollider(const QueueCommand&, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
||||
{
|
||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collider!")
|
||||
|
||||
physicsObject->RemoveAllCollisionShapes();
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::addCollisionShape(const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
||||
{
|
||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to add collision shape!")
|
||||
|
||||
physicsObject->AddCollisionShape(command.shapeIndex);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::removeCollisionShape(const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup&)
|
||||
{
|
||||
SHASSERT(physicsObject != nullptr, "Valid physics object required to remove collision shape!")
|
||||
|
||||
physicsObject->RemoveCollisionShape(command.shapeIndex);
|
||||
}
|
||||
|
||||
void SHPhysicsObjectManager::wakeAllObjects() noexcept
|
||||
{
|
||||
for (auto& physicsObject : physicsObjects | std::views::values)
|
||||
physicsObject.GetRigidBody()->setIsSleeping(false);
|
||||
}
|
||||
|
||||
|
||||
} // namespace SHADE
|
|
@ -1,181 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsObjectManager.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a Physics Object Manager.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <queue>
|
||||
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
||||
// Project Headers
|
||||
#include "SHPhysicsObject.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHPhysicsObjectManager
|
||||
{
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Friends */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHPhysicsSystem;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
using PhysicsObjectEntityMap = std::unordered_map<EntityID, SHPhysicsObject>;
|
||||
|
||||
public:
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
enum class PhysicsComponents
|
||||
{
|
||||
RIGID_BODY
|
||||
, COLLIDER
|
||||
, COLLISION_SHAPE
|
||||
|
||||
, TOTAL
|
||||
, INVALID = -1
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObjectManager () = default;
|
||||
~SHPhysicsObjectManager () = default;
|
||||
|
||||
SHPhysicsObjectManager (const SHPhysicsObjectManager&) = delete;
|
||||
SHPhysicsObjectManager (SHPhysicsObjectManager&&) = delete;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Operator Overloads */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObjectManager& operator=(const SHPhysicsObjectManager&) = delete;
|
||||
SHPhysicsObjectManager& operator=(SHPhysicsObjectManager&&) = delete;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] SHPhysicsObject* GetPhysicsObject (EntityID eid) noexcept;
|
||||
[[nodiscard]] const PhysicsObjectEntityMap GetPhysicsObjects () const noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetFactory (rp3d::PhysicsCommon& physicsFactory) noexcept;
|
||||
void SetWorld (rp3d::PhysicsWorld* physicsWorld) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void AddRigidBody (EntityID eid) noexcept;
|
||||
void AddCollider (EntityID eid) noexcept;
|
||||
void AddCollisionShape (EntityID eid, int shapeIndex) noexcept;
|
||||
|
||||
void RemoveRigidBody (EntityID eid) noexcept;
|
||||
void RemoveCollider (EntityID eid) noexcept;
|
||||
void RemoveCollisionShape (EntityID eid, int shapeIndex) noexcept;
|
||||
|
||||
void UpdateCommands ();
|
||||
void RemoveAllObjects ();
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
struct QueueCommand
|
||||
{
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
enum class Command
|
||||
{
|
||||
ADD
|
||||
, REMOVE
|
||||
|
||||
, INVALID = -1
|
||||
};
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
EntityID eid = MAX_EID;
|
||||
Command command = Command::INVALID;
|
||||
PhysicsComponents component = PhysicsComponents::INVALID;
|
||||
int shapeIndex = -1; // Only used when adding & removing collision shapes
|
||||
};
|
||||
|
||||
struct PhysicsComponentGroup
|
||||
{
|
||||
public:
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
EntityID eid = MAX_EID;
|
||||
SHRigidBodyComponent* rigidBodyComponent = nullptr;
|
||||
SHColliderComponent* colliderComponent = nullptr;
|
||||
};
|
||||
|
||||
using CommandFunctionPtr = void(*)(const QueueCommand&, SHPhysicsObject*, const PhysicsComponentGroup&);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
static CommandFunctionPtr componentFunc[3][2]; // 3 components, 2 commands
|
||||
|
||||
rp3d::PhysicsCommon* factory = nullptr;
|
||||
rp3d::PhysicsWorld* world = nullptr;
|
||||
|
||||
PhysicsObjectEntityMap physicsObjects;
|
||||
std::queue<QueueCommand> commandQueue;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsObject* createPhysicsObject (EntityID eid) noexcept;
|
||||
void destroyPhysicsObject (EntityID eid) noexcept;
|
||||
|
||||
void wakeAllObjects () noexcept;
|
||||
|
||||
static void addRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||
static void addCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||
static void removeRigidBody (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||
static void removeCollider (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||
|
||||
static void addCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||
static void removeCollisionShape (const QueueCommand& command, SHPhysicsObject* physicsObject, const PhysicsComponentGroup& componentGroup);
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace SHADE
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "Physics/PhysicsObject/SHPhysicsObject.h"
|
||||
#include "Physics/Interface/PhysicsObject/SHPhysicsObject.h"
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
|
||||
|
@ -25,9 +25,9 @@
|
|||
|
||||
uint32_t matchColliders(const SHADE::SHPhysicsObject&physicsObject, const rp3d::Entity colliderID)
|
||||
{
|
||||
for (uint32_t i = 0; i < physicsObject.GetCollisionBody()->getNbColliders(); ++i)
|
||||
for (uint32_t i = 0; i < physicsObject.body->getNbColliders(); ++i)
|
||||
{
|
||||
const auto* collider = physicsObject.GetCollisionBody()->getCollider(i);
|
||||
const auto* collider = physicsObject.body->getCollider(i);
|
||||
if (collider->getEntity() == colliderID)
|
||||
return i;
|
||||
}
|
||||
|
@ -178,10 +178,10 @@ namespace SHADE
|
|||
bool matched[2] = { false, false };
|
||||
|
||||
|
||||
for (auto& [entityID, physicsObject] : system->GetPhysicsObjects())
|
||||
for (auto& [entityID, physicsObject] : system->objectManager.GetPhysicsObjects())
|
||||
{
|
||||
// Match body 1
|
||||
if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.GetCollisionBody()->getEntity() == body1)
|
||||
if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.body->getEntity() == body1)
|
||||
{
|
||||
cInfo.ids[SHCollisionInfo::ENTITY_A] = entityID;
|
||||
cInfo.ids[SHCollisionInfo::COLLIDER_A] = matchColliders(physicsObject, collider1);
|
||||
|
@ -190,7 +190,7 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Match body 2
|
||||
if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.GetCollisionBody()->getEntity() == body2)
|
||||
if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.body->getEntity() == body2)
|
||||
{
|
||||
cInfo.ids[SHCollisionInfo::ENTITY_B] = entityID;
|
||||
cInfo.ids[SHCollisionInfo::COLLIDER_B] = matchColliders(physicsObject, collider2);
|
||||
|
@ -222,10 +222,10 @@ namespace SHADE
|
|||
bool matched[2] = { false, false };
|
||||
|
||||
|
||||
for (auto& [entityID, physicsObject] : system->GetPhysicsObjects())
|
||||
for (auto& [entityID, physicsObject] : system->objectManager.GetPhysicsObjects())
|
||||
{
|
||||
// Match body 1
|
||||
if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.GetCollisionBody()->getEntity() == body1)
|
||||
if (matched[SHCollisionInfo::ENTITY_A] == false && physicsObject.body->getEntity() == body1)
|
||||
{
|
||||
cInfo.ids[SHCollisionInfo::ENTITY_A] = entityID;
|
||||
cInfo.ids[SHCollisionInfo::COLLIDER_A] = matchColliders(physicsObject, collider1);
|
||||
|
@ -234,7 +234,7 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Match body 2
|
||||
if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.GetCollisionBody()->getEntity() == body2)
|
||||
if (matched[SHCollisionInfo::ENTITY_B] == false && physicsObject.body->getEntity() == body2)
|
||||
{
|
||||
cInfo.ids[SHCollisionInfo::ENTITY_B] = entityID;
|
||||
cInfo.ids[SHCollisionInfo::COLLIDER_B] = matchColliders(physicsObject, collider2);
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
// Project Headers
|
||||
#include "SH_API.h"
|
||||
#include "SHCollisionInfo.h"
|
||||
#include "Physics/Collision/SHCollisionInfo.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
|
@ -13,8 +13,7 @@
|
|||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
||||
// Project Headers
|
||||
#include "Math/SHMath.h"
|
||||
#include "SH_API.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
|
@ -0,0 +1,132 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsRaycaster.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for a Physics Raycaster.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHRaycaster.h"
|
||||
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
|
||||
/*
|
||||
* TODO(DIREN):
|
||||
* Once the physics engine has been rebuilt, this whole implementation should change
|
||||
* and just call PhysicsWorld.Raycast etc.
|
||||
*
|
||||
* SHRaycastResult can be converted to a bool when necessary.
|
||||
*/
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHRaycaster::SHRaycaster() noexcept
|
||||
: system { nullptr }
|
||||
, world { nullptr }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHRaycaster::BindToSystem(SHPhysicsSystem* physicsSystem) noexcept
|
||||
{
|
||||
system = physicsSystem;
|
||||
}
|
||||
|
||||
void SHRaycaster::BindToWorld(rp3d::PhysicsWorld* physicsWorld) noexcept
|
||||
{
|
||||
world = physicsWorld;
|
||||
}
|
||||
|
||||
const SHRaycaster::RaycastResults& SHRaycaster::Raycast(const RaycastInfo& info) noexcept
|
||||
{
|
||||
results.clear();
|
||||
currentInfo = info;
|
||||
|
||||
SHASSERT(world, "Physics World missing link with Raycaster!")
|
||||
|
||||
// Clamp distance to 2km
|
||||
const float DISTANCE = std::clamp(info.distance, 0.0f, SHRay::MAX_RAYCAST_DIST);
|
||||
|
||||
const rp3d::Ray RP3D_RAY = { info.ray.position, info.ray.position + info.ray.direction * DISTANCE };
|
||||
world->raycast(RP3D_RAY, this, info.layers);
|
||||
|
||||
// Reset
|
||||
currentInfo.reset();
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
rp3d::decimal SHRaycaster::notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo)
|
||||
{
|
||||
SHASSERT(system, "Physics System unlinked with Raycaster!")
|
||||
|
||||
SHPhysicsRaycastResult result;
|
||||
|
||||
// Compare body IDs to find the matching physics object
|
||||
const auto HIT_BODY_EID = raycastInfo.body->getEntity();
|
||||
|
||||
for (const auto& [entityID, physicsObject] : system->objectManager.GetPhysicsObjects())
|
||||
{
|
||||
// Match rp3d bodies
|
||||
if (physicsObject.body->getEntity() != HIT_BODY_EID)
|
||||
continue;
|
||||
|
||||
// Skip ignored entity
|
||||
if (currentInfo->colliderEntityID.has_value())
|
||||
if (entityID == currentInfo->colliderEntityID)
|
||||
return 1.0f;
|
||||
|
||||
result.entityHit = entityID;
|
||||
|
||||
// Find collider index
|
||||
if (const int INDEX = findColliderIndex(physicsObject.body, raycastInfo.collider->getEntity()); INDEX > -1)
|
||||
{
|
||||
result.shapeIndex = INDEX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.hit = true;
|
||||
result.position = raycastInfo.worldPoint;
|
||||
result.normal = raycastInfo.worldNormal;
|
||||
result.distance = SHVec3::Distance(currentInfo->ray.position, result.position);
|
||||
result.angle = SHVec3::Angle(currentInfo->ray.position, result.position);
|
||||
|
||||
results.emplace_back(result);
|
||||
|
||||
if (currentInfo->continuous)
|
||||
return 1.0f;
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
int SHRaycaster::findColliderIndex(const rp3d::CollisionBody* rp3dBody, rp3d::Entity rp3dColliderEID) noexcept
|
||||
{
|
||||
const int NUM_COLLISION_SHAPES = static_cast<int>(rp3dBody->getNbColliders());
|
||||
for (int i = 0; i < NUM_COLLISION_SHAPES; ++i)
|
||||
{
|
||||
const auto COLLIDER_EID = rp3dBody->getCollider(i)->getEntity();
|
||||
if (COLLIDER_EID == rp3dColliderEID)
|
||||
return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,133 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsRaycaster.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Interface for a Physics Raycaster.
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
||||
// Project Headers
|
||||
#include "Math/SHRay.h"
|
||||
#include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h"
|
||||
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
|
||||
#include "Physics/Collision/SHPhysicsRaycastResult.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declarations */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SHPhysicsSystem;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API SHRaycaster : public reactphysics3d::RaycastCallback
|
||||
{
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
using RaycastResults = std::vector<SHPhysicsRaycastResult>;
|
||||
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
struct RaycastInfo
|
||||
{
|
||||
private:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Friends */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHRaycaster;
|
||||
|
||||
public:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
bool continuous = false;
|
||||
uint16_t layers = static_cast<uint16_t>(SHCollisionTag::Layer::ALL);
|
||||
float distance = std::numeric_limits<float>::infinity();
|
||||
SHRay ray;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Sets the collider ID for the raycast. Setting this specifies that the ray
|
||||
* should ignore this collider.
|
||||
* @param eid
|
||||
* The entity ID of the collider.
|
||||
*/
|
||||
void SetColliderID(EntityID eid) noexcept { colliderEntityID = eid; }
|
||||
|
||||
private:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
std::optional<EntityID> colliderEntityID;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHRaycaster() noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void BindToSystem (SHPhysicsSystem* physicsSystem) noexcept;
|
||||
void BindToWorld (rp3d::PhysicsWorld* physicsWorld) noexcept;
|
||||
|
||||
rp3d::decimal notifyRaycastHit(const rp3d::RaycastInfo& raycastInfo) override;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Casts a ray into the physics world.
|
||||
* @param info
|
||||
* Contains the information for the raycast.
|
||||
* @return
|
||||
* A container of the objects hit by the ray. If nothing was hit, the container
|
||||
* will be empty.
|
||||
*/
|
||||
[[nodiscard]] const RaycastResults& Raycast(const RaycastInfo& info) noexcept;
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsSystem* system;
|
||||
rp3d::PhysicsWorld* world;
|
||||
RaycastResults results; // Holds the temporary result after casting into the world
|
||||
std::optional<RaycastInfo> currentInfo; // Hold the state of the current raycast.
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
static int findColliderIndex (const rp3d::CollisionBody* rp3dBody, rp3d::Entity rp3dColliderEID) noexcept;
|
||||
};
|
||||
|
||||
|
||||
} // namespace SHADE
|
|
@ -11,8 +11,7 @@
|
|||
#pragma once
|
||||
|
||||
// Project Headers
|
||||
#include "Interface/SHCollisionShape.h"
|
||||
|
||||
#include "Collision/Shapes/SHCollisionShape.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -28,9 +27,16 @@ namespace SHADE
|
|||
};
|
||||
|
||||
struct SHPhysicsColliderRemovedEvent
|
||||
{
|
||||
EntityID entityID;
|
||||
SHCollisionShape::Type colliderType;
|
||||
int colliderIndex;
|
||||
};
|
||||
|
||||
struct SHColliderOnDebugDrawEvent
|
||||
{
|
||||
EntityID entityID;
|
||||
int colliderIndex;
|
||||
bool debugDrawState;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsDebugDrawRutine.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for the Physics Debut Draw Routine
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "Physics/System/SHPhysicsDebugDrawSystem.h"
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
#include "Tools/Utilities/SHUtilities.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsDebugDrawSystem::PhysicsDebugDraw::PhysicsDebugDraw()
|
||||
: SHSystemRoutine { "Physics Debug-Draw", true }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsDebugDrawSystem::PhysicsDebugDraw::Execute(double) noexcept
|
||||
{
|
||||
auto* physicsDebugDrawSystem = reinterpret_cast<SHPhysicsDebugDrawSystem*>(GetSystem());
|
||||
|
||||
if (!physicsDebugDrawSystem->IsDebugDrawActive())
|
||||
return;
|
||||
|
||||
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
|
||||
|
||||
const bool DRAW_COLLIDERS = physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::COLLIDERS);
|
||||
const bool DRAW_CONTACTS = physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::CONTACTS);
|
||||
const bool DRAW_RAYCASTS = physicsDebugDrawSystem->GetFlagState(DebugDrawFlags::RAYCASTS);
|
||||
\
|
||||
// If draw all colliders is active, get all colliders from the dense set and draw.
|
||||
// Else we check if any colliders have been flagged for drawing.
|
||||
if (DRAW_COLLIDERS)
|
||||
{
|
||||
const auto& COLLIDER_COMPONENT_DENSE = SHComponentManager::GetDense<SHColliderComponent>();
|
||||
for (const auto& COLLIDER_COMPONENT : COLLIDER_COMPONENT_DENSE)
|
||||
drawCollider(debugDrawSystem, COLLIDER_COMPONENT);
|
||||
}
|
||||
else if (!physicsDebugDrawSystem->collidersToDraw.empty())
|
||||
{
|
||||
for (const auto EID : physicsDebugDrawSystem->collidersToDraw)
|
||||
drawCollider(debugDrawSystem, *SHComponentManager::GetComponent<SHColliderComponent>(EID));
|
||||
}
|
||||
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (!physicsSystem)
|
||||
return;
|
||||
|
||||
if (DRAW_RAYCASTS)
|
||||
{
|
||||
const SHColour& RAY_COLOUR = physicsDebugDrawSystem->DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::RAYCAST)];
|
||||
|
||||
const auto& RAYS = physicsSystem->raycastHits;
|
||||
for (const auto& hit : RAYS)
|
||||
debugDrawSystem->DrawLine(hit.start, hit.end, RAY_COLOUR, true);
|
||||
|
||||
// Clear rays for the physics system
|
||||
physicsSystem->raycastHits.clear();
|
||||
}
|
||||
|
||||
rp3d::DebugRenderer* rp3dRenderer = nullptr;
|
||||
if (physicsSystem->worldState.world)
|
||||
rp3dRenderer = &physicsSystem->worldState.world->getDebugRenderer();
|
||||
|
||||
// No world exists, nothing else to be drawn
|
||||
if (!rp3dRenderer)
|
||||
return;
|
||||
|
||||
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, DRAW_CONTACTS);
|
||||
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, DRAW_CONTACTS);
|
||||
|
||||
if (DRAW_CONTACTS)
|
||||
{
|
||||
const SHColour& CONTACT_COLOUR = physicsDebugDrawSystem->DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::CONTACT)];
|
||||
|
||||
const int NUM_TRIS = static_cast<int>(rp3dRenderer->getNbTriangles());
|
||||
if (NUM_TRIS == 0) // No contact points
|
||||
return;
|
||||
|
||||
// Draw contacts
|
||||
const auto& TRI_ARRAY = rp3dRenderer->getTrianglesArray();
|
||||
for (int i = 0; i < NUM_TRIS; ++i)
|
||||
debugDrawSystem->DrawTri(TRI_ARRAY[i].point1, TRI_ARRAY[i].point2, TRI_ARRAY[i].point3, CONTACT_COLOUR, true);
|
||||
|
||||
// Draw normals
|
||||
const int NUM_LINES = static_cast<int>(rp3dRenderer->getNbLines());
|
||||
|
||||
const auto& LINE_ARRAY = rp3dRenderer->getLinesArray();
|
||||
for (int i = 0; i < NUM_LINES; ++i)
|
||||
debugDrawSystem->DrawLine(LINE_ARRAY[i].point1, LINE_ARRAY[i].point2, CONTACT_COLOUR, true);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,120 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsPostUpdateRoutine.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for the Physics Post-Update Routine
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsSystem::PhysicsPostUpdate::PhysicsPostUpdate()
|
||||
: SHSystemRoutine { "Physics Post-Update", false }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept
|
||||
{
|
||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||
|
||||
if (scriptingSystem == nullptr)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
|
||||
}
|
||||
|
||||
const float FACTOR = static_cast<float>(physicsSystem->interpolationFactor);
|
||||
|
||||
// Interpolate transforms for rendering.
|
||||
// Only rigid bodies can move due to physics, so we run through the rigid body component dense set.
|
||||
if (physicsSystem->worldUpdated)
|
||||
{
|
||||
for (auto& [entityID, physicsObject] : physicsSystem->objectManager.GetPhysicsObjects())
|
||||
{
|
||||
// Skip missing transforms
|
||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
||||
if (!transformComponent)
|
||||
continue;
|
||||
|
||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
||||
|
||||
// Skip invalid bodies (Should not occur)
|
||||
if (!rigidBodyComponent || !rigidBodyComponent->rigidBody)
|
||||
continue;
|
||||
|
||||
// Skip inactive bodies
|
||||
const bool IS_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(entityID);
|
||||
if (!IS_ACTIVE || rigidBodyComponent->type == SHRigidBodyComponent::Type::STATIC)
|
||||
continue;
|
||||
|
||||
const rp3d::Transform& CURRENT_TF = physicsObject.body->getTransform();
|
||||
|
||||
if (rigidBodyComponent->IsInterpolating())
|
||||
{
|
||||
const rp3d::Transform PREV_TF
|
||||
{
|
||||
rigidBodyComponent->position
|
||||
, rigidBodyComponent->orientation
|
||||
};
|
||||
|
||||
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(FACTOR));
|
||||
|
||||
const SHVec3 RENDER_POSITION = INTERPOLATED_TF.getPosition();
|
||||
const SHQuaternion RENDER_ORIENTATION = INTERPOLATED_TF.getOrientation();
|
||||
|
||||
transformComponent->SetWorldPosition(RENDER_POSITION);
|
||||
transformComponent->SetWorldOrientation(RENDER_ORIENTATION);
|
||||
}
|
||||
else
|
||||
{
|
||||
transformComponent->SetWorldPosition(CURRENT_TF.getPosition());
|
||||
transformComponent->SetWorldOrientation(CURRENT_TF.getOrientation());
|
||||
}
|
||||
|
||||
rigidBodyComponent->position = CURRENT_TF.getPosition();
|
||||
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
|
||||
|
||||
// Set colliders transform if exists
|
||||
if (auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID); colliderComponent)
|
||||
{
|
||||
colliderComponent->transform.position = CURRENT_TF.getPosition();
|
||||
colliderComponent->transform.orientation = CURRENT_TF.getOrientation();
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: Test if the scene graph transforms abides by setting world position. Collisions will ignore the scene graph hierarchy.
|
||||
*/
|
||||
}
|
||||
|
||||
// Since this function never runs when editor in not in play, execute the function anyway
|
||||
physicsSystem->collisionListener.CleanContainers();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Collision & Trigger messages
|
||||
if (scriptingSystem != nullptr)
|
||||
scriptingSystem->ExecuteCollisionFunctions();
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,107 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsPreUpdateRoutine.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for the Physics Pre-Update Routine
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate()
|
||||
: SHSystemRoutine { "Physics Pre-Update", true }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
|
||||
{
|
||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||
|
||||
// Update colliders since collision tag has changed
|
||||
const bool UPDATE_COLLISION_TAGS = SHCollisionTagMatrix::IsDirty();
|
||||
|
||||
// Get all physics objects & sync transforms
|
||||
auto& physicsObjects = physicsSystem->objectManager.GetPhysicsObjects();
|
||||
for (auto& [entityID, physicsObject] : physicsObjects)
|
||||
{
|
||||
const auto* TRANSFORM_COMPONENT = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
||||
// Assume transform is always active
|
||||
const bool UPDATE_TRANSFORM = TRANSFORM_COMPONENT && TRANSFORM_COMPONENT->HasChanged();
|
||||
|
||||
// We assume that all engine components and physics object components have been successfully linked
|
||||
|
||||
if (!physicsObject.body)
|
||||
continue;
|
||||
|
||||
auto* shadeBody = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
||||
auto* shadeCollider = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
||||
|
||||
if (UPDATE_TRANSFORM)
|
||||
{
|
||||
// Set body transform
|
||||
const SHVec3& WORLD_POS = TRANSFORM_COMPONENT->GetWorldPosition();
|
||||
const SHQuaternion& WORLD_ROT = TRANSFORM_COMPONENT->GetWorldOrientation();
|
||||
|
||||
const rp3d::Transform NEW_TRANSFORM{ WORLD_POS, WORLD_ROT };
|
||||
physicsObject.body->setTransform(NEW_TRANSFORM);
|
||||
|
||||
// Sync rigid body active states if one exists
|
||||
if (shadeBody)
|
||||
{
|
||||
const bool SHADE_BODY_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(entityID);
|
||||
const bool RP3D_BODY_ACTIVE = physicsObject.body->isActive();
|
||||
|
||||
if (SHADE_BODY_ACTIVE != RP3D_BODY_ACTIVE)
|
||||
physicsObject.body->setIsActive(SHADE_BODY_ACTIVE);
|
||||
|
||||
shadeBody->position = WORLD_POS;
|
||||
shadeBody->orientation = WORLD_ROT;
|
||||
}
|
||||
|
||||
// Sync collider active states if one exists
|
||||
if (shadeCollider)
|
||||
{
|
||||
const bool SHADE_COLLIDER_ACTIVE = SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(entityID);
|
||||
const bool RP3D_COLLIDERS_ACTIVE = shadeCollider->flags & SHColliderComponent::ACTIVE_FLAG;
|
||||
|
||||
// Modify the static body's active state
|
||||
// The collision listener & raycaster will handle culling inactive colliders.
|
||||
if (SHADE_COLLIDER_ACTIVE != RP3D_COLLIDERS_ACTIVE)
|
||||
physicsObject.body->setIsActive(SHADE_COLLIDER_ACTIVE);
|
||||
|
||||
shadeCollider->transform.position = WORLD_POS;
|
||||
shadeCollider->transform.orientation = WORLD_ROT;
|
||||
shadeCollider->transform.scale = TRANSFORM_COMPONENT->GetWorldScale();
|
||||
|
||||
shadeCollider->Update();
|
||||
}
|
||||
}
|
||||
|
||||
if (UPDATE_COLLISION_TAGS && shadeCollider)
|
||||
shadeCollider->UpdateCollisionTags();
|
||||
}
|
||||
|
||||
// Clear collision tag dirty flags
|
||||
SHCollisionTagMatrix::Clear();
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -0,0 +1,66 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsUpdateRoutine.cpp
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for the Physics Update Routine
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "Physics/System/SHPhysicsSystem.h"
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsSystem::PhysicsUpdate::PhysicsUpdate()
|
||||
: SHFixedSystemRoutine { DEFAULT_FIXED_STEP, "Physics Update", false }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsSystem::PhysicsUpdate::Execute(double dt) noexcept
|
||||
{
|
||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||
|
||||
auto* scriptEngine = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||
if (!scriptEngine)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing ScriptEngine!")
|
||||
}
|
||||
|
||||
const double FIXED_DT = physicsSystem->fixedDT;
|
||||
accumulatedTime += dt;
|
||||
|
||||
int count = 0;
|
||||
while (accumulatedTime > FIXED_DT)
|
||||
{
|
||||
if (scriptEngine)
|
||||
scriptEngine->ExecuteFixedUpdates();
|
||||
|
||||
if (physicsSystem->worldState.world)
|
||||
physicsSystem->worldState.world->update(static_cast<rp3d::decimal>(FIXED_DT));
|
||||
|
||||
accumulatedTime -= FIXED_DT;
|
||||
++count;
|
||||
}
|
||||
|
||||
stats.numSteps = count;
|
||||
physicsSystem->worldUpdated = count > 0;
|
||||
|
||||
physicsSystem->interpolationFactor = physicsSystem->worldUpdated ? accumulatedTime / FIXED_DT : 0.0;
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -13,79 +13,59 @@
|
|||
// Primary Header
|
||||
#include "SHPhysicsDebugDrawSystem.h"
|
||||
|
||||
// Project Headers
|
||||
// Project Header
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Editor/SHEditor.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Physics/SHPhysicsEvents.h"
|
||||
#include "Tools/Utilities/SHUtilities.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Static Data Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
const SHPhysicsDebugDrawSystem::DebugDrawFunction SHPhysicsDebugDrawSystem::drawFunctions[NUM_FLAGS] =
|
||||
const SHColour SHPhysicsDebugDrawSystem::DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(Colours::COUNT)]
|
||||
{
|
||||
drawColliders
|
||||
, drawColliderAABBs
|
||||
, drawBroadPhaseAABBs
|
||||
, drawContactPoints
|
||||
, drawContactNormals
|
||||
, drawRaycasts
|
||||
SHColour::GREEN // Colliders
|
||||
, SHColour::PURPLE // Triggers
|
||||
, SHColour::RED // Contacts
|
||||
, SHColour::ORANGE // Raycasts
|
||||
};
|
||||
|
||||
SHVec3 SHPhysicsDebugDrawSystem::boxVertices[NUM_BOX_VERTICES];
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsDebugDrawSystem::SHPhysicsDebugDrawSystem() noexcept
|
||||
: debugDrawFlags { 0 }
|
||||
, physicsSystem { nullptr }
|
||||
: flags { 0 }
|
||||
{
|
||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER)] = SHColour::GREEN;
|
||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::COLLIDER_AABB)] = SHColour::YELLOW;
|
||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::BROAD_PHASE_AABB)] = SHColour::CYAN;
|
||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_POINTS)] = SHColour::RED;
|
||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::CONTACT_NORMALS)] = SHColour::RED;
|
||||
debugColours[SHUtilities::ConvertEnum(DebugDrawFlags::RAYCASTS)] = SHColour::ORANGE;
|
||||
collidersToDraw.clear();
|
||||
}
|
||||
|
||||
SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::PhysicsDebugDrawRoutine()
|
||||
: SHSystemRoutine { "Physics Debug Draw", true }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
bool SHPhysicsDebugDrawSystem::GetDebugDrawFlag(DebugDrawFlags flag) const noexcept
|
||||
bool SHPhysicsDebugDrawSystem::IsDebugDrawActive() const noexcept
|
||||
{
|
||||
const auto INT_FLAG = SHUtilities::ConvertEnum(flag);
|
||||
if (INT_FLAG < 0 || INT_FLAG >= NUM_FLAGS)
|
||||
{
|
||||
SHLOG_ERROR("Invalid Debug Draw Flag Passed {} in. Unable to get debug draw state!", INT_FLAG)
|
||||
return false;
|
||||
}
|
||||
return flags & ACTIVE_FLAG;
|
||||
}
|
||||
|
||||
return debugDrawFlags & 1U << SHUtilities::ConvertEnum(flag);
|
||||
bool SHPhysicsDebugDrawSystem::GetFlagState(DebugDrawFlags flag) const noexcept
|
||||
{
|
||||
const uint8_t ENUM_VALUE = SHUtilities::ConvertEnum(flag);
|
||||
return flags & ENUM_VALUE;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsDebugDrawSystem::SetDebugDrawFlag(DebugDrawFlags flag, bool value) noexcept
|
||||
void SHPhysicsDebugDrawSystem::SetFlagState(DebugDrawFlags flag, bool state) noexcept
|
||||
{
|
||||
const auto INT_FLAG = SHUtilities::ConvertEnum(flag);
|
||||
if (INT_FLAG < 0 || INT_FLAG >= NUM_FLAGS)
|
||||
{
|
||||
SHLOG_ERROR("Invalid Debug Draw Flag Passed {} in. Unable to set debug draw state!", INT_FLAG)
|
||||
return;
|
||||
}
|
||||
const uint8_t ENUM_VALUE = SHUtilities::ConvertEnum(flag);
|
||||
state ? flags |= ENUM_VALUE : flags &= ~ENUM_VALUE;
|
||||
|
||||
value ? (debugDrawFlags |= 1U << INT_FLAG) : (debugDrawFlags &= ~(1U << INT_FLAG));
|
||||
// If no other debug drawing state is active, turn active off. Otherwise, we maintain
|
||||
// the active state.
|
||||
flags == ACTIVE_FLAG ? flags = 0 : flags |= ACTIVE_FLAG;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -96,240 +76,76 @@ namespace SHADE
|
|||
{
|
||||
SystemFamily::GetID<SHPhysicsDebugDrawSystem>();
|
||||
|
||||
SHASSERT(physicsSystem == nullptr, "Non-existent physics system attached to the physics debug draw system!")
|
||||
physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
// Register collider draw event
|
||||
const std::shared_ptr EVENT_RECEIVER = std::make_shared<SHEventReceiverSpec<SHPhysicsDebugDrawSystem>>(this, &SHPhysicsDebugDrawSystem::onColliderDraw);
|
||||
const ReceiverPtr EVENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(EVENT_RECEIVER);
|
||||
|
||||
// Generate shapes
|
||||
generateBox();
|
||||
SHEventManager::SubscribeTo(SH_PHYSICS_COLLIDER_DRAW_EVENT, EVENT_RECEIVER_PTR);
|
||||
}
|
||||
|
||||
void SHPhysicsDebugDrawSystem::Exit()
|
||||
{
|
||||
physicsSystem = nullptr;
|
||||
|
||||
}
|
||||
|
||||
void SHPhysicsDebugDrawSystem::PhysicsDebugDrawRoutine::Execute(double) noexcept
|
||||
void SHPhysicsDebugDrawSystem::AddRaycast(const SHRay& ray, const SHPhysicsRaycastResult& result) noexcept
|
||||
{
|
||||
auto* system = reinterpret_cast<SHPhysicsDebugDrawSystem*>(GetSystem());
|
||||
|
||||
auto* debugDrawSystem = SHSystemManager::GetSystem<SHDebugDrawSystem>();
|
||||
if (debugDrawSystem == nullptr)
|
||||
{
|
||||
SHLOG_ERROR("Unable to get a debug draw system for Physics Debug Drawing!")
|
||||
return;
|
||||
}
|
||||
|
||||
rp3d::DebugRenderer* rp3dRenderer = nullptr;
|
||||
if (system->physicsSystem->worldState.world)
|
||||
rp3dRenderer = &system->physicsSystem->worldState.world->getDebugRenderer();
|
||||
|
||||
for (int i = 0; i < SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS); ++i)
|
||||
{
|
||||
const bool DRAW = (system->debugDrawFlags & (1U << i)) > 0;
|
||||
if (DRAW)
|
||||
{
|
||||
drawFunctions[i](debugDrawSystem, rp3dRenderer);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rp3dRenderer && (i == 3 || i == 4))
|
||||
{
|
||||
rp3dRenderer->setIsDebugItemDisplayed(reactphysics3d::DebugRenderer::DebugItem::CONTACT_POINT, false);
|
||||
rp3dRenderer->setIsDebugItemDisplayed(reactphysics3d::DebugRenderer::DebugItem::CONTACT_NORMAL, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Automatically clear the container of raycasts despite debug drawing state
|
||||
// TODO(Diren): Move this somewhere else
|
||||
system->physicsSystem->raycaster.ClearFrame();
|
||||
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsDebugDrawSystem::drawColliders(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
||||
SHEventHandle SHPhysicsDebugDrawSystem::onColliderDraw(SHEventPtr onColliderDrawEvent)
|
||||
{
|
||||
const auto& COLLIDER_SET = SHComponentManager::GetDense<SHColliderComponent>();
|
||||
for (const auto& COLLIDER : COLLIDER_SET)
|
||||
{
|
||||
// Skip inactive colliders
|
||||
if (!SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(COLLIDER.GetEID()))
|
||||
continue;
|
||||
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHColliderOnDebugDrawEvent>*>(onColliderDrawEvent.get())->data;
|
||||
|
||||
for (auto& collisionShape : COLLIDER.GetCollisionShapes())
|
||||
// Add to the container to draw all colliders
|
||||
if (EVENT_DATA->debugDrawState)
|
||||
{
|
||||
if (collidersToDraw.empty())
|
||||
flags |= ACTIVE_FLAG;
|
||||
|
||||
collidersToDraw.emplace(EVENT_DATA->entityID);
|
||||
}
|
||||
else
|
||||
{
|
||||
collidersToDraw.erase(EVENT_DATA->entityID);
|
||||
|
||||
// if no colliders queued for drawing and no other debug drawing is enabled, disable debug drawing
|
||||
if (collidersToDraw.empty() && flags == ACTIVE_FLAG)
|
||||
flags = 0;
|
||||
}
|
||||
|
||||
return onColliderDrawEvent.get()->handle;
|
||||
}
|
||||
|
||||
void SHPhysicsDebugDrawSystem::drawCollider(SHDebugDrawSystem* debugDrawSystem, const SHColliderComponent& collider) noexcept
|
||||
{
|
||||
for (const auto& SHAPE : collider.GetCollisionShapes())
|
||||
{
|
||||
const SHColour& DRAW_COLOUR = DEBUG_DRAW_COLOURS[SHUtilities::ConvertEnum(SHAPE->IsTrigger() ? Colours::TRIGGER : Colours::COLLIDER)];
|
||||
|
||||
switch (SHAPE->GetType())
|
||||
{
|
||||
switch (collisionShape.GetType())
|
||||
case SHCollisionShape::Type::SPHERE:
|
||||
{
|
||||
case SHCollisionShape::Type::BOX: debugDrawBox(debugRenderer, COLLIDER, collisionShape); break;
|
||||
case SHCollisionShape::Type::SPHERE: debugDrawSphere(debugRenderer, COLLIDER, collisionShape); break;
|
||||
default: break;
|
||||
debugDrawSystem->DrawWireSphere(SHAPE->GetTRS(), DRAW_COLOUR, true);
|
||||
break;
|
||||
}
|
||||
case SHCollisionShape::Type::BOX:
|
||||
{
|
||||
debugDrawSystem->DrawWireCube(SHAPE->GetTRS(), DRAW_COLOUR, true);
|
||||
break;
|
||||
}
|
||||
//case SHCollisionShape::Type::CAPSULE:
|
||||
//{
|
||||
// break;
|
||||
//}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHPhysicsDebugDrawSystem::drawColliderAABBs(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SHPhysicsDebugDrawSystem::drawBroadPhaseAABBs(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void SHPhysicsDebugDrawSystem::drawContactPoints(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
||||
{
|
||||
#ifdef SHEDITOR
|
||||
|
||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||
{
|
||||
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, true);
|
||||
const int NUM_TRIS = static_cast<int>(rp3dRenderer->getNbTriangles());
|
||||
if (NUM_TRIS == 0)
|
||||
return;
|
||||
|
||||
const auto& TRI_ARRAY = rp3dRenderer->getTrianglesArray();
|
||||
for (int i = 0; i < NUM_TRIS; ++i)
|
||||
debugRenderer->DrawTri(TRI_ARRAY[i].point1, TRI_ARRAY[i].point2, TRI_ARRAY[i].point3, SHColour::RED);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_POINT, true);
|
||||
const int NUM_TRIS = static_cast<int>(rp3dRenderer->getNbTriangles());
|
||||
if (NUM_TRIS == 0)
|
||||
return;
|
||||
|
||||
const auto& TRI_ARRAY = rp3dRenderer->getTrianglesArray();
|
||||
for (int i = 0; i < NUM_TRIS; ++i)
|
||||
debugRenderer->DrawTri(TRI_ARRAY[i].point1, TRI_ARRAY[i].point2, TRI_ARRAY[i].point3, SHColour::RED);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void SHPhysicsDebugDrawSystem::drawContactNormals(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
||||
{
|
||||
#ifdef SHEDITOR
|
||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||
{
|
||||
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, true);
|
||||
const int NUM_LINES = static_cast<int>(rp3dRenderer->getNbLines());
|
||||
if (NUM_LINES == 0)
|
||||
return;
|
||||
|
||||
const auto& LINE_ARRAY = rp3dRenderer->getLinesArray();
|
||||
for (int i = 0; i < NUM_LINES; ++i)
|
||||
debugRenderer->DrawLine(LINE_ARRAY[i].point1, LINE_ARRAY[i].point2, SHColour::RED);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
rp3dRenderer->setIsDebugItemDisplayed(rp3d::DebugRenderer::DebugItem::CONTACT_NORMAL, true);
|
||||
const int NUM_LINES = static_cast<int>(rp3dRenderer->getNbLines());
|
||||
if (NUM_LINES == 0)
|
||||
return;
|
||||
|
||||
const auto& LINE_ARRAY = rp3dRenderer->getLinesArray();
|
||||
for (int i = 0; i < NUM_LINES; ++i)
|
||||
debugRenderer->DrawLine(LINE_ARRAY[i].point1, LINE_ARRAY[i].point2, SHColour::RED);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void SHPhysicsDebugDrawSystem::drawRaycasts(SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept
|
||||
{
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (!physicsSystem)
|
||||
{
|
||||
SHLOG_ERROR("Unable to retrieve physics system for debug drawing raycasts!")
|
||||
return;
|
||||
}
|
||||
|
||||
const SHColour& RAY_COLOUR = SHColour::ORANGE;
|
||||
|
||||
// Draw all raycast pairs
|
||||
for (const auto& [ray, raycastResult] : physicsSystem->raycaster.GetRaycasts())
|
||||
{
|
||||
// If infinity, it is an infinite raycast. If not, render the distance in raycastResult.
|
||||
// Ignore the hit variable as it will always correspond to the length of the raycast, hit or miss.
|
||||
const float RENDER_DIST = raycastResult.distance == std::numeric_limits<float>::infinity() ? SHRay::MAX_RAYCAST_DIST : raycastResult.distance;
|
||||
const SHVec3 END_POS = ray.position + (ray.direction * RENDER_DIST);
|
||||
|
||||
debugRenderer->DrawLine(ray.position, END_POS, RAY_COLOUR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SHPhysicsDebugDrawSystem::generateBox() noexcept
|
||||
{
|
||||
boxVertices[0] = { 0.5f, 0.5f, -0.5f }; // TOP_RIGHT_BACK
|
||||
boxVertices[1] = { -0.5f, 0.5f, -0.5f }; // TOP_LEFT_BACK
|
||||
boxVertices[2] = { 0.5f, -0.5f, -0.5f }; // BTM_RIGHT_BACK
|
||||
boxVertices[3] = { -0.5f, -0.5f, -0.5f }; // BTM_LEFT_BACK
|
||||
boxVertices[4] = { 0.5f, 0.5f, 0.5f }; // TOP_RIGHT_FRONT
|
||||
boxVertices[5] = { -0.5f, 0.5f, 0.5f }; // TOP_LEFT_FRONT
|
||||
boxVertices[6] = { 0.5f, -0.5f, 0.5f }; // BTM_RIGHT_FRONT
|
||||
boxVertices[7] = { -0.5f, -0.5f, 0.5f }; // BTM_LEFT_FRONT
|
||||
}
|
||||
|
||||
void SHPhysicsDebugDrawSystem::debugDrawBox(SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
||||
{
|
||||
auto* BOX = reinterpret_cast<const SHBox*>(collisionShape.GetShape());
|
||||
|
||||
// Calculate final position & orientation
|
||||
const SHVec3 COLLIDER_POS = colliderComponent.GetPosition();
|
||||
const SHVec3 BOX_POS = collisionShape.GetPositionOffset();
|
||||
const SHQuaternion COLLIDER_ROT = colliderComponent.GetOrientation();
|
||||
const SHQuaternion BOX_ROT = SHQuaternion::FromEuler(collisionShape.GetRotationOffset());
|
||||
|
||||
|
||||
const SHMatrix COLLIDER_TR = SHMatrix::Rotate(COLLIDER_ROT) * SHMatrix::Translate(COLLIDER_POS);
|
||||
const SHMatrix BOX_TRS = SHMatrix::Scale(BOX->GetWorldExtents() * 2.0f) * SHMatrix::Rotate(BOX_ROT) * SHMatrix::Translate(BOX_POS);
|
||||
|
||||
const SHMatrix FINAL_TRS = BOX_TRS * COLLIDER_TR;
|
||||
|
||||
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
|
||||
|
||||
std::array<SHVec3, NUM_BOX_VERTICES> transformedVertices;
|
||||
for (uint32_t i = 0; i < NUM_BOX_VERTICES / 2; ++i)
|
||||
{
|
||||
const uint32_t IDX1 = i;
|
||||
const uint32_t IDX2 = i + NUM_BOX_VERTICES / 2;
|
||||
|
||||
transformedVertices[IDX1] = SHVec3::Transform(boxVertices[IDX1], FINAL_TRS);
|
||||
transformedVertices[IDX2] = SHVec3::Transform(boxVertices[IDX2], FINAL_TRS);
|
||||
|
||||
// Draw 4 line to connect the quads
|
||||
debugRenderer->DrawLine(transformedVertices[IDX1], transformedVertices[IDX2], COLLIDER_COLOUR);
|
||||
}
|
||||
|
||||
// A, B, C, D
|
||||
std::array backQuad { transformedVertices[0], transformedVertices[1], transformedVertices[3], transformedVertices[2] };
|
||||
debugRenderer->DrawLineLoop(backQuad.begin(), backQuad.end(), COLLIDER_COLOUR);
|
||||
|
||||
// E, F, G, H
|
||||
std::array frontQuad { transformedVertices[4], transformedVertices[5], transformedVertices[7], transformedVertices[6] };
|
||||
debugRenderer->DrawLineLoop(frontQuad.begin(), frontQuad.end(), COLLIDER_COLOUR);
|
||||
}
|
||||
|
||||
void SHPhysicsDebugDrawSystem::debugDrawSphere(SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept
|
||||
{
|
||||
auto* SPHERE = reinterpret_cast<const SHSphere*>(collisionShape.GetShape());
|
||||
|
||||
const SHColour COLLIDER_COLOUR = collisionShape.IsTrigger() ? SHColour::PURPLE : SHColour::GREEN;
|
||||
|
||||
// Calculate final position & orientation
|
||||
const SHQuaternion FINAL_ROT = colliderComponent.GetOrientation() * SHQuaternion::FromEuler(collisionShape.GetRotationOffset());
|
||||
const SHMatrix TR = SHMatrix::Rotate(FINAL_ROT) * SHMatrix::Translate(colliderComponent.GetPosition());
|
||||
|
||||
/* #KWFix */
|
||||
//debugRenderer->DrawSphere(COLLIDER_COLOUR, SHVec3::Transform(collisionShape.GetPositionOffset(), TR), SPHERE->GetWorldRadius());
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -10,14 +10,16 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
#include <unordered_set>
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Entity/SHEntity.h"
|
||||
#include "ECS_Base/System/SHSystem.h"
|
||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||
#include "Events/SHEvent.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h"
|
||||
#include "Math/SHColour.h"
|
||||
#include "SHPhysicsSystem.h"
|
||||
#include "Tools/Utilities/SHUtilities.h"
|
||||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
#include "Physics/Collision/SHPhysicsRaycastResult.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -28,63 +30,54 @@ namespace SHADE
|
|||
class SH_API SHPhysicsDebugDrawSystem final : public SHSystem
|
||||
{
|
||||
public:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
enum class DebugDrawFlags
|
||||
enum class DebugDrawFlags : uint8_t
|
||||
{
|
||||
COLLIDER
|
||||
, COLLIDER_AABB
|
||||
, BROAD_PHASE_AABB
|
||||
, CONTACT_POINTS
|
||||
, CONTACT_NORMALS
|
||||
, RAYCASTS
|
||||
|
||||
, NUM_FLAGS
|
||||
COLLIDERS = 0x02
|
||||
, CONTACTS = 0x04
|
||||
, RAYCASTS = 0x08
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsDebugDrawSystem() noexcept;
|
||||
SHPhysicsDebugDrawSystem () noexcept;
|
||||
~SHPhysicsDebugDrawSystem() noexcept = default;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
bool GetDebugDrawFlag(DebugDrawFlags flag) const noexcept;
|
||||
|
||||
[[nodiscard]] bool IsDebugDrawActive () const noexcept;
|
||||
[[nodiscard]] bool GetFlagState (DebugDrawFlags flag) const noexcept;
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetDebugDrawFlag(DebugDrawFlags flag, bool value) noexcept;
|
||||
void SetFlagState (DebugDrawFlags flag, bool state) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/* Member Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void Init() override;
|
||||
void Exit() override;
|
||||
void Init () override;
|
||||
void Exit () override;
|
||||
|
||||
void AddRaycast (const SHRay& ray, const SHPhysicsRaycastResult& result) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* System Routines */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
class SH_API PhysicsDebugDrawRoutine final : public SHSystemRoutine
|
||||
/**
|
||||
* @brief
|
||||
* If the editor is enabled, this routine invokes debug drawing for colliders and collision information.
|
||||
*/
|
||||
class SH_API PhysicsDebugDraw final : public SHSystemRoutine
|
||||
{
|
||||
public:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
PhysicsDebugDrawRoutine();
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
PhysicsDebugDraw();
|
||||
void Execute(double dt) noexcept override;
|
||||
};
|
||||
|
||||
|
@ -93,46 +86,58 @@ namespace SHADE
|
|||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
using DebugDrawFunction = void(*)(SHDebugDrawSystem*, rp3d::DebugRenderer*) noexcept;
|
||||
union DebugDrawInfo
|
||||
{
|
||||
struct Contact
|
||||
{
|
||||
SHVec3 worldPos;
|
||||
SHVec3 normal;
|
||||
} contact;
|
||||
|
||||
struct Raycast
|
||||
{
|
||||
SHVec3 start;
|
||||
SHVec3 end;
|
||||
} raycast;
|
||||
};
|
||||
|
||||
using Colliders = std::unordered_set<EntityID>;
|
||||
using Raycasts = std::vector<DebugDrawInfo>;
|
||||
using Contacts = std::vector<DebugDrawInfo>;
|
||||
|
||||
enum class Colours
|
||||
{
|
||||
COLLIDER
|
||||
, TRIGGER
|
||||
, CONTACT
|
||||
, RAYCAST
|
||||
|
||||
, COUNT
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
static constexpr int NUM_FLAGS = SHUtilities::ConvertEnum(DebugDrawFlags::NUM_FLAGS);
|
||||
static const DebugDrawFunction drawFunctions[NUM_FLAGS];
|
||||
static constexpr uint8_t ACTIVE_FLAG = 0x01;
|
||||
|
||||
// SHAPES INFO
|
||||
static const SHColour DEBUG_DRAW_COLOURS[static_cast<int>(Colours::COUNT)];
|
||||
|
||||
static constexpr size_t NUM_BOX_VERTICES = 8;
|
||||
static SHVec3 boxVertices[NUM_BOX_VERTICES];
|
||||
// 0 0 0 drawBroadphase drawRaycasts drawContacts drawAllColliders debugDrawActive
|
||||
uint8_t flags;
|
||||
|
||||
Colliders collidersToDraw;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Member Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHEventHandle onColliderDraw(SHEventPtr onColliderDrawEvent);
|
||||
|
||||
static void drawCollider (SHDebugDrawSystem* debugDrawSystem, const SHColliderComponent& collider) noexcept;
|
||||
static void drawRaycast (SHDebugDrawSystem* debugDrawSystem, const DebugDrawInfo::Raycast& raycastInfo) noexcept;
|
||||
|
||||
|
||||
uint8_t debugDrawFlags;
|
||||
SHPhysicsSystem* physicsSystem;
|
||||
SHColour debugColours[NUM_FLAGS];
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
// Generic Draw Functions
|
||||
|
||||
static void drawColliders (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
||||
static void drawColliderAABBs (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
||||
static void drawBroadPhaseAABBs (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
||||
static void drawContactPoints (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
||||
static void drawContactNormals (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
||||
static void drawRaycasts (SHDebugDrawSystem* debugRenderer, rp3d::DebugRenderer* rp3dRenderer) noexcept;
|
||||
|
||||
// Shape Generation Functions
|
||||
|
||||
static void generateBox () noexcept;
|
||||
|
||||
// Shape Draw Functions
|
||||
|
||||
static void debugDrawBox (SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
||||
static void debugDrawSphere (SHDebugDrawSystem* debugRenderer, const SHColliderComponent& colliderComponent, const SHCollisionShape& collisionShape) noexcept;
|
||||
};
|
||||
|
||||
} // namespace SHADE
|
||||
|
||||
} // namespace SHADE
|
|
@ -19,8 +19,9 @@
|
|||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Editor/SHEditor.h"
|
||||
#include "Physics/Collision/SHCollisionTagMatrix.h"
|
||||
#include "Physics/SHPhysicsEvents.h"
|
||||
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
|
||||
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
|
||||
|
@ -30,11 +31,23 @@ namespace SHADE
|
|||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsSystem::SHPhysicsSystem()
|
||||
SHPhysicsSystem::SHPhysicsSystem() noexcept
|
||||
: worldUpdated { false }
|
||||
, interpolationFactor { 0.0 }
|
||||
, fixedDT { DEFAULT_FIXED_STEP }
|
||||
{}
|
||||
{
|
||||
// Add more events here to register them
|
||||
|
||||
eventFunctions[0] = { &SHPhysicsSystem::onComponentAdded , SH_COMPONENT_ADDED_EVENT };
|
||||
eventFunctions[1] = { &SHPhysicsSystem::onComponentRemoved, SH_COMPONENT_REMOVED_EVENT };
|
||||
eventFunctions[2] = { &SHPhysicsSystem::onSceneInit , SH_SCENE_INIT_POST };
|
||||
eventFunctions[3] = { &SHPhysicsSystem::onSceneExit , SH_SCENE_EXIT_POST };
|
||||
}
|
||||
|
||||
SHPhysicsSystem::~SHPhysicsSystem()
|
||||
{
|
||||
worldState.DestroyWorld(factory);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Getter Function Definitions */
|
||||
|
@ -45,9 +58,9 @@ namespace SHADE
|
|||
return 1.0 / fixedDT;
|
||||
}
|
||||
|
||||
const SHPhysicsWorldState::WorldSettings& SHPhysicsSystem::GetWorldSettings() const noexcept
|
||||
double SHPhysicsSystem::GetFixedDT() const noexcept
|
||||
{
|
||||
return worldState.settings;
|
||||
return fixedDT;
|
||||
}
|
||||
|
||||
const std::vector<SHCollisionInfo>& SHPhysicsSystem::GetAllCollisionInfo() const noexcept
|
||||
|
@ -60,30 +73,43 @@ namespace SHADE
|
|||
return collisionListener.GetTriggerInfoContainer();
|
||||
}
|
||||
|
||||
const SHPhysicsObject* SHPhysicsSystem::GetPhysicsObject(EntityID eid) noexcept
|
||||
{
|
||||
return objectManager.GetPhysicsObject(eid);
|
||||
}
|
||||
|
||||
|
||||
const SHPhysicsObjectManager::PhysicsObjectEntityMap& SHPhysicsSystem::GetPhysicsObjects() const noexcept
|
||||
{
|
||||
return objectManager.physicsObjects;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Setter Function Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsSystem::SetFixedUpdateRate(double fixedUpdateRate) noexcept
|
||||
{
|
||||
// Handle invalid input
|
||||
if (fixedUpdateRate <= 0.0)
|
||||
{
|
||||
SHLOGV_WARNING("Invalid value for setting fixed update rate! Fixed update rate unchanged.")
|
||||
return;
|
||||
}
|
||||
|
||||
fixedDT = 1.0 / fixedUpdateRate;
|
||||
|
||||
// Handle potential incorrect / unintended input
|
||||
if (fixedDT > 1.0)
|
||||
{
|
||||
SHLOGV_WARNING("Fixed Update Rate Time is set below 1. This may result in undesirable behaviour.")
|
||||
}
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::SetWorldSettings(const SHPhysicsWorldState::WorldSettings& settings) noexcept
|
||||
void SHPhysicsSystem::SetFixedDT(double fixedDt) noexcept
|
||||
{
|
||||
worldState.settings = settings;
|
||||
worldState.UpdateSettings();
|
||||
if (fixedDt <= 0.0)
|
||||
{
|
||||
SHLOGV_WARNING("Invalid value for setting fixed delta time! Fixed delta time unchanged.")
|
||||
return;
|
||||
}
|
||||
|
||||
fixedDT = fixedDt;
|
||||
|
||||
// Handle potential incorrect / unintended input
|
||||
if (fixedDT > 1.0)
|
||||
{
|
||||
SHLOGV_WARNING("Fixed Delta Time is set above 1. This may result in undesirable behaviour.")
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -92,40 +118,24 @@ namespace SHADE
|
|||
|
||||
void SHPhysicsSystem::Init()
|
||||
{
|
||||
// TODO(Diren): Consider using a non-static collision tag matrix.
|
||||
// Initialise collision tags
|
||||
std::filesystem::path defaultCollisionTagNameFilePath { ASSET_ROOT };
|
||||
defaultCollisionTagNameFilePath.append("CollisionTags.SHConfig");
|
||||
SHCollisionTagMatrix::Init(defaultCollisionTagNameFilePath);
|
||||
|
||||
// Link Physics Object Manager with System & Raycaster
|
||||
objectManager.SetFactory(factory);
|
||||
raycaster.SetObjectManager(&objectManager);
|
||||
// Register Events
|
||||
for (int i = 0; i < NUM_EVENT_FUNCTIONS; ++i)
|
||||
{
|
||||
const std::shared_ptr EVENT_RECEIVER = std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, eventFunctions[i].first);
|
||||
const ReceiverPtr EVENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(EVENT_RECEIVER);
|
||||
|
||||
// Link Collision Listener with System
|
||||
SHEventManager::SubscribeTo(eventFunctions[i].second, EVENT_RECEIVER_PTR);
|
||||
}
|
||||
|
||||
objectManager.SetFactory(&factory);
|
||||
collisionListener.BindToSystem(this);
|
||||
|
||||
// Subscribe to component events
|
||||
const std::shared_ptr ADD_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::addPhysicsComponent) };
|
||||
const ReceiverPtr ADD_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ADD_COMPONENT_RECEIVER);
|
||||
SHEventManager::SubscribeTo(SH_COMPONENT_ADDED_EVENT, ADD_COMPONENT_RECEIVER_PTR);
|
||||
|
||||
const std::shared_ptr REMOVE_COMPONENT_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::removePhysicsComponent) };
|
||||
const ReceiverPtr REMOVE_COMPONENT_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(REMOVE_COMPONENT_RECEIVER);
|
||||
SHEventManager::SubscribeTo(SH_COMPONENT_REMOVED_EVENT, REMOVE_COMPONENT_RECEIVER_PTR);
|
||||
|
||||
#ifdef SHEDITOR
|
||||
|
||||
// Subscribe to Editor State Change Events
|
||||
const std::shared_ptr ON_PLAY_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::onPlay) };
|
||||
const ReceiverPtr ON_PLAY_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ON_PLAY_RECEIVER);
|
||||
SHEventManager::SubscribeTo(SH_EDITOR_ON_PLAY_EVENT, ON_PLAY_RECEIVER_PTR);
|
||||
|
||||
const std::shared_ptr ON_STOP_RECEIVER { std::make_shared<SHEventReceiverSpec<SHPhysicsSystem>>(this, &SHPhysicsSystem::onStop) };
|
||||
const ReceiverPtr ON_STOP_RECEIVER_PTR = std::dynamic_pointer_cast<SHEventReceiver>(ON_STOP_RECEIVER);
|
||||
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, ON_STOP_RECEIVER_PTR);
|
||||
|
||||
#endif
|
||||
|
||||
raycaster.BindToSystem(this);
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::Exit()
|
||||
|
@ -138,344 +148,166 @@ namespace SHADE
|
|||
SHCollisionTagMatrix::Exit(defaultCollisionTagNameFilePath);
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::BuildScene(SHSceneGraph& sceneGraph)
|
||||
const std::vector<SHPhysicsRaycastResult>& SHPhysicsSystem::Raycast(const SHRaycaster::RaycastInfo& info) noexcept
|
||||
{
|
||||
static const auto BUILD_NEW_SCENE_PHYSICS_OBJECT = [&](SHSceneNode* node)
|
||||
{
|
||||
const EntityID EID = node->GetEntityID();
|
||||
auto& results = raycaster.Raycast(info);
|
||||
|
||||
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(EID))
|
||||
objectManager.AddRigidBody(EID);
|
||||
// Load start and end points into the container for debug drawing
|
||||
#ifdef SHEDITOR
|
||||
|
||||
if (SHComponentManager::HasComponent<SHColliderComponent>(EID))
|
||||
{
|
||||
objectManager.AddCollider(EID);
|
||||
SHVec3 endPos = info.ray.position + info.ray.direction * SHRay::MAX_RAYCAST_DIST;
|
||||
|
||||
auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(EID);
|
||||
for (size_t i = 0; i < COLLIDER->GetCollisionShapes().size(); ++i)
|
||||
objectManager.AddCollisionShape(EID, i);
|
||||
}
|
||||
if (!results.empty())
|
||||
endPos = results.back().position;
|
||||
|
||||
};
|
||||
raycastHits.emplace_back(info.ray.position, endPos);
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
// Destroy an existing world
|
||||
if (worldState.world != nullptr)
|
||||
{
|
||||
objectManager.RemoveAllObjects();
|
||||
objectManager.SetWorld(nullptr);
|
||||
|
||||
collisionListener.ClearContainers();
|
||||
raycaster.ClearFrame();
|
||||
|
||||
worldState.DestroyWorld(factory);
|
||||
}
|
||||
|
||||
worldState.CreateWorld(factory);
|
||||
#ifdef _PUBLISH
|
||||
worldState.world->setIsDebugRenderingEnabled(false);
|
||||
#else
|
||||
worldState.world->setIsDebugRenderingEnabled(true);
|
||||
#endif
|
||||
|
||||
// Link Collision Listener & Raycaster
|
||||
collisionListener.BindToWorld(worldState.world);
|
||||
raycaster.BindToWorld(worldState.world);
|
||||
|
||||
// Link with object manager & create all physics objects
|
||||
objectManager.SetWorld(worldState.world);
|
||||
|
||||
// When building a scene, clear the object manager command queue and build scene objects again.
|
||||
// This is done to avoid duplicate adds.
|
||||
while (!objectManager.commandQueue.empty())
|
||||
objectManager.commandQueue.pop();
|
||||
|
||||
sceneGraph.Traverse(BUILD_NEW_SCENE_PHYSICS_OBJECT);
|
||||
objectManager.UpdateCommands();
|
||||
return results;
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::ForceBuild(SHSceneGraph& sceneGraph)
|
||||
{
|
||||
// HACK: Band-aid fix. To be removed.
|
||||
objectManager.UpdateCommands();
|
||||
}
|
||||
|
||||
|
||||
void SHPhysicsSystem::ForceUpdate()
|
||||
{
|
||||
if (!worldState.world)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to force update without a Physics world!")
|
||||
return;
|
||||
}
|
||||
|
||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||
if (scriptingSystem == nullptr)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
|
||||
}
|
||||
|
||||
// Force the physics world to update once
|
||||
if (scriptingSystem != nullptr)
|
||||
scriptingSystem->ExecuteFixedUpdates();
|
||||
|
||||
worldState.world->update(static_cast<rp3d::decimal>(fixedDT));
|
||||
|
||||
// Sync transforms. No interpolation applied here
|
||||
for (auto& [entityID, physicsObject] : objectManager.physicsObjects)
|
||||
{
|
||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
||||
|
||||
const auto& CURRENT_TF = physicsObject.GetRigidBody()->getTransform();
|
||||
const auto& RENDER_POS = CURRENT_TF.getPosition();
|
||||
const auto& RENDER_ROT = CURRENT_TF.getOrientation();
|
||||
|
||||
// Cache transform
|
||||
physicsObject.prevTransform = CURRENT_TF;
|
||||
|
||||
// Sync with physics components
|
||||
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(entityID))
|
||||
{
|
||||
rigidBodyComponent->position = RENDER_POS;
|
||||
rigidBodyComponent->orientation = RENDER_ROT;
|
||||
}
|
||||
|
||||
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(entityID))
|
||||
{
|
||||
colliderComponent->position = RENDER_POS;
|
||||
colliderComponent->orientation = RENDER_ROT;
|
||||
}
|
||||
|
||||
// Set transform for rendering
|
||||
if (transformComponent)
|
||||
{
|
||||
transformComponent->SetWorldPosition(RENDER_POS);
|
||||
transformComponent->SetWorldOrientation(RENDER_ROT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystem::Raycast(const SHRay& ray, float distance, const SHCollisionTag& collisionTag) noexcept
|
||||
{
|
||||
return raycaster.Raycast(ray, distance, collisionTag);
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystem::Linecast(const SHVec3& start, const SHVec3& end, const SHCollisionTag& collisionTag) noexcept
|
||||
{
|
||||
return raycaster.Linecast(start, end, collisionTag);
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystem::ColliderRaycast(EntityID eid, const SHRay& ray, float distance) noexcept
|
||||
{
|
||||
return raycaster.ColliderRaycast(eid, ray, distance);
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystem::ColliderRaycast(EntityID eid, int shapeIndex, const SHRay& ray, float distance) noexcept
|
||||
{
|
||||
return raycaster.ColliderRaycast(eid, shapeIndex, ray, distance);
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystem::ColliderLinecast(EntityID eid, const SHVec3& start, const SHVec3& end) noexcept
|
||||
{
|
||||
return raycaster.ColliderLinecast(eid, start, end);
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystem::ColliderLinecast(EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) noexcept
|
||||
{
|
||||
return raycaster.ColliderLinecast(eid, shapeIndex, start, end);
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::AddCollisionShape(EntityID eid, int shapeIndex)
|
||||
{
|
||||
static const auto ADD_SHAPE = [&](EntityID entityID, int index)
|
||||
{
|
||||
objectManager.AddCollisionShape(entityID, index);
|
||||
|
||||
auto* colliderComponent = SHComponentManager::GetComponent<SHColliderComponent>(entityID);
|
||||
auto& collisionShape = colliderComponent->GetCollisionShape(index);
|
||||
|
||||
const SHPhysicsColliderAddedEvent COLLIDER_ADDED_EVENT_DATA
|
||||
{
|
||||
.entityID = entityID
|
||||
, .colliderType = collisionShape.GetType()
|
||||
, .colliderIndex = index
|
||||
};
|
||||
|
||||
SHEventManager::BroadcastEvent<SHPhysicsColliderAddedEvent>(COLLIDER_ADDED_EVENT_DATA, SH_PHYSICS_COLLIDER_ADDED_EVENT);
|
||||
};
|
||||
|
||||
#ifdef SHEDITOR
|
||||
|
||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||
ADD_SHAPE(eid, shapeIndex);
|
||||
|
||||
#else
|
||||
|
||||
ADD_SHAPE(eid, shapeIndex);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::RemoveCollisionShape(EntityID eid, int shapeIndex)
|
||||
{
|
||||
static const auto REMOVE_SHAPE = [&](EntityID entityID, int index)
|
||||
{
|
||||
objectManager.RemoveCollisionShape(entityID, index);
|
||||
|
||||
const SHPhysicsColliderRemovedEvent COLLIDER_REMOVED_EVENT_DATA
|
||||
{
|
||||
.entityID = entityID
|
||||
, .colliderIndex = index
|
||||
};
|
||||
|
||||
SHEventManager::BroadcastEvent<SHPhysicsColliderRemovedEvent>(COLLIDER_REMOVED_EVENT_DATA, SH_PHYSICS_COLLIDER_REMOVED_EVENT);
|
||||
};
|
||||
|
||||
#ifdef SHEDITOR
|
||||
|
||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||
REMOVE_SHAPE(eid, shapeIndex);
|
||||
|
||||
#else
|
||||
|
||||
REMOVE_SHAPE(eid, shapeIndex);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHEventHandle SHPhysicsSystem::addPhysicsComponent(SHEventPtr addComponentEvent) noexcept
|
||||
SHEventHandle SHPhysicsSystem::onSceneInit(SHEventPtr onSceneInitEvent)
|
||||
{
|
||||
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentAddedEvent>*>(addComponentEvent.get());
|
||||
/*
|
||||
* If a world already exists, destroy it
|
||||
* Recreate the world.
|
||||
*
|
||||
* If there is an editor and editor mode is already playing, link all entities with the world immediately.
|
||||
*/
|
||||
|
||||
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
||||
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
||||
|
||||
const auto ADDED_ID = EVENT_DATA->data->addedComponentType;
|
||||
const bool IS_PHYSICS_COMPONENT = ADDED_ID == RIGID_BODY_ID || ADDED_ID == COLLIDER_ID;
|
||||
if (IS_PHYSICS_COMPONENT)
|
||||
// Destroy an existing world if there is one.
|
||||
//! This should almost never happen.
|
||||
if (worldState.world)
|
||||
{
|
||||
const EntityID EID = EVENT_DATA->data->eid;
|
||||
|
||||
// We only add tell the physics object manager to add a component if the scene is played
|
||||
|
||||
#ifdef SHEDITOR
|
||||
|
||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||
|
||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||
ADDED_ID == RIGID_BODY_ID ? objectManager.AddRigidBody(EID) : objectManager.AddCollider(EID);
|
||||
|
||||
#else
|
||||
|
||||
ADDED_ID == RIGID_BODY_ID ? objectManager.AddRigidBody(EID) : objectManager.AddCollider(EID);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
return EVENT_DATA->handle;
|
||||
}
|
||||
|
||||
SHEventHandle SHPhysicsSystem::removePhysicsComponent(SHEventPtr removeComponentEvent) noexcept
|
||||
{
|
||||
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentRemovedEvent>*>(removeComponentEvent.get());
|
||||
|
||||
static const auto RIGID_BODY_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
||||
static const auto COLLIDER_ID = ComponentFamily::GetID<SHColliderComponent>();
|
||||
|
||||
const auto REMOVED_ID = EVENT_DATA->data->removedComponentType;
|
||||
const bool IS_PHYSICS_COMPONENT = REMOVED_ID == RIGID_BODY_ID || REMOVED_ID == COLLIDER_ID;
|
||||
if (IS_PHYSICS_COMPONENT)
|
||||
{
|
||||
const EntityID EID = EVENT_DATA->data->eid;
|
||||
|
||||
// We only add tell the physics object manager to remove a component if the scene is played
|
||||
|
||||
#ifdef SHEDITOR
|
||||
|
||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||
|
||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||
REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID);
|
||||
|
||||
#else
|
||||
|
||||
REMOVED_ID == RIGID_BODY_ID ? objectManager.RemoveRigidBody(EID) : objectManager.RemoveCollider(EID);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
return EVENT_DATA->handle;
|
||||
}
|
||||
|
||||
SHEventHandle SHPhysicsSystem::onPlay(SHEventPtr onPlayEvent)
|
||||
{
|
||||
static const auto BUILD_PHYSICS_OBJECT = [&](SHSceneNode* node)
|
||||
{
|
||||
const EntityID EID = node->GetEntityID();
|
||||
|
||||
if (SHComponentManager::HasComponent<SHRigidBodyComponent>(EID))
|
||||
objectManager.AddRigidBody(EID);
|
||||
|
||||
if (SHComponentManager::HasComponent<SHColliderComponent>(EID))
|
||||
// Remove all references of physics objects from the world
|
||||
for (const auto& PHYSICS_OBJECT : objectManager.GetPhysicsObjects() | std::views::values)
|
||||
{
|
||||
objectManager.AddCollider(EID);
|
||||
if (PHYSICS_OBJECT.body)
|
||||
{
|
||||
// Remove all colliders and destroy world
|
||||
int32_t numShapes = static_cast<int32_t>(PHYSICS_OBJECT.body->getNbColliders());
|
||||
while (--numShapes >= 0)
|
||||
{
|
||||
auto* rp3dCollider = PHYSICS_OBJECT.body->getCollider(numShapes);
|
||||
PHYSICS_OBJECT.body->removeCollider(rp3dCollider);
|
||||
}
|
||||
|
||||
auto* COLLIDER = SHComponentManager::GetComponent<SHColliderComponent>(EID);
|
||||
for (size_t i = 0; i < COLLIDER->GetCollisionShapes().size(); ++i)
|
||||
objectManager.AddCollisionShape(EID, i);
|
||||
worldState.world->destroyRigidBody(PHYSICS_OBJECT.body);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
////////////////////////////////
|
||||
|
||||
// Create physics world
|
||||
if (worldState.world != nullptr)
|
||||
return onPlayEvent->handle;
|
||||
worldState.DestroyWorld(factory);
|
||||
}
|
||||
|
||||
// Create the physics world & collision space
|
||||
worldState.CreateWorld(factory);
|
||||
#ifdef _PUBLISH
|
||||
worldState.world->setIsDebugRenderingEnabled(false);
|
||||
#else
|
||||
worldState.world->setIsDebugRenderingEnabled(true);
|
||||
#endif
|
||||
|
||||
// Link Collision Listener & Raycaster
|
||||
// Link with managers
|
||||
objectManager.SetPhysicsWorld(worldState.world);
|
||||
objectManager.FlushDefinitions();
|
||||
|
||||
collisionListener.BindToWorld(worldState.world);
|
||||
raycaster.BindToWorld(worldState.world);
|
||||
|
||||
// Link with object manager & create all physics objects
|
||||
objectManager.SetWorld(worldState.world);
|
||||
|
||||
// Build scene
|
||||
SHSceneManager::GetCurrentSceneGraph().Traverse(BUILD_PHYSICS_OBJECT);
|
||||
objectManager.UpdateCommands();
|
||||
|
||||
return onPlayEvent->handle;
|
||||
return onSceneInitEvent.get()->handle;
|
||||
}
|
||||
|
||||
SHEventHandle SHPhysicsSystem::onStop(SHEventPtr onStopEvent)
|
||||
SHEventHandle SHPhysicsSystem::onSceneExit(SHEventPtr onSceneExitEvent)
|
||||
{
|
||||
// Remove all physics objects
|
||||
objectManager.RemoveAllObjects();
|
||||
objectManager.SetWorld(nullptr);
|
||||
/*
|
||||
* Destroy the physics world.
|
||||
* Destroy all physics objects.
|
||||
*/
|
||||
|
||||
// Clear all collision info
|
||||
// Collision listener is automatically unbound when world is destroyed
|
||||
collisionListener.ClearContainers();
|
||||
raycaster.ClearFrame();
|
||||
if (worldState.world)
|
||||
{
|
||||
// Remove all references of physics objects from the world
|
||||
for (const auto& PHYSICS_OBJECT : objectManager.GetPhysicsObjects() | std::views::values)
|
||||
{
|
||||
if (PHYSICS_OBJECT.body)
|
||||
worldState.world->destroyRigidBody(PHYSICS_OBJECT.body);
|
||||
}
|
||||
|
||||
// Destroy the world
|
||||
worldState.DestroyWorld(factory);
|
||||
worldState.DestroyWorld(factory);
|
||||
}
|
||||
|
||||
return onStopEvent->handle;
|
||||
// Unlink with managers
|
||||
objectManager.SetPhysicsWorld(nullptr);
|
||||
|
||||
return onSceneExitEvent.get()->handle;
|
||||
}
|
||||
|
||||
SHEventHandle SHPhysicsSystem::onComponentAdded(SHEventPtr onComponentAddedEvent)
|
||||
{
|
||||
static const auto RIGID_BODY_COMPONENT_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
||||
static const auto COLLIDER_COMPONENT_ID = ComponentFamily::GetID<SHColliderComponent>();
|
||||
|
||||
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentAddedEvent>*>(onComponentAddedEvent.get())->data;
|
||||
|
||||
const auto ADDED_ID = EVENT_DATA->addedComponentType;
|
||||
|
||||
const bool IS_RIGID_BODY = ADDED_ID == RIGID_BODY_COMPONENT_ID;
|
||||
const bool IS_COLLIDER = ADDED_ID == COLLIDER_COMPONENT_ID;
|
||||
|
||||
// Check if its a physics component
|
||||
const bool IS_PHYSICS_COMPONENT = IS_RIGID_BODY || IS_COLLIDER;
|
||||
if (!IS_PHYSICS_COMPONENT)
|
||||
return onComponentAddedEvent.get()->handle;
|
||||
|
||||
const EntityID EID = EVENT_DATA->eid;
|
||||
|
||||
// Link engine components with physics object component
|
||||
if (IS_RIGID_BODY)
|
||||
{
|
||||
if (worldState.world)
|
||||
objectManager.AddRigidBody(EID);
|
||||
else
|
||||
objectManager.AddRigidBodyDef(EID);
|
||||
}
|
||||
|
||||
if (IS_COLLIDER)
|
||||
{
|
||||
if (worldState.world)
|
||||
objectManager.AddCollider(EID);
|
||||
else
|
||||
objectManager.AddColliderDef(EID);
|
||||
}
|
||||
|
||||
return onComponentAddedEvent.get()->handle;
|
||||
}
|
||||
|
||||
SHEventHandle SHPhysicsSystem::onComponentRemoved(SHEventPtr onComponentRemovedEvent)
|
||||
{
|
||||
static const auto RIGID_BODY_COMPONENT_ID = ComponentFamily::GetID<SHRigidBodyComponent>();
|
||||
static const auto COLLIDER_COMPONENT_ID = ComponentFamily::GetID<SHColliderComponent>();
|
||||
|
||||
const auto& EVENT_DATA = reinterpret_cast<const SHEventSpec<SHComponentRemovedEvent>*>(onComponentRemovedEvent.get())->data;
|
||||
|
||||
const auto REMOVED_DATA = EVENT_DATA->removedComponentType;
|
||||
|
||||
const bool IS_RIGID_BODY = REMOVED_DATA == RIGID_BODY_COMPONENT_ID;
|
||||
const bool IS_COLLIDER = REMOVED_DATA == COLLIDER_COMPONENT_ID;
|
||||
|
||||
// Check if its a physics component
|
||||
const bool IS_PHYSICS_COMPONENT = IS_RIGID_BODY || IS_COLLIDER;
|
||||
if (!IS_PHYSICS_COMPONENT)
|
||||
return onComponentRemovedEvent.get()->handle;
|
||||
|
||||
const EntityID EID = EVENT_DATA->eid;
|
||||
|
||||
if (IS_RIGID_BODY)
|
||||
objectManager.RemoveRigidBody(EID);
|
||||
|
||||
if (IS_COLLIDER)
|
||||
objectManager.RemoveCollider(EID);
|
||||
|
||||
return onComponentRemovedEvent.get()->handle;
|
||||
}
|
||||
|
||||
} // namespace SHADE
|
|
@ -10,8 +10,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
// External Dependencies
|
||||
#include <reactphysics3d/reactphysics3d.h>
|
||||
|
@ -19,14 +18,11 @@
|
|||
// Project Headers
|
||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||
#include "ECS_Base/System/SHFixedSystemRoutine.h"
|
||||
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Physics/Collision/SHCollisionListener.h"
|
||||
#include "Physics/Collision/SHPhysicsRaycaster.h"
|
||||
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
#include "Physics/PhysicsObject/SHPhysicsObjectManager.h"
|
||||
#include "Physics/SHPhysicsWorld.h"
|
||||
#include "Physics/Collision/SHCollisionInfo.h"
|
||||
#include "Physics/Interface/PhysicsObject/SHPhysicsObjectManager.h"
|
||||
#include "Physics/RP3DWrapper/SHPhysicsWorld.h"
|
||||
#include "Physics/RP3DWrapper/SHCollisionListener.h"
|
||||
#include "Physics/RP3DWrapper/SHRaycaster.h"
|
||||
#include "Scene/SHSceneGraph.h"
|
||||
|
||||
namespace SHADE
|
||||
|
@ -43,254 +39,150 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHPhysicsDebugDrawSystem;
|
||||
friend class SHCollisionListener;
|
||||
friend class SHRaycaster;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsSystem();
|
||||
SHPhysicsSystem () noexcept;
|
||||
~SHPhysicsSystem() noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Getter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] double GetFixedUpdateRate () const noexcept;
|
||||
[[nodiscard]] const SHPhysicsWorldState::WorldSettings& GetWorldSettings () const noexcept;
|
||||
[[nodiscard]] double GetFixedUpdateRate () const noexcept;
|
||||
[[nodiscard]] double GetFixedDT () const noexcept;
|
||||
|
||||
[[nodiscard]] const std::vector<SHCollisionInfo>& GetAllCollisionInfo () const noexcept;
|
||||
[[nodiscard]] const std::vector<SHCollisionInfo>& GetAllTriggerInfo () const noexcept;
|
||||
[[nodiscard]] const std::vector<SHCollisionInfo>& GetAllTriggerInfo () const noexcept;
|
||||
[[nodiscard]] const std::vector<SHCollisionInfo>& GetAllCollisionInfo () const noexcept;
|
||||
|
||||
[[nodiscard]] const SHPhysicsObject* GetPhysicsObject (EntityID eid) noexcept;
|
||||
[[nodiscard]] const SHPhysicsObjectManager::PhysicsObjectEntityMap& GetPhysicsObjects () const noexcept;
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void SetFixedUpdateRate (double fixedUpdateRate) noexcept;
|
||||
void SetWorldSettings (const SHPhysicsWorldState::WorldSettings& settings) noexcept;
|
||||
|
||||
void SetFixedUpdateRate (double fixedUpdateRate) noexcept;
|
||||
void SetFixedDT (double fixedDt) noexcept;
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
void Init () override;
|
||||
void Exit () override;
|
||||
|
||||
void BuildScene (SHSceneGraph& sceneGraph);
|
||||
void ForceBuild (SHSceneGraph& sceneGraph);
|
||||
void ForceUpdate ();
|
||||
/**
|
||||
* @brief
|
||||
* - Initialises the static collision tag matrix.
|
||||
* - Registers the system to catch specific events.
|
||||
*/
|
||||
void Init() override;
|
||||
void Exit() override;
|
||||
|
||||
/**
|
||||
* @brief Casts a ray into the world.
|
||||
* @param ray The ray to cast.
|
||||
* @param distance The distance to cast the ray. Defaults to infinity.
|
||||
* @param collisionTag The collision tag to use for filtering the raycast.
|
||||
* @return The result of the raycast.
|
||||
*/
|
||||
SHPhysicsRaycastResult Raycast
|
||||
(
|
||||
const SHRay& ray
|
||||
, float distance = std::numeric_limits<float>::infinity()
|
||||
, const SHCollisionTag& collisionTag = SHCollisionTag{}
|
||||
) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Casts a bounded ray into the world.
|
||||
* @param start The starting point of the ray.
|
||||
* @param end The end point of the ray.
|
||||
* @param collisionTag The collision tag to use for filtering the bounded raycast.
|
||||
* @return The result of the raycast.
|
||||
*/
|
||||
SHPhysicsRaycastResult Linecast
|
||||
(
|
||||
const SHVec3& start
|
||||
, const SHVec3& end
|
||||
, const SHCollisionTag& collisionTag = SHCollisionTag{}
|
||||
) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Casts a ray at a body with colliders.
|
||||
* @param eid The entity to cast to.
|
||||
* @param ray The ray to cast.
|
||||
* @param distance The distance to cast the ray. Defaults to infinity.
|
||||
* @return The result of the raycast.
|
||||
*/
|
||||
SHPhysicsRaycastResult ColliderRaycast
|
||||
(
|
||||
EntityID eid
|
||||
, const SHRay& ray
|
||||
, float distance = std::numeric_limits<float>::infinity()
|
||||
) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Casts a ray at a collider.
|
||||
* @param eid The entity to cast to.
|
||||
* @param shapeIndex The index of the collision shape.
|
||||
* @param ray The ray to cast.
|
||||
* @param distance The distance to cast the ray. Defaults to infinity.
|
||||
* @return The result of the raycast.
|
||||
*/
|
||||
SHPhysicsRaycastResult ColliderRaycast
|
||||
(
|
||||
EntityID eid
|
||||
, int shapeIndex
|
||||
, const SHRay& ray
|
||||
, float distance = std::numeric_limits<float>::infinity()
|
||||
) noexcept;
|
||||
|
||||
/**
|
||||
* @brief Casts a bounded ray at a body with colliders.
|
||||
* @param eid
|
||||
* @param start
|
||||
* @param end
|
||||
* @return The result of the raycast.
|
||||
*/
|
||||
SHPhysicsRaycastResult ColliderLinecast
|
||||
(
|
||||
EntityID eid
|
||||
, const SHVec3& start
|
||||
, const SHVec3& end
|
||||
) noexcept;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @param eid
|
||||
* @param shapeIndex
|
||||
* @param start
|
||||
* @param end
|
||||
* @return The result of the raycast.
|
||||
*/
|
||||
SHPhysicsRaycastResult ColliderLinecast
|
||||
(
|
||||
EntityID eid
|
||||
, int shapeIndex
|
||||
, const SHVec3& start
|
||||
, const SHVec3& end
|
||||
) noexcept;
|
||||
|
||||
// Specific Handling for Collision Shapes as they are not under the Component System.
|
||||
// This is done as events need to be sent out.
|
||||
// TODO(Diren): Consider using a static method through the ColliderComponent.
|
||||
|
||||
void AddCollisionShape (EntityID eid, int shapeIndex);
|
||||
void RemoveCollisionShape (EntityID eid, int shapeIndex);
|
||||
* @brief
|
||||
* Casts a ray into the collision space.
|
||||
* @param info
|
||||
* Contains the information for the raycast.
|
||||
* @return
|
||||
* A container of the objects hit by the ray. If nothing was hit, the container
|
||||
* will be empty.
|
||||
*/
|
||||
[[nodiscard]] const std::vector<SHPhysicsRaycastResult>& Raycast(const SHRaycaster::RaycastInfo& info) noexcept;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* System Routines */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* The physics update routine that runs before the simulation is updated.
|
||||
* This is always running, regardless of the editor state.
|
||||
* <br/>
|
||||
* This update game logic is applied before the simulation runs.
|
||||
*/
|
||||
class SH_API PhysicsPreUpdate final : public SHSystemRoutine
|
||||
{
|
||||
public:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
PhysicsPreUpdate();
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
void Execute(double dt) noexcept override;
|
||||
|
||||
private:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
void syncRigidBodyActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept;
|
||||
void syncColliderActive (EntityID eid, SHPhysicsObject& physicsObject) const noexcept;
|
||||
static void syncOnPlay (EntityID eid, SHPhysicsObject& physicsObject) noexcept;
|
||||
|
||||
static void preUpdateSyncTransform
|
||||
(
|
||||
SHPhysicsObject& physicsObject
|
||||
, SHTransformComponent* transformComponent
|
||||
, SHRigidBodyComponent* rigidBodyComponent
|
||||
, SHColliderComponent* colliderComponent
|
||||
) noexcept;
|
||||
};
|
||||
|
||||
class SH_API PhysicsFixedUpdate final : public SHFixedSystemRoutine
|
||||
/**
|
||||
* @brief
|
||||
* The physics update routine that runs at a fixed rate. This is where the main
|
||||
* simulation runs. If delta time is large enough, this may run more than once per
|
||||
* frame. If delta time is small enough, this may not run at all.
|
||||
*/
|
||||
class SH_API PhysicsUpdate final : public SHFixedSystemRoutine
|
||||
{
|
||||
public:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
PhysicsFixedUpdate();
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
void Execute (double dt) noexcept override;
|
||||
PhysicsUpdate();
|
||||
void Execute(double dt) noexcept override;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* The physics update that runs after the simulation. This sets the rendering
|
||||
* transforms and sends messages to scripting system for collision & trigger events. <br/>
|
||||
*
|
||||
*/
|
||||
class SH_API PhysicsPostUpdate final : public SHSystemRoutine
|
||||
{
|
||||
public:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
PhysicsPostUpdate();
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
void Execute(double dt) noexcept override;
|
||||
|
||||
private:
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
static void postUpdateSyncTransforms
|
||||
(
|
||||
SHPhysicsObject& physicsObject
|
||||
, SHTransformComponent* transformComponent
|
||||
, SHRigidBodyComponent* rigidBodyComponent
|
||||
, SHColliderComponent* colliderComponent
|
||||
, double interpolationFactor
|
||||
) noexcept;
|
||||
};
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
using EventFunctionPair = std::pair<SHEventHandle(SHPhysicsSystem::*)(SHEventPtr), SHEventIdentifier>;
|
||||
|
||||
struct RaycastHit
|
||||
{
|
||||
SHVec3 start;
|
||||
SHVec3 end;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
// System data
|
||||
static constexpr int NUM_EVENT_FUNCTIONS = 4;
|
||||
|
||||
// Event function container for cleanly registering to events
|
||||
EventFunctionPair eventFunctions[NUM_EVENT_FUNCTIONS];
|
||||
|
||||
// System data
|
||||
bool worldUpdated;
|
||||
double interpolationFactor;
|
||||
double fixedDT;
|
||||
|
||||
// rp3d
|
||||
// Sub-systems / managers
|
||||
|
||||
rp3d::PhysicsCommon factory;
|
||||
|
||||
// Interface objects
|
||||
|
||||
SHPhysicsWorldState worldState;
|
||||
SHPhysicsObjectManager objectManager;
|
||||
SHCollisionListener collisionListener;
|
||||
SHPhysicsRaycaster raycaster;
|
||||
SHRaycaster raycaster;
|
||||
|
||||
// For the debug drawer to draw rays
|
||||
#ifdef SHEDITOR
|
||||
std::vector<RaycastHit> raycastHits;
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Function Members */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
SHEventHandle addPhysicsComponent (SHEventPtr addComponentEvent) noexcept;
|
||||
SHEventHandle removePhysicsComponent (SHEventPtr removeComponentEvent) noexcept;
|
||||
SHEventHandle onSceneInit (SHEventPtr onSceneInitEvent);
|
||||
SHEventHandle onSceneExit (SHEventPtr onSceneExitEvent);
|
||||
|
||||
SHEventHandle onPlay (SHEventPtr onPlayEvent);
|
||||
SHEventHandle onStop (SHEventPtr onStopEvent);
|
||||
SHEventHandle buildScene (SHEventPtr onSceneChangeEvent);
|
||||
SHEventHandle onComponentAdded (SHEventPtr onComponentAddedEvent);
|
||||
SHEventHandle onComponentRemoved (SHEventPtr onComponentRemovedEvent);
|
||||
};
|
||||
} // namespace SHADE
|
|
@ -52,85 +52,43 @@ namespace SHADE
|
|||
|
||||
double SHPhysicsSystemInterface::GetFixedDT() noexcept
|
||||
{
|
||||
auto phySystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (phySystem)
|
||||
{
|
||||
return 1.0 / phySystem->GetFixedUpdateRate();
|
||||
}
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (physicsSystem)
|
||||
return physicsSystem->GetFixedDT();
|
||||
|
||||
SHLOGV_WARNING("Failed to get fixed delta time. 0.0 returned instead.");
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::Raycast(const SHRay& ray, float distance) noexcept
|
||||
int SHPhysicsSystemInterface::GetFixedUpdateRate() noexcept
|
||||
{
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (physicsSystem)
|
||||
{
|
||||
return physicsSystem->Raycast(ray, distance);
|
||||
}
|
||||
return physicsSystem->GetFixedUpdateRate();
|
||||
|
||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
||||
return SHPhysicsRaycastResult{};
|
||||
SHLOGV_WARNING("Failed to get fixed update rate. 0.0 returned instead.");
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::Linecast(const SHVec3& start, const SHVec3& end) noexcept
|
||||
const std::vector<SHPhysicsRaycastResult>& SHPhysicsSystemInterface::Raycast(const RaycastInfo& info) noexcept
|
||||
{
|
||||
static std::vector<SHPhysicsRaycastResult> emptyVec;
|
||||
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (physicsSystem)
|
||||
{
|
||||
return physicsSystem->Linecast(start, end);
|
||||
SHRaycaster::RaycastInfo raycastInfo;
|
||||
raycastInfo.continuous = info.continuous;
|
||||
raycastInfo.distance = info.distance;
|
||||
raycastInfo.layers = info.layers;
|
||||
raycastInfo.ray = info.ray;
|
||||
|
||||
if (info.colliderEntityID.has_value())
|
||||
raycastInfo.SetColliderID(info.colliderEntityID.value());
|
||||
|
||||
return physicsSystem->Raycast(raycastInfo);
|
||||
}
|
||||
|
||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
||||
return SHPhysicsRaycastResult{};
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::ColliderRaycast(EntityID eid, const SHRay& ray, float distance) noexcept
|
||||
{
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (physicsSystem)
|
||||
{
|
||||
return physicsSystem->ColliderRaycast(eid, ray, distance);
|
||||
}
|
||||
|
||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
||||
return SHPhysicsRaycastResult{};
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::ColliderRaycast(EntityID eid, int shapeIndex, const SHRay& ray, float distance) noexcept
|
||||
{
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (physicsSystem)
|
||||
{
|
||||
return physicsSystem->ColliderRaycast(eid, shapeIndex, ray, distance);
|
||||
}
|
||||
|
||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
||||
return SHPhysicsRaycastResult{};
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::ColliderLinecast(EntityID eid, const SHVec3& start, const SHVec3& end) noexcept
|
||||
{
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (physicsSystem)
|
||||
{
|
||||
return physicsSystem->ColliderLinecast(eid, start, end);
|
||||
}
|
||||
|
||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
||||
return SHPhysicsRaycastResult{};
|
||||
}
|
||||
|
||||
SHPhysicsRaycastResult SHPhysicsSystemInterface::ColliderLinecast(EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) noexcept
|
||||
{
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
if (physicsSystem)
|
||||
{
|
||||
return physicsSystem->ColliderLinecast(eid, shapeIndex, start, end);
|
||||
}
|
||||
|
||||
SHLOGV_WARNING("Failed to get the physics system. No ray was casted.");
|
||||
return SHPhysicsRaycastResult{};
|
||||
return emptyVec;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,11 +12,13 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#pragma once
|
||||
|
||||
// STL Includes
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
// Project Headers
|
||||
#include "ECS_Base/Entity/SHEntity.h"
|
||||
|
||||
#include "Math/SHRay.h"
|
||||
#include "Physics/Collision/CollisionTags/SHCollisionTags.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -25,11 +27,8 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
class SHCollisionInfo;
|
||||
class SHVec3;
|
||||
struct SHRay;
|
||||
struct SHPhysicsRaycastResult;
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -39,7 +38,49 @@ namespace SHADE
|
|||
/// </summary>
|
||||
class SH_API SHPhysicsSystemInterface final
|
||||
{
|
||||
public:
|
||||
|
||||
struct RaycastInfo
|
||||
{
|
||||
private:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Friends */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
friend class SHPhysicsSystemInterface;
|
||||
|
||||
public:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
bool continuous = false;
|
||||
uint16_t layers = static_cast<uint16_t>(SHCollisionTag::Layer::ALL);
|
||||
float distance = std::numeric_limits<float>::infinity();
|
||||
SHRay ray;
|
||||
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Setter Functions */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Sets the collider ID for the raycast. Setting this specifies that the ray
|
||||
* should ignore this collider.
|
||||
* @param eid
|
||||
* The entity ID of the collider.
|
||||
*/
|
||||
void SetColliderID(EntityID eid) noexcept { colliderEntityID = eid; }
|
||||
|
||||
private:
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
/* Data Members */
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
|
||||
std::optional<EntityID> colliderEntityID;
|
||||
};
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructor */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -49,15 +90,11 @@ namespace SHADE
|
|||
/* Static Usage Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetCollisionInfo() noexcept;
|
||||
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetTriggerInfo () noexcept;
|
||||
[[nodiscard]] static double GetFixedDT () noexcept;
|
||||
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetCollisionInfo () noexcept;
|
||||
[[nodiscard]] static const std::vector<SHCollisionInfo>& GetTriggerInfo () noexcept;
|
||||
[[nodiscard]] static double GetFixedDT () noexcept;
|
||||
[[nodiscard]] static int GetFixedUpdateRate () noexcept;
|
||||
[[nodiscard]] static const std::vector<SHPhysicsRaycastResult>& Raycast (const RaycastInfo& info) noexcept;
|
||||
|
||||
[[nodiscard]] static SHPhysicsRaycastResult Raycast (const SHRay& ray, float distance = std::numeric_limits<float>::infinity()) noexcept;
|
||||
[[nodiscard]] static SHPhysicsRaycastResult Linecast (const SHVec3& start, const SHVec3& end) noexcept;
|
||||
[[nodiscard]] static SHPhysicsRaycastResult ColliderRaycast (EntityID eid, const SHRay& ray, float distance = std::numeric_limits<float>::infinity()) noexcept;
|
||||
[[nodiscard]] static SHPhysicsRaycastResult ColliderRaycast (EntityID eid, int shapeIndex, const SHRay& ray, float distance = std::numeric_limits<float>::infinity()) noexcept;
|
||||
[[nodiscard]] static SHPhysicsRaycastResult ColliderLinecast (EntityID eid, const SHVec3& start, const SHVec3& end) noexcept;
|
||||
[[nodiscard]] static SHPhysicsRaycastResult ColliderLinecast (EntityID eid, int shapeIndex, const SHVec3& start, const SHVec3& end) noexcept;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,412 +0,0 @@
|
|||
/****************************************************************************************
|
||||
* \file SHPhysicsSystemRoutines.h
|
||||
* \author Diren D Bharwani, diren.dbharwani, 390002520
|
||||
* \brief Implementation for the Physics System Routines
|
||||
*
|
||||
* \copyright Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
****************************************************************************************/
|
||||
|
||||
#include <SHpch.h>
|
||||
|
||||
// Primary Header
|
||||
#include "SHPhysicsSystem.h"
|
||||
// Project Headers
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Editor/SHEditor.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
|
||||
#include "Input/SHInputManager.h"
|
||||
#include "Physics/Collision/SHCollisionTagMatrix.h"
|
||||
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
/* Local Functions */
|
||||
/*-------------------------------------------------------------------------------------*/
|
||||
|
||||
void testFunction();
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors & Destructor Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
SHPhysicsSystem::PhysicsPreUpdate::PhysicsPreUpdate()
|
||||
: SHSystemRoutine { "Physics PreUpdate", true }
|
||||
{}
|
||||
|
||||
SHPhysicsSystem::PhysicsFixedUpdate::PhysicsFixedUpdate()
|
||||
: SHFixedSystemRoutine { DEFAULT_FIXED_STEP, "Physics FixedUpdate", false }
|
||||
{}
|
||||
|
||||
SHPhysicsSystem::PhysicsPostUpdate::PhysicsPostUpdate()
|
||||
: SHSystemRoutine { "Physics PostUpdate", false }
|
||||
{}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Public Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsSystem::PhysicsPreUpdate::Execute(double) noexcept
|
||||
{
|
||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||
|
||||
#ifdef SHEDITOR
|
||||
|
||||
// Only Sync on Play.
|
||||
// Otherwise, Components are only holding data until the world is built on play.
|
||||
const auto* EDITOR = SHSystemManager::GetSystem<SHEditor>();
|
||||
if (EDITOR && EDITOR->editorState != SHEditor::State::STOP)
|
||||
{
|
||||
physicsSystem->objectManager.UpdateCommands();
|
||||
|
||||
for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects)
|
||||
{
|
||||
// Ensure a valid physics Object
|
||||
if (physicsObject.rp3dBody == nullptr)
|
||||
continue;
|
||||
|
||||
// Sync active states between SHADE & RP3D
|
||||
syncRigidBodyActive(entityID, physicsObject);
|
||||
syncColliderActive(entityID, physicsObject);
|
||||
|
||||
syncOnPlay(entityID, physicsObject);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& rigidBodyDense = SHComponentManager::GetDense<SHRigidBodyComponent>();
|
||||
auto& colliderDense = SHComponentManager::GetDense<SHColliderComponent>();
|
||||
|
||||
for (auto& rigidBodyComponent : rigidBodyDense)
|
||||
{
|
||||
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(rigidBodyComponent.GetEID());
|
||||
|
||||
if (TRANSFORM && TRANSFORM->HasChanged())
|
||||
{
|
||||
rigidBodyComponent.position = TRANSFORM->GetWorldPosition();
|
||||
rigidBodyComponent.orientation = TRANSFORM->GetWorldOrientation();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& colliderComponent : colliderDense)
|
||||
{
|
||||
const auto* TRANSFORM = SHComponentManager::GetComponent_s<SHTransformComponent>(colliderComponent.GetEID());
|
||||
|
||||
if (TRANSFORM && TRANSFORM->HasChanged())
|
||||
{
|
||||
colliderComponent.position = TRANSFORM->GetWorldPosition();
|
||||
colliderComponent.orientation = TRANSFORM->GetWorldOrientation();
|
||||
colliderComponent.scale = TRANSFORM->GetWorldScale();
|
||||
|
||||
colliderComponent.RecomputeCollisionShapes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
// Always sync Rigid Body & Collider Components with Physics Objects
|
||||
// Do not check for an editor here
|
||||
|
||||
physicsSystem->objectManager.UpdateCommands();
|
||||
|
||||
for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects)
|
||||
{
|
||||
// Ensure a valid physics Object
|
||||
if (physicsObject.rp3dBody == nullptr)
|
||||
continue;
|
||||
|
||||
syncRigidBodyActive(entityID, physicsObject);
|
||||
syncColliderActive(entityID, physicsObject);
|
||||
|
||||
syncOnPlay(entityID, physicsObject);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::PhysicsFixedUpdate::Execute(double dt) noexcept
|
||||
{
|
||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||
if (scriptingSystem == nullptr)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to invoke FixedUpdate() on scripts due to missing SHScriptEngine!");
|
||||
}
|
||||
|
||||
const double FIXED_DT = physicsSystem->fixedDT;
|
||||
// HACK: Clamp DT here to prevent a ridiculous amount of updates. This limits updates from large dt to 2.
|
||||
// HACK: This should be done by the FRC and not here for predictable behaviour.
|
||||
|
||||
accumulatedTime += dt;
|
||||
|
||||
//testFunction();
|
||||
|
||||
int count = 0;
|
||||
while (accumulatedTime > FIXED_DT)
|
||||
{
|
||||
if (scriptingSystem != nullptr)
|
||||
scriptingSystem->ExecuteFixedUpdates();
|
||||
|
||||
physicsSystem->worldState.world->update(static_cast<rp3d::decimal>(FIXED_DT));
|
||||
|
||||
accumulatedTime -= FIXED_DT;
|
||||
++count;
|
||||
}
|
||||
|
||||
stats.numSteps = count;
|
||||
physicsSystem->worldUpdated = count > 0;
|
||||
|
||||
physicsSystem->interpolationFactor = accumulatedTime / fixedTimeStep;
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::PhysicsPostUpdate::Execute(double) noexcept
|
||||
{
|
||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||
auto* scriptingSystem = SHSystemManager::GetSystem<SHScriptEngine>();
|
||||
|
||||
if (scriptingSystem == nullptr)
|
||||
{
|
||||
SHLOGV_ERROR("Unable to invoke collision and trigger script events due to missing SHScriptEngine!");
|
||||
}
|
||||
|
||||
// Interpolate transforms for rendering
|
||||
if (physicsSystem->worldUpdated)
|
||||
{
|
||||
for (auto& [entityID, physicsObject] : physicsSystem->objectManager.physicsObjects)
|
||||
{
|
||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(entityID);
|
||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(entityID);
|
||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(entityID);
|
||||
|
||||
postUpdateSyncTransforms
|
||||
(
|
||||
physicsObject
|
||||
, transformComponent
|
||||
, rigidBodyComponent
|
||||
, colliderComponent
|
||||
, physicsSystem->interpolationFactor
|
||||
);
|
||||
}
|
||||
|
||||
// Collision & Trigger messages
|
||||
if (scriptingSystem != nullptr)
|
||||
scriptingSystem->ExecuteCollisionFunctions();
|
||||
|
||||
// Since this function never runs when editor in not in play, execute the function anyway
|
||||
physicsSystem->collisionListener.CleanContainers();
|
||||
}
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Private Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void SHPhysicsSystem::PhysicsPreUpdate::syncRigidBodyActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept
|
||||
{
|
||||
if (!SHComponentManager::HasComponent<SHRigidBodyComponent>(eid))
|
||||
return;
|
||||
|
||||
const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(eid);
|
||||
const bool IS_RP3D_BODY_ACTIVE = physicsObject.GetRigidBody()->isActive();
|
||||
|
||||
if (IS_ACTIVE_IN_SCENE != IS_RP3D_BODY_ACTIVE)
|
||||
physicsObject.GetRigidBody()->setIsActive(IS_ACTIVE_IN_SCENE);
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::PhysicsPreUpdate::syncColliderActive(EntityID eid, SHPhysicsObject& physicsObject) const noexcept
|
||||
{
|
||||
const auto* COLLIDER = SHComponentManager::GetComponent_s<SHColliderComponent>(eid);
|
||||
if (!COLLIDER)
|
||||
return;
|
||||
|
||||
const bool IS_ACTIVE_IN_SCENE = SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(eid);
|
||||
const bool IS_RP3D_COLLIDER_ACTIVE = physicsObject.collidersActive;
|
||||
|
||||
if (IS_ACTIVE_IN_SCENE != IS_RP3D_COLLIDER_ACTIVE)
|
||||
{
|
||||
// HACK: If active state turned off, remove all collision shapes. If turned on, add them back.
|
||||
auto* physicsSystem = reinterpret_cast<SHPhysicsSystem*>(GetSystem());
|
||||
|
||||
const int NUM_SHAPES = static_cast<int>(COLLIDER->GetCollisionShapes().size());
|
||||
if (IS_ACTIVE_IN_SCENE)
|
||||
{
|
||||
for (int i = 0; i < NUM_SHAPES; ++i)
|
||||
physicsSystem->objectManager.AddCollisionShape(eid, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = NUM_SHAPES - 1; i >= 0; --i)
|
||||
physicsSystem->objectManager.RemoveCollisionShape(eid, i);
|
||||
}
|
||||
|
||||
physicsObject.collidersActive = IS_ACTIVE_IN_SCENE;
|
||||
}
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::PhysicsPreUpdate::syncOnPlay(EntityID eid, SHPhysicsObject& physicsObject) noexcept
|
||||
{
|
||||
auto* transformComponent = SHComponentManager::GetComponent_s<SHTransformComponent>(eid);
|
||||
auto* rigidBodyComponent = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid);
|
||||
auto* colliderComponent = SHComponentManager::GetComponent_s<SHColliderComponent>(eid);
|
||||
|
||||
// Sync transforms & physics components transforms
|
||||
if (transformComponent && transformComponent->HasChanged())
|
||||
{
|
||||
physicsObject.GetRigidBody()->setIsSleeping(false);
|
||||
|
||||
preUpdateSyncTransform
|
||||
(
|
||||
physicsObject
|
||||
, transformComponent
|
||||
, rigidBodyComponent
|
||||
, colliderComponent
|
||||
);
|
||||
}
|
||||
|
||||
// Sync Rigid Bodies
|
||||
if (rigidBodyComponent)
|
||||
physicsObject.SyncRigidBody(*rigidBodyComponent);
|
||||
|
||||
// Sync Colliders
|
||||
if (colliderComponent)
|
||||
physicsObject.SyncColliders(*colliderComponent);
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::PhysicsPreUpdate::preUpdateSyncTransform
|
||||
(
|
||||
SHPhysicsObject& physicsObject
|
||||
, SHTransformComponent* transformComponent
|
||||
, SHRigidBodyComponent* rigidBodyComponent
|
||||
, SHColliderComponent* colliderComponent
|
||||
) noexcept
|
||||
{
|
||||
if (!transformComponent)
|
||||
return;
|
||||
|
||||
const SHVec3& WORLD_POS = transformComponent->GetWorldPosition();
|
||||
const SHQuaternion& WORLD_ROT = transformComponent->GetWorldOrientation();
|
||||
const SHVec3& WORLD_SCL = transformComponent->GetWorldScale();
|
||||
|
||||
const rp3d::Transform RP3D_TRANSFORM { WORLD_POS, WORLD_ROT };
|
||||
physicsObject.GetRigidBody()->setTransform(RP3D_TRANSFORM);
|
||||
physicsObject.prevTransform = RP3D_TRANSFORM;
|
||||
|
||||
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
|
||||
{
|
||||
rigidBodyComponent->position = WORLD_POS;
|
||||
rigidBodyComponent->orientation = WORLD_ROT;
|
||||
}
|
||||
|
||||
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
|
||||
{
|
||||
colliderComponent->position = WORLD_POS;
|
||||
colliderComponent->orientation = WORLD_ROT;
|
||||
colliderComponent->scale = WORLD_SCL;
|
||||
|
||||
colliderComponent->RecomputeCollisionShapes();
|
||||
}
|
||||
}
|
||||
|
||||
void SHPhysicsSystem::PhysicsPostUpdate::postUpdateSyncTransforms
|
||||
(
|
||||
SHPhysicsObject& physicsObject
|
||||
, SHTransformComponent* transformComponent
|
||||
, SHRigidBodyComponent* rigidBodyComponent
|
||||
, SHColliderComponent* colliderComponent
|
||||
, double interpolationFactor
|
||||
) noexcept
|
||||
{
|
||||
const rp3d::Transform& CURRENT_TF = physicsObject.GetRigidBody()->getTransform();
|
||||
auto renderPos = CURRENT_TF.getPosition();
|
||||
auto renderRot = CURRENT_TF.getOrientation();
|
||||
|
||||
// Cache transforms
|
||||
if (physicsObject.GetRigidBody()->isActive())
|
||||
physicsObject.prevTransform = CURRENT_TF;
|
||||
|
||||
// Sync with rigid bodies
|
||||
if (rigidBodyComponent && SHSceneManager::CheckNodeAndComponentsActive<SHRigidBodyComponent>(physicsObject.entityID))
|
||||
{
|
||||
// Skip static bodies
|
||||
if (rigidBodyComponent->GetType() == SHRigidBodyComponent::Type::STATIC)
|
||||
return;
|
||||
|
||||
// Check if transform should be interpolated
|
||||
if (rigidBodyComponent->IsInterpolating())
|
||||
{
|
||||
// Interpolate transforms between current and predicted next transform
|
||||
|
||||
const rp3d::Transform PREV_TF = physicsObject.prevTransform;
|
||||
const rp3d::Transform INTERPOLATED_TF = rp3d::Transform::interpolateTransforms(PREV_TF, CURRENT_TF, static_cast<rp3d::decimal>(interpolationFactor));
|
||||
|
||||
renderPos = INTERPOLATED_TF.getPosition();
|
||||
renderRot = INTERPOLATED_TF.getOrientation();
|
||||
}
|
||||
|
||||
rigidBodyComponent->position = CURRENT_TF.getPosition();
|
||||
rigidBodyComponent->orientation = CURRENT_TF.getOrientation();
|
||||
|
||||
// Sync with colliders
|
||||
if (colliderComponent && SHSceneManager::CheckNodeAndComponentsActive<SHColliderComponent>(physicsObject.entityID))
|
||||
{
|
||||
// Skip colliders without rigidbody components. If any transform was updated, it was done in pre-update.
|
||||
|
||||
colliderComponent->position = CURRENT_TF.getPosition();
|
||||
colliderComponent->orientation = CURRENT_TF.getOrientation();
|
||||
}
|
||||
|
||||
// Set transform for rendering
|
||||
if (transformComponent)
|
||||
{
|
||||
transformComponent->SetWorldPosition(renderPos);
|
||||
transformComponent->SetWorldOrientation(renderRot);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace SHADE
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void testFunction()
|
||||
{
|
||||
using namespace SHADE;
|
||||
|
||||
// Test movement
|
||||
const float forceModifier = 25.0f;
|
||||
EntityID eid = 65538;
|
||||
|
||||
if (SHEntityManager::IsValidEID(eid))
|
||||
{
|
||||
auto* rb = SHComponentManager::GetComponent_s<SHRigidBodyComponent>(eid);
|
||||
if (rb)
|
||||
{
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::W))
|
||||
rb->AddForce(SHVec3::UnitZ * forceModifier);
|
||||
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::A))
|
||||
rb->AddForce(-SHVec3::UnitX * forceModifier);
|
||||
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::S))
|
||||
rb->AddForce(-SHVec3::UnitZ * forceModifier);
|
||||
|
||||
if (SHInputManager::GetKey(SHInputManager::SH_KEYCODE::D))
|
||||
rb->AddForce(SHVec3::UnitX * forceModifier);
|
||||
}
|
||||
}
|
||||
|
||||
// Cast rays
|
||||
auto* tag = SHCollisionTagMatrix::GetTag(1);
|
||||
tag->SetLayerState(SHCollisionTag::Layer::_1, false);
|
||||
tag->SetLayerState(SHCollisionTag::Layer::_2, true);
|
||||
|
||||
SHRay ray { SHVec3{3.0f, 3.5f, 0.0f}, -SHVec3::UnitX };
|
||||
auto* physicsSystem = SHSystemManager::GetSystem<SHPhysicsSystem>();
|
||||
physicsSystem->Raycast(ray, std::numeric_limits<float>::infinity(), *tag);
|
||||
}
|
|
@ -3,9 +3,8 @@
|
|||
#include "Physics/Interface/SHColliderComponent.h"
|
||||
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
|
||||
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||
#include "Math/Geometry/SHBox.h"
|
||||
#include "Math/Geometry/SHSphere.h"
|
||||
#include "Physics/Interface/SHCollisionShape.h"
|
||||
#include "Physics/Collision/Shapes/SHSphere.h"
|
||||
#include "Physics/Collision/Shapes/SHBox.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
#include "Math/Vector/SHVec2.h"
|
||||
#include "Math/Vector/SHVec3.h"
|
||||
|
@ -15,7 +14,7 @@
|
|||
#include "SHSerializationTools.h"
|
||||
#include "Graphics/MiddleEnd/TextRendering/SHFont.h"
|
||||
#include "Animation/SHAnimatorComponent.h"
|
||||
#include "Physics/Collision/SHCollisionTagMatrix.h"
|
||||
#include "Physics/Collision/CollisionTags/SHCollisionTagMatrix.h"
|
||||
|
||||
namespace YAML
|
||||
{
|
||||
|
@ -149,17 +148,17 @@ namespace YAML
|
|||
{
|
||||
case SHCollisionShape::Type::BOX:
|
||||
{
|
||||
const auto* BOX = reinterpret_cast<const SHBox*>(rhs.GetShape());
|
||||
node[HalfExtents] = BOX->GetRelativeExtents();
|
||||
const auto& BOX_SHAPE = dynamic_cast<SHBox&>(rhs);
|
||||
node[HalfExtents] = BOX_SHAPE.GetRelativeExtents();
|
||||
}
|
||||
break;
|
||||
case SHCollisionShape::Type::SPHERE:
|
||||
{
|
||||
const auto* SPHERE = reinterpret_cast<const SHSphere*>(rhs.GetShape());
|
||||
node[Radius] = SPHERE->GetRelativeRadius();
|
||||
const auto& SPHERE_SHAPE = dynamic_cast<SHSphere&>(rhs);
|
||||
node[Radius] = SPHERE_SHAPE.GetRelativeRadius();
|
||||
}
|
||||
break;
|
||||
case SHCollisionShape::Type::CAPSULE: break;
|
||||
//case SHCollisionShape::Type::CAPSULE: break;
|
||||
default:;
|
||||
}
|
||||
|
||||
|
@ -192,16 +191,16 @@ namespace YAML
|
|||
case SHCollisionShape::Type::BOX:
|
||||
{
|
||||
if (node[HalfExtents].IsDefined())
|
||||
rhs.SetBoundingBox(node[HalfExtents].as<SHVec3>());
|
||||
dynamic_cast<SHBox&>(rhs).SetRelativeExtents(node[HalfExtents].as<SHVec3>());
|
||||
}
|
||||
break;
|
||||
case SHCollisionShape::Type::SPHERE:
|
||||
{
|
||||
if (node[Radius].IsDefined())
|
||||
rhs.SetBoundingSphere(node[Radius].as<float>());
|
||||
dynamic_cast<SHSphere&>(rhs).SetRelativeRadius(node[Radius].as<float>());
|
||||
}
|
||||
break;
|
||||
case SHCollisionShape::Type::CAPSULE: break;
|
||||
//case SHCollisionShape::Type::CAPSULE: break;
|
||||
default:;
|
||||
}
|
||||
if (node[Friction].IsDefined())
|
||||
|
@ -254,9 +253,9 @@ namespace YAML
|
|||
|
||||
switch (colliderType)
|
||||
{
|
||||
case SHCollisionShape::Type::BOX: rhs.AddBoundingBox(); break;
|
||||
case SHCollisionShape::Type::SPHERE: rhs.AddBoundingSphere(); break;
|
||||
case SHCollisionShape::Type::CAPSULE: break;
|
||||
case SHCollisionShape::Type::BOX: rhs.AddBoxCollisionShape(SHVec3::One); break;
|
||||
case SHCollisionShape::Type::SPHERE: rhs.AddSphereCollisionShape(1.0f); break;
|
||||
//case SHCollisionShape::Type::CAPSULE: break;
|
||||
default:;
|
||||
}
|
||||
YAML::convert<SHCollisionShape>::decode(colliderNode, rhs.GetCollisionShape(numColliders++));
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Oct 20, 2022
|
||||
\brief Contains the definition of the functions of the managed Collider class.
|
||||
|
||||
Note: This file is written in C++17/CLI.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
|
@ -15,11 +14,14 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "SHpch.h"
|
||||
// Primary Header
|
||||
#include "Collider.hxx"
|
||||
|
||||
#include "Physics/Collision/Shapes/SHBox.h"
|
||||
#include "Physics/Collision/Shapes/SHSphere.h"
|
||||
#include "Utility/Debug.hxx"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* CollisionShape - Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
CollisionShape::CollisionShape(int arrayIdx, Entity attachedEntity)
|
||||
|
@ -120,7 +122,7 @@ namespace SHADE
|
|||
/* BoxCollider - Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
BoxCollider::BoxCollider(int arrayIdx, Entity attachedEntity)
|
||||
: CollisionShape { arrayIndex, attachedEntity }
|
||||
: CollisionShape { arrayIdx, attachedEntity }
|
||||
{}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -128,35 +130,20 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
Vector3 BoxCollider::Center::get()
|
||||
{
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetCenter());
|
||||
}
|
||||
void BoxCollider::Center::set(Vector3 value)
|
||||
{
|
||||
getNativeCollisionShape<SHBox>().SetCenter(Convert::ToNative(value));
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetWorldCentroid());
|
||||
}
|
||||
Vector3 BoxCollider::HalfExtents::get()
|
||||
{
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetWorldExtents());
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetWorldExtents());
|
||||
}
|
||||
void BoxCollider::HalfExtents::set(Vector3 value)
|
||||
{
|
||||
getNativeCollisionShape<SHBox>().SetWorldExtents(Convert::ToNative(value));
|
||||
getNativeCollisionShape<SHBox>().SetWorldExtents(Convert::ToNative(value));
|
||||
}
|
||||
Vector3 BoxCollider::Min::get()
|
||||
Quaternion BoxCollider::Orientation::get()
|
||||
{
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetMin());
|
||||
}
|
||||
void BoxCollider::Min::set(Vector3 value)
|
||||
{
|
||||
getNativeCollisionShape<SHBox>().SetMin(Convert::ToNative(value));
|
||||
}
|
||||
Vector3 BoxCollider::Max::get()
|
||||
{
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetMax());
|
||||
}
|
||||
void BoxCollider::Max::set(Vector3 value)
|
||||
{
|
||||
getNativeCollisionShape<SHBox>().SetMax(Convert::ToNative(value));
|
||||
//return Convert::ToCLI(getNativeCollisionShape<SHBox>().GetWorldOrientation());
|
||||
return Quaternion::Identity;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -164,11 +151,13 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
bool BoxCollider::TestPoint(Vector3 point)
|
||||
{
|
||||
return getNativeCollisionShape<SHBox>().TestPoint(Convert::ToNative(point));
|
||||
//return getNativeCollisionShape<SHAABB>().TestPoint(Convert::ToNative(point));
|
||||
return false;
|
||||
}
|
||||
bool BoxCollider::Raycast(Ray ray, float maxDistance)
|
||||
{
|
||||
return getNativeCollisionShape<SHBox>().Raycast(Convert::ToNative(ray));
|
||||
//return getNativeCollisionShape<SHAABB>().Raycast(Convert::ToNative(ray));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -176,19 +165,15 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
Vector3 SphereCollider::Center::get()
|
||||
{
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHSphere>().GetCenter());
|
||||
}
|
||||
void SphereCollider::Center::set(Vector3 value)
|
||||
{
|
||||
getNativeCollisionShape<SHSphere>().SetCenter(Convert::ToNative(value));
|
||||
return Convert::ToCLI(getNativeCollisionShape<SHSphere>().GetWorldCentroid());
|
||||
}
|
||||
float SphereCollider::Radius::get()
|
||||
{
|
||||
return getNativeCollisionShape<SHSphere>().GetWorldRadius();
|
||||
return getNativeCollisionShape<SHSphere>().GetWorldRadius();
|
||||
}
|
||||
void SphereCollider::Radius::set(float value)
|
||||
{
|
||||
getNativeCollisionShape<SHSphere>().SetWorldRadius(value);
|
||||
getNativeCollisionShape<SHSphere>().SetWorldRadius(value);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -196,11 +181,13 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
bool SphereCollider::TestPoint(Vector3 point)
|
||||
{
|
||||
return getNativeCollisionShape<SHBox>().TestPoint(Convert::ToNative(point));
|
||||
//return getNativeCollisionShape<SHSphere>().TestPoint(Convert::ToNative(point));
|
||||
return false;
|
||||
}
|
||||
bool SphereCollider::Raycast(Ray ray, float maxDistance)
|
||||
{
|
||||
return getNativeCollisionShape<SHBox>().Raycast(Convert::ToNative(ray));
|
||||
//return getNativeCollisionShape<SHSphere>().Raycast(Convert::ToNative(ray));
|
||||
return false;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -231,7 +218,10 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
int Collider::CollisionShapeCount::get()
|
||||
{
|
||||
return static_cast<int>(GetNativeComponent()->GetCollisionShapes().size());
|
||||
if (const auto* nativeComponent = GetNativeComponent(); nativeComponent)
|
||||
return static_cast<int>(nativeComponent->GetCollisionShapes().size());
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -314,7 +304,7 @@ namespace SHADE
|
|||
for (const auto& collider : GetNativeComponent()->GetCollisionShapes())
|
||||
{
|
||||
CollisionShape^ bound = nullptr;
|
||||
switch (collider.GetType())
|
||||
switch (collider->GetType())
|
||||
{
|
||||
case SHCollisionShape::Type::BOX:
|
||||
bound = gcnew BoxCollider(i, Owner.GetEntity());
|
||||
|
@ -322,9 +312,9 @@ namespace SHADE
|
|||
case SHCollisionShape::Type::SPHERE:
|
||||
bound = gcnew SphereCollider(i, Owner.GetEntity());
|
||||
break;
|
||||
case SHCollisionShape::Type::CAPSULE:
|
||||
// TODO
|
||||
break;
|
||||
//case SHCollisionShape::Type::CAPSULE:
|
||||
// // TODO
|
||||
// break;
|
||||
default:
|
||||
Debug::LogWarning("[Collider] An invalid Collider Type was detected. Skipping.");
|
||||
break;
|
||||
|
@ -335,4 +325,4 @@ namespace SHADE
|
|||
subColliderList->Add(bound);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -31,7 +31,7 @@ namespace SHADE
|
|||
if (shape.GetType() != SHCollisionShape::Type::BOX)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape.");
|
||||
|
||||
return reinterpret_cast<CollisionShapeType&>(shape);
|
||||
return dynamic_cast<CollisionShapeType&>(shape);
|
||||
}
|
||||
catch (std::invalid_argument&)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
/************************************************************************************//*!
|
||||
\file Collider.hxx
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
Diren D Bharwani, diren.dbharwani, 390002520
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
email: diren.dbharwani\@digipen.edu
|
||||
\date Oct 20, 2022
|
||||
\brief Contains the definition of the managed Collider class with the
|
||||
declaration of functions for working with it.
|
||||
|
@ -142,15 +144,14 @@ namespace SHADE
|
|||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Center of the Bounding Box formed by this bound.
|
||||
/// Center of the box collider.
|
||||
/// </summary>
|
||||
property Vector3 Center
|
||||
{
|
||||
Vector3 get();
|
||||
void set(Vector3 value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Half of the scale of the Bounding Box formed by this bound.
|
||||
/// Half of the scale of the box collider.
|
||||
/// </summary>
|
||||
property Vector3 HalfExtents
|
||||
{
|
||||
|
@ -158,22 +159,11 @@ namespace SHADE
|
|||
void set(Vector3 value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Position of the bottom left back corner of the Bounding Box formed by this
|
||||
/// bound.
|
||||
/// The orientation of the box.
|
||||
/// </summary>
|
||||
property Vector3 Min
|
||||
property Quaternion Orientation
|
||||
{
|
||||
Vector3 get();
|
||||
void set(Vector3 value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Position of the top right front corner of the Bounding Box formed by this
|
||||
/// bound.
|
||||
/// </summary>
|
||||
property Vector3 Max
|
||||
{
|
||||
Vector3 get();
|
||||
void set(Vector3 value);
|
||||
Quaternion get();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
@ -201,12 +191,11 @@ namespace SHADE
|
|||
/* Properties */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Center of the Bounding Sphere formed by this bound.
|
||||
/// Center of the sphere.
|
||||
/// </summary>
|
||||
property Vector3 Center
|
||||
{
|
||||
Vector3 get();
|
||||
void set(Vector3 value);
|
||||
}
|
||||
/// <summary>
|
||||
/// Radius of the Bounding Sphere formed by this bound.
|
||||
|
|
|
@ -15,10 +15,14 @@
|
|||
// External Dependencies
|
||||
#include "Physics/System/SHPhysicsSystemInterface.h"
|
||||
// Project Header
|
||||
#include "Components/Collider.hxx"
|
||||
#include "Components/Transform.hxx"
|
||||
#include "Engine/GameObject.hxx"
|
||||
#include "Utility/Convert.hxx"
|
||||
#include "Utility/Debug.hxx"
|
||||
|
||||
using namespace System::Collections::Generic;
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -41,49 +45,271 @@ namespace SHADE
|
|||
/* Raycast Function Member Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
RaycastHit Physics::Raycast(Ray ray)
|
||||
List<RaycastHit>^ Physics::Raycast(Ray ray, bool continuous, unsigned short layer)
|
||||
{
|
||||
return Convert::ToCLI(SHPhysicsSystemInterface::Raycast(Convert::ToNative(ray)));
|
||||
List<RaycastHit>^ results = gcnew List<RaycastHit>();
|
||||
|
||||
// Cast natively
|
||||
SHPhysicsSystemInterface::RaycastInfo raycastInfo;
|
||||
raycastInfo.ray = Convert::ToNative(ray);
|
||||
raycastInfo.continuous = continuous;
|
||||
raycastInfo.layers = layer;
|
||||
|
||||
const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo);
|
||||
if (!NATIVE_RESULTS.empty())
|
||||
{
|
||||
for (const auto& nativeResult : NATIVE_RESULTS)
|
||||
results->Add(Convert::ToCLI(nativeResult));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
RaycastHit Physics::Raycast(Ray ray, float distance)
|
||||
List<RaycastHit>^ Physics::Raycast(Ray ray, float distance, bool continuous, unsigned short layer)
|
||||
{
|
||||
return Convert::ToCLI(SHPhysicsSystemInterface::Raycast(Convert::ToNative(ray), distance));
|
||||
List<RaycastHit>^ results = gcnew List<RaycastHit>();
|
||||
|
||||
// Cast natively
|
||||
SHPhysicsSystemInterface::RaycastInfo raycastInfo;
|
||||
raycastInfo.ray = Convert::ToNative(ray);
|
||||
raycastInfo.distance = distance;
|
||||
raycastInfo.continuous = continuous;
|
||||
raycastInfo.layers = layer;
|
||||
|
||||
const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo);
|
||||
if (!NATIVE_RESULTS.empty())
|
||||
{
|
||||
for (const auto& nativeResult : NATIVE_RESULTS)
|
||||
results->Add(Convert::ToCLI(nativeResult));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
RaycastHit Physics::Linecast(Vector3 start, Vector3 end)
|
||||
List<RaycastHit>^ Physics::Linecast(Vector3 start, Vector3 end, bool continuous, unsigned short layer)
|
||||
{
|
||||
return Convert::ToCLI(SHPhysicsSystemInterface::Linecast(Convert::ToNative(start), Convert::ToNative(end)));
|
||||
List<RaycastHit>^ results = gcnew List<RaycastHit>();
|
||||
|
||||
// Cast natively
|
||||
Vector3 direction = end - start;
|
||||
direction.Normalise();
|
||||
const Ray CLI_RAY( start, direction );
|
||||
|
||||
SHPhysicsSystemInterface::RaycastInfo raycastInfo;
|
||||
raycastInfo.ray = Convert::ToNative(CLI_RAY);
|
||||
raycastInfo.distance = (end - start).GetMagnitude();
|
||||
raycastInfo.continuous = continuous;
|
||||
raycastInfo.layers = layer;
|
||||
|
||||
const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo);
|
||||
if (!NATIVE_RESULTS.empty())
|
||||
{
|
||||
for (const auto& nativeResult : NATIVE_RESULTS)
|
||||
results->Add(Convert::ToCLI(nativeResult));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
RaycastHit Physics::ColliderRaycast(GameObject object, Ray ray)
|
||||
List<RaycastHit>^ Physics::ColliderRaycast(GameObject object, Ray ray, bool continuous, unsigned short layer)
|
||||
{
|
||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, Convert::ToNative(ray)));
|
||||
List<RaycastHit>^ results = gcnew List<RaycastHit>();
|
||||
|
||||
// Get the collider's position (same as the transform)
|
||||
Transform^ managedTransform = object.GetComponent<Transform^>();
|
||||
if (!managedTransform)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Transform.");
|
||||
|
||||
const Vector3 COLLIDER_POS = managedTransform->GlobalPosition;
|
||||
ray.Position += COLLIDER_POS;
|
||||
|
||||
SHPhysicsSystemInterface::RaycastInfo raycastInfo;
|
||||
raycastInfo.ray = Convert::ToNative(ray);
|
||||
raycastInfo.continuous = continuous;
|
||||
raycastInfo.layers = layer;
|
||||
raycastInfo.SetColliderID(object.EntityId);
|
||||
|
||||
const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo);
|
||||
if (!NATIVE_RESULTS.empty())
|
||||
{
|
||||
for (const auto& nativeResult : NATIVE_RESULTS)
|
||||
results->Add(Convert::ToCLI(nativeResult));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
RaycastHit Physics::ColliderRaycast(GameObject object, Ray ray, float distance)
|
||||
List<RaycastHit>^ Physics::ColliderRaycast(GameObject object, Ray ray, float distance, bool continuous, unsigned short layer)
|
||||
{
|
||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, Convert::ToNative(ray), distance));
|
||||
List<RaycastHit>^ results = gcnew List<RaycastHit>();
|
||||
|
||||
// Get the collider's position (same as the transform)
|
||||
Transform^ managedTransform = object.GetComponent<Transform^>();
|
||||
if (!managedTransform)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Transform.");
|
||||
|
||||
const Vector3 COLLIDER_POS = managedTransform->GlobalPosition;
|
||||
ray.Position += COLLIDER_POS;
|
||||
|
||||
SHPhysicsSystemInterface::RaycastInfo raycastInfo;
|
||||
raycastInfo.ray = Convert::ToNative(ray);
|
||||
raycastInfo.distance = distance;
|
||||
raycastInfo.continuous = continuous;
|
||||
raycastInfo.layers = layer;
|
||||
raycastInfo.SetColliderID(object.EntityId);
|
||||
|
||||
const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo);
|
||||
if (!NATIVE_RESULTS.empty())
|
||||
{
|
||||
for (const auto& nativeResult : NATIVE_RESULTS)
|
||||
results->Add(Convert::ToCLI(nativeResult));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
RaycastHit Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray)
|
||||
List<RaycastHit>^ Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, bool continuous, unsigned short layer)
|
||||
{
|
||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, shapeIndex, Convert::ToNative(ray)));
|
||||
List<RaycastHit>^ results = gcnew List<RaycastHit>();
|
||||
|
||||
// Get the collider's position
|
||||
Vector3 shapePos = Vector3::Zero;
|
||||
Collider^ managedCollider = object.GetComponent<Collider^>();
|
||||
if (!managedCollider)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Collider.");
|
||||
|
||||
CollisionShape^ managedShape = managedCollider->GetCollisionShape(shapeIndex);
|
||||
if (!managedShape)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape.");
|
||||
|
||||
const auto& NATIVE_SHAPE = managedShape->getNativeCollisionShape();
|
||||
shapePos = Convert::ToCLI(NATIVE_SHAPE.GetWorldCentroid());
|
||||
|
||||
ray.Position += shapePos;
|
||||
|
||||
SHPhysicsSystemInterface::RaycastInfo raycastInfo;
|
||||
raycastInfo.ray = Convert::ToNative(ray);
|
||||
raycastInfo.continuous = continuous;
|
||||
raycastInfo.layers = layer;
|
||||
raycastInfo.SetColliderID(object.EntityId);
|
||||
|
||||
const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo);
|
||||
if (!NATIVE_RESULTS.empty())
|
||||
{
|
||||
for (const auto& nativeResult : NATIVE_RESULTS)
|
||||
results->Add(Convert::ToCLI(nativeResult));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
RaycastHit Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, float distance)
|
||||
List<RaycastHit>^ Physics::ColliderRaycast(GameObject object, int shapeIndex, Ray ray, float distance, bool continuous, unsigned short layer)
|
||||
{
|
||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderRaycast(object.EntityId, shapeIndex, Convert::ToNative(ray), distance));
|
||||
List<RaycastHit>^ results = gcnew List<RaycastHit>();
|
||||
|
||||
// Get the collider's position
|
||||
Vector3 shapePos = Vector3::Zero;
|
||||
Collider^ managedCollider = object.GetComponent<Collider^>();
|
||||
if (!managedCollider)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Collider.");
|
||||
|
||||
CollisionShape^ managedShape = managedCollider->GetCollisionShape(shapeIndex);
|
||||
if (!managedShape)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape.");
|
||||
|
||||
const auto& NATIVE_SHAPE = managedShape->getNativeCollisionShape();
|
||||
shapePos = Convert::ToCLI(NATIVE_SHAPE.GetWorldCentroid());
|
||||
|
||||
ray.Position += shapePos;
|
||||
|
||||
SHPhysicsSystemInterface::RaycastInfo raycastInfo;
|
||||
raycastInfo.ray = Convert::ToNative(ray);
|
||||
raycastInfo.continuous = continuous;
|
||||
raycastInfo.distance = distance;
|
||||
raycastInfo.layers = layer;
|
||||
raycastInfo.SetColliderID(object.EntityId);
|
||||
|
||||
const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo);
|
||||
if (!NATIVE_RESULTS.empty())
|
||||
{
|
||||
for (const auto& nativeResult : NATIVE_RESULTS)
|
||||
results->Add(Convert::ToCLI(nativeResult));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
RaycastHit Physics::ColliderLineCast(GameObject object, Vector3 start, Vector3 end)
|
||||
List<RaycastHit>^ Physics::ColliderLineCast(GameObject object, Vector3 start, Vector3 end, bool continuous, unsigned short layer)
|
||||
{
|
||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderLinecast(object.EntityId, Convert::ToNative(start), Convert::ToNative(end)));
|
||||
List<RaycastHit>^ results = gcnew List<RaycastHit>();
|
||||
|
||||
// Get the collider's position (same as the transform)
|
||||
Transform^ managedTransform = object.GetComponent<Transform^>();
|
||||
if (!managedTransform)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Transform.");
|
||||
|
||||
const Vector3 COLLIDER_POS = managedTransform->GlobalPosition;
|
||||
start += COLLIDER_POS;
|
||||
|
||||
Vector3 direction = end - start;
|
||||
direction.Normalise();
|
||||
const Ray CLI_RAY( start, direction );
|
||||
|
||||
SHPhysicsSystemInterface::RaycastInfo raycastInfo;
|
||||
raycastInfo.ray = Convert::ToNative(CLI_RAY);
|
||||
raycastInfo.distance = (end - start).GetMagnitude();
|
||||
raycastInfo.continuous = continuous;
|
||||
raycastInfo.layers = layer;
|
||||
raycastInfo.SetColliderID(object.EntityId);
|
||||
|
||||
const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo);
|
||||
if (!NATIVE_RESULTS.empty())
|
||||
{
|
||||
for (const auto& nativeResult : NATIVE_RESULTS)
|
||||
results->Add(Convert::ToCLI(nativeResult));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
RaycastHit Physics::ColliderLineCast(GameObject object, int shapeIndex, Vector3 start, Vector3 end)
|
||||
List<RaycastHit>^ Physics::ColliderLineCast(GameObject object, int shapeIndex, Vector3 start, Vector3 end, bool continuous, unsigned short layer)
|
||||
{
|
||||
return Convert::ToCLI(SHPhysicsSystemInterface::ColliderLinecast(object.EntityId, shapeIndex, Convert::ToNative(start), Convert::ToNative(end)));
|
||||
List<RaycastHit>^ results = gcnew List<RaycastHit>();
|
||||
|
||||
// Get the collider's position
|
||||
Vector3 shapePos = Vector3::Zero;
|
||||
Collider^ managedCollider = object.GetComponent<Collider^>();
|
||||
if (!managedCollider)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid Collider.");
|
||||
|
||||
CollisionShape^ managedShape = managedCollider->GetCollisionShape(shapeIndex);
|
||||
if (!managedShape)
|
||||
throw gcnew System::InvalidOperationException("Attempted to retrieve invalid CollisionShape.");
|
||||
|
||||
const auto& NATIVE_SHAPE = managedShape->getNativeCollisionShape();
|
||||
shapePos = Convert::ToCLI(NATIVE_SHAPE.GetWorldCentroid());
|
||||
|
||||
start += shapePos;
|
||||
|
||||
Vector3 direction = end - start;
|
||||
direction.Normalise();
|
||||
const Ray CLI_RAY( start, direction );
|
||||
|
||||
SHPhysicsSystemInterface::RaycastInfo raycastInfo;
|
||||
raycastInfo.ray = Convert::ToNative(CLI_RAY);
|
||||
raycastInfo.continuous = continuous;
|
||||
raycastInfo.distance = (end - start).GetMagnitude();
|
||||
raycastInfo.layers = layer;
|
||||
raycastInfo.SetColliderID(object.EntityId);
|
||||
|
||||
const auto& NATIVE_RESULTS = SHPhysicsSystemInterface::Raycast(raycastInfo);
|
||||
if (!NATIVE_RESULTS.empty())
|
||||
{
|
||||
for (const auto& nativeResult : NATIVE_RESULTS)
|
||||
results->Add(Convert::ToCLI(nativeResult));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -40,82 +40,146 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
|
||||
/// <summary>
|
||||
/// Casts an infinite ray into the world.
|
||||
/// Casts an infinite ray into the world. <br/>
|
||||
/// This raycast will stop at the first object hit.
|
||||
/// </summary>
|
||||
/// <param name="ray">The ray to cast.</param>
|
||||
/// <returns>The result of the raycast.</returns>
|
||||
static RaycastHit Raycast (Ray ray);
|
||||
/// <param name="continuous">
|
||||
/// Whether or not the raycast should stop at the first object hit.
|
||||
/// </param>
|
||||
/// <param name="layer">
|
||||
/// The layers to cast the ray on.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The results of the raycast. If nothing was hit, an empty list is returned.
|
||||
/// </returns>
|
||||
static System::Collections::Generic::List<RaycastHit>^ Raycast (Ray ray, bool continuous, unsigned short layer);
|
||||
|
||||
/// <summary>
|
||||
/// Casts a ray for a given distance into the world.
|
||||
/// </summary>
|
||||
/// <param name="ray">The ray to cast.</param>
|
||||
/// <param name="distance">The distance to cast the ray.</param>
|
||||
/// <returns>The result of the raycast.</returns>
|
||||
static RaycastHit Raycast (Ray ray, float distance);
|
||||
/// <param name="continuous">
|
||||
/// Whether or not the raycast should stop at the first object hit.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The results of the raycast. If nothing was hit, an empty list is returned.
|
||||
/// </returns>
|
||||
static System::Collections::Generic::List<RaycastHit>^ Raycast (Ray ray, float distance, bool continuous, unsigned short layer);
|
||||
|
||||
/// <summary>
|
||||
/// Casts a bounded ray into the world.
|
||||
/// </summary>
|
||||
/// <param name="start">The start of the bounded ray.</param>
|
||||
/// <param name="end">The end of the bounded ray.</param>
|
||||
/// <returns>The result of the raycast.</returns>
|
||||
static RaycastHit Linecast (Vector3 start, Vector3 end);
|
||||
/// <param name="continuous">
|
||||
/// Whether or not the raycast should stop at the first object hit.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The results of the raycast. If nothing was hit, an empty list is returned.
|
||||
/// </returns>
|
||||
static System::Collections::Generic::List<RaycastHit>^ Linecast (Vector3 start, Vector3 end, bool continuous, unsigned short layer);
|
||||
|
||||
/// <summary>
|
||||
/// Casts an infinite ray w.r.t a GameObject.
|
||||
/// </summary>
|
||||
/// <param name="object">The GameObject to cast the ray to.</param>
|
||||
/// <param name="ray">The ray to cast.</param>
|
||||
/// <returns>The result of the raycast.</returns>
|
||||
static RaycastHit ColliderRaycast (GameObject object, Ray ray);
|
||||
/// <param name="ray">
|
||||
/// The ray to cast. <br/>
|
||||
/// The position of the ray is offset from the collider's position.
|
||||
/// </param>
|
||||
/// <param name="continuous">
|
||||
/// Whether or not the raycast should stop at the first object hit.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The results of the raycast. If nothing was hit, an empty list is returned.
|
||||
/// </returns>
|
||||
static System::Collections::Generic::List<RaycastHit>^ ColliderRaycast (GameObject object, Ray ray, bool continuous, unsigned short layer);
|
||||
|
||||
/// <summary>
|
||||
/// Casts a ray for a given distance w.r.t a GameObject.
|
||||
/// </summary>
|
||||
/// <param name="object">The GameObject to cast the ray to.</param>
|
||||
/// <param name="ray">The ray to cast.</param>
|
||||
/// <param name="ray">
|
||||
/// The ray to cast. <br/>
|
||||
/// The position of the ray is offset from the collider's position.
|
||||
/// </param>
|
||||
/// <param name="distance">The distance to cast the ray.</param>
|
||||
/// <returns>The result of the raycast.</returns>
|
||||
static RaycastHit ColliderRaycast (GameObject object, Ray ray, float distance);
|
||||
/// <param name="continuous">
|
||||
/// Whether or not the raycast should stop at the first object hit.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The results of the raycast. If nothing was hit, an empty list is returned.
|
||||
/// </returns>
|
||||
static System::Collections::Generic::List<RaycastHit>^ ColliderRaycast (GameObject object, Ray ray, float distance, bool continuous, unsigned short layer);
|
||||
|
||||
/// <summary>
|
||||
/// Casts an infinite ray w.r.t a specific collider on a GameObject.
|
||||
/// </summary>
|
||||
/// <param name="object">The GameObject to cast the ray to.</param>
|
||||
/// <param name="shapeIndex">The collision shape index on the collider to cast to.</param>
|
||||
/// <param name="ray">The ray to cast.</param>
|
||||
/// <returns>The result of the raycast.</returns>
|
||||
static RaycastHit ColliderRaycast (GameObject object, int shapeIndex, Ray ray);
|
||||
/// <param name="ray">
|
||||
/// The ray to cast. <br/>
|
||||
/// The position of the ray is offset from the collider's position.
|
||||
/// </param>
|
||||
/// <param name="continuous">
|
||||
/// Whether or not the raycast should stop at the first object hit.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The results of the raycast. If nothing was hit, an empty list is returned.
|
||||
/// </returns>
|
||||
static System::Collections::Generic::List<RaycastHit>^ ColliderRaycast (GameObject object, int shapeIndex, Ray ray, bool continuous, unsigned short layer);
|
||||
|
||||
/// <summary>
|
||||
/// Casts a ray for a given distance w.r.t a specific collider on a GameObject.
|
||||
/// </summary>
|
||||
/// <param name="object">The GameObject to cast the ray to.</param>
|
||||
/// <param name="shapeIndex">The collision shape index on the collider to cast to.</param>
|
||||
/// <param name="ray">The ray to cast.</param>
|
||||
/// <param name="ray">
|
||||
/// The ray to cast. <br/>
|
||||
/// The position of the ray is offset from the collider's position.
|
||||
/// </param>
|
||||
/// <param name="distance">The distance to cast the ray.</param>
|
||||
/// <returns>The result of the raycast.</returns>
|
||||
static RaycastHit ColliderRaycast (GameObject object, int shapeIndex, Ray ray, float distance);
|
||||
/// <param name="continuous">
|
||||
/// Whether or not the raycast should stop at the first object hit.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The results of the raycast. If nothing was hit, an empty list is returned.
|
||||
/// </returns>
|
||||
static System::Collections::Generic::List<RaycastHit>^ ColliderRaycast (GameObject object, int shapeIndex, Ray ray, float distance, bool continuous, unsigned short layer);
|
||||
|
||||
/// <summary>
|
||||
/// Casts a bounded ray w.r.t a GameObject.
|
||||
/// </summary>
|
||||
/// <param name="object">The GameObject to cast the ray to.</param>
|
||||
/// <param name="start">The start of the bounded ray.</param>
|
||||
/// <param name="start">
|
||||
/// The start of the bounded ray. <br/>
|
||||
/// The start of the ray is offset from the collider's position. </param>
|
||||
/// <param name="end"></param>
|
||||
/// <returns>The result of the raycast.</returns>
|
||||
static RaycastHit ColliderLineCast (GameObject object, Vector3 start, Vector3 end);
|
||||
/// <param name="continuous">
|
||||
/// Whether or not the raycast should stop at the first object hit.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The results of the raycast. If nothing was hit, an empty list is returned.
|
||||
/// </returns>
|
||||
static System::Collections::Generic::List<RaycastHit>^ ColliderLineCast (GameObject object, Vector3 start, Vector3 end, bool continuous, unsigned short layer);
|
||||
|
||||
/// <summary>
|
||||
/// Casts a bounded ray w.r.t a specific collider on a GameObject.
|
||||
/// </summary>
|
||||
/// <param name="object">The GameObject to cast the ray to.</param>
|
||||
/// <param name="shapeIndex">The collision shape index on the collider to cast to.</param>
|
||||
/// <param name="start">The start of the bounded ray.</param>
|
||||
/// <param name="start">
|
||||
/// The start of the bounded ray. <br/>
|
||||
/// The start of the ray is offset from the collider's position. </param>
|
||||
/// <param name="end">The end of the bounded ray.</param>
|
||||
/// <returns>The result of the raycast.</returns>
|
||||
static RaycastHit ColliderLineCast (GameObject object, int shapeIndex, Vector3 start, Vector3 end);
|
||||
/// <param name="continuous">
|
||||
/// Whether or not the raycast should stop at the first object hit.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// The results of the raycast. If nothing was hit, an empty list is returned./// </returns>
|
||||
static System::Collections::Generic::List<RaycastHit>^ ColliderLineCast (GameObject object, int shapeIndex, Vector3 start, Vector3 end, bool continuous, unsigned short layer);
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
|
Loading…
Reference in New Issue