Added shape sweeping in C#

This commit is contained in:
Antoine Pilote
2024-08-10 18:09:22 -04:00
parent f3b9b328b1
commit 4dd1a4e6f7
9 changed files with 369 additions and 7 deletions

View File

@@ -15,6 +15,12 @@
#include <Jolt/RegisterTypes.h>
#include <Jolt/Core/Factory.h>
#include <Jolt/Core/TempAllocator.h>
#include <Jolt/Physics/Body/BodyCreationSettings.h>
#include <Jolt/Physics/Body/BodyActivationListener.h>
#include <Jolt/Physics/Character/CharacterVirtual.h>
#include <Jolt/Physics/Collision/RayCast.h>
#include <Jolt/Physics/Collision/ShapeCast.h>
#include <Jolt/Physics/Collision/CastResult.h>
#include <Jolt/Core/JobSystemThreadPool.h>
#include <Jolt/Physics/PhysicsSettings.h>
#include <Jolt/Physics/PhysicsSystem.h>
@@ -25,11 +31,6 @@
#include <Jolt/Physics/Collision/Shape/MeshShape.h>
#include <Jolt/Physics/Collision/Shape/ConvexHullShape.h>
#include <Jolt/Physics/Body/BodyCreationSettings.h>
#include <Jolt/Physics/Body/BodyActivationListener.h>
#include <Jolt/Physics/Character/CharacterVirtual.h>
#include <Jolt/Physics/Collision/RayCast.h>
#include <Jolt/Physics/Collision/CastResult.h>
#include <Jolt/Core/TempAllocator.h>
#include <dependencies/JoltPhysics/Jolt/Physics/Collision/CollisionCollectorImpl.h>
@@ -480,7 +481,6 @@ namespace Nuake
// Fetch results
std::vector<RaycastResult> raycastResults;
if (collector.HadHit())
{
int num_hits = (int)collector.mHits.size();
@@ -505,6 +505,56 @@ namespace Nuake
return raycastResults;
}
std::vector<ShapeCastResult> DynamicWorld::CastShape(const Vector3& from, const Vector3& to, const Ref<PhysicShape>& shape)
{
auto joltShape = GetJoltShape(shape);
const auto& fromJolt = JPH::Vec3(from.x, from.y, from.z);
const auto& toDirectionJolt = JPH::Vec3(to.x - from.x, to.y - from.y, to.z - from.z);
const auto& scale = JPH::Vec3(1, 1, 1);
JPH::Mat44 centerOfMass = JPH::Mat44::sIdentity();
centerOfMass.SetTranslation(JPH::Vec3(from.x, from.y, from.z));
const JPH::AABox worldBound = JPH::AABox(JPH::Vec3{-1000, -1000, -1000}, JPH::Vec3{1000, 1000, 1000});
JPH::RShapeCast ray = JPH::RShapeCast(joltShape, scale, centerOfMass, toDirectionJolt, worldBound);
JPH::AllHitCollisionCollector<JPH::CastShapeCollector> collector;
JPH::RayCastResult result;
JPH::ShapeCastSettings shapeCastSetting;
shapeCastSetting.mCollectFacesMode = JPH::ECollectFacesMode::CollectFaces;
_JoltPhysicsSystem->GetNarrowPhaseQuery().CastShape(ray, shapeCastSetting, JPH::Vec3(0, 0, 0), collector);
std::vector<ShapeCastResult> shapecastResults;
if (collector.HadHit())
{
int num_hits = (int)collector.mHits.size();
auto results = collector.mHits.data();
// Format result
for (int i = 0; i < num_hits; ++i)
{
const float hitFraction = results[i].mFraction;
const JPH::Vec3& hitPosition = ray.GetPointOnRay(results[i].mFraction);
auto bodyId = static_cast<JPH::BodyID>(results[i].mBodyID2);
JPH::TransformedShape ts = _JoltPhysicsSystem->GetBodyInterface().GetTransformedShape(results[i].mBodyID2);
JPH::Vec3 surfaceNormal = ts.GetWorldSpaceSurfaceNormal(results[i].mSubShapeID2, results[i].mContactPointOn2);
ShapeCastResult result
{
Vector3(hitPosition.GetX(), hitPosition.GetY(), hitPosition.GetZ()),
hitFraction,
Vector3(surfaceNormal.GetX(), surfaceNormal.GetY(), surfaceNormal.GetZ())
};
shapecastResults.push_back(std::move(result));
}
}
return shapecastResults;
}
void DynamicWorld::SyncEntitiesTranforms()
{
const auto& bodyInterface = _JoltPhysicsSystem->GetBodyInterface();

View File

@@ -82,6 +82,7 @@ namespace Nuake
void AddForceToRigidBody(Entity& entity, const Vector3& force);
std::vector<RaycastResult> Raycast(const Vector3& from, const Vector3& to);
std::vector<ShapeCastResult> CastShape(const Vector3& from, const Vector3& to, const Ref<PhysicShape>& shape);
void StepSimulation(Timestep ts);
void Clear();

View File

@@ -52,6 +52,11 @@ namespace Nuake
return m_World->Raycast(from, to);
}
std::vector<ShapeCastResult> PhysicsManager::Shapecast(const Vector3& from, const Vector3& to, const Ref<Physics::PhysicShape>& shape)
{
return m_World->CastShape(from, to, shape);
}
const std::vector<Physics::CollisionData>& PhysicsManager::GetCollisions()
{
return m_World->GetCollisionsData();

View File

@@ -49,6 +49,7 @@ namespace Nuake
void Reset();
std::vector<RaycastResult> Raycast(const Vector3& from, const Vector3& to);
std::vector<ShapeCastResult> Shapecast(const Vector3& from, const Vector3& to, const Ref<Physics::PhysicShape>& shape);
const std::vector<Physics::CollisionData>& GetCollisions();

View File

@@ -11,4 +11,11 @@ namespace Nuake
Vector3 WorldPosition;
float Fraction;
};
struct ShapeCastResult
{
Vector3 ImpactPosition;
float Fraction;
Vector3 ImpactNormal;
};
}

View File

@@ -236,7 +236,10 @@ namespace Nuake
system->Update(ts);
}
m_SceneRenderer->Update(ts);
if (Engine::IsPlayMode())
{
m_SceneRenderer->Update(ts);
}
}
void Scene::FixedUpdate(Timestep ts)

View File

@@ -3,9 +3,24 @@
#include <src/Core/Maths.h>
#include <Engine.h>
#include "src/Rendering/SceneRenderer.h"
#include <Coral/Array.hpp>
#include <src/Physics/PhysicsManager.h>
namespace Nuake {
struct CapsuleInternal
{
float Radius;
float Height;
};
struct BoxInternal
{
float x;
float y;
float z;
};
void Log(Coral::String string)
{
Logger::Log(string, ".net", VERBOSE);
@@ -20,10 +35,50 @@ namespace Nuake {
Engine::GetCurrentScene()->m_SceneRenderer->DrawDebugLine(start, end, color, life);
}
Coral::Array<float> ConvertHitsToArray(const std::vector<ShapeCastResult> hits)
{
std::vector<float> results;
for (const auto& hit : hits)
{
results.push_back(hit.ImpactPosition.x);
results.push_back(hit.ImpactPosition.y);
results.push_back(hit.ImpactPosition.z);
results.push_back(hit.ImpactNormal.x);
results.push_back(hit.ImpactNormal.y);
results.push_back(hit.ImpactNormal.z);
results.push_back(hit.Fraction);
}
return Coral::Array<float>::New(results);
}
Coral::Array<float> ShapeCastCapsule(float fromX, float fromY, float fromZ, float toX, float toY, float toZ, CapsuleInternal capsuleInternal)
{
auto capsule = CreateRef<Physics::Capsule>(capsuleInternal.Radius, capsuleInternal.Height);
const Vector3 from = { fromX, fromY, fromZ };
const Vector3 to = { toX, toY, toZ };
auto hits = PhysicsManager::Get().Shapecast(from, to, capsule);
return ConvertHitsToArray(hits);
}
Coral::Array<float> ShapeCastBox(float fromX, float fromY, float fromZ, float toX, float toY, float toZ, BoxInternal boxInternal)
{
auto capsule = CreateRef<Physics::Box>(boxInternal.x, boxInternal.y, boxInternal.z);
const Vector3 from = { fromX, fromY, fromZ };
const Vector3 to = { toX, toY, toZ };
auto hits = PhysicsManager::Get().Shapecast(from, to, capsule);
return ConvertHitsToArray(hits);
}
void EngineNetAPI::RegisterMethods()
{
RegisterMethod("Engine.LoggerLogIcall", (void*)(&Log));
RegisterMethod("Debug.DrawLineIcall", &DrawLine);
RegisterMethod("Physic.ShapeCastCapsuleIcall", &ShapeCastCapsule);
RegisterMethod("Physic.ShapeCastBoxIcall", &ShapeCastBox);
}
}

View File

@@ -226,6 +226,12 @@ void generate_brush_vertices(int entity_idx, int brush_idx)
if (phong)
{
const char* phong_angle_property = map_data_get_entity_property(entity_idx, "_phong_angle");
if (phong_angle_property == NULL)
{
phong_angle_property = "89";
}
if (phong_angle_property != NULL)
{
double threshold = cos((atof(phong_angle_property) + 0.01) * 0.0174533);

234
NuakeNet/src/Physic.cs Normal file
View File

@@ -0,0 +1,234 @@
using Coral.Managed.Interop;
using Nuake.Net.Physics.Shapes;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace Nuake.Net
{
namespace Physics
{
namespace Shapes
{
public class Box
{
public float Width { get; set; } = 1.0f;
public float Height { get; set; } = 1.0f;
public float Depth { get; set; } = 1.0f;
public Box(float width, float height, float depth)
{
Width = width;
Height = height;
Depth = depth;
}
public Box(Vector3 size)
{
Width = size.X;
Height = size.Y;
Depth = size.Z;
}
public Vector3 GetSize()
{
return new Vector3(Width, Height, Depth);
}
public void SetSize(Vector3 size)
{
Width = size.X;
Height = size.Y;
Depth = size.Z;
}
}
public class Sphere
{
public float Radius { get; set; } = 0.5f;
public Sphere(float radius)
{
Radius = radius;
}
}
public class Capsule
{
public float Radius { get; set; } = 0.5f;
public float Height { get; set; } = 1.0f;
public Capsule(float radius, float height)
{
Radius = radius;
Height = height;
}
}
public class Cylinder
{
public float Radius { get; set; } = 0.5f;
public float Height { get; set; } = 1.0f;
public Cylinder(float radius, float height)
{
Radius = radius;
Height = height;
}
}
}
}
public class Physic
{
public struct ShapeCastResult
{
public Vector3 ImpactPosition;
public Vector3 ImpactNormal;
public float Fraction;
}
public struct BoxInternal
{
public float X;
public float Y;
public float Z;
}
public struct CapsuleInternal
{
public float Radius;
public float Height;
}
internal static unsafe delegate*<float, float, float, float, float, float, BoxInternal, NativeArray<float>> ShapeCastBoxIcall;
internal static unsafe delegate*<float, float, float, float, float, float, float, NativeArray<float>> ShapeCastSphereIcall;
internal static unsafe delegate*<float, float, float, float, float, float, CapsuleInternal, NativeArray<float>> ShapeCastCapsuleIcall;
internal static unsafe delegate*<float, float, float, float, float, float, CapsuleInternal, NativeArray<float>> ShapeCastCylinderIcall;
public static List<ShapeCastResult> ShapeCast(Vector3 from, Vector3 to, Box box)
{
List<ShapeCastResult> result = [];
BoxInternal boxInternal = new()
{
X = box.Width,
Y = box.Height,
Z = box.Depth
};
unsafe
{
NativeArray<float> resultICall = ShapeCastBoxIcall(from.X, from.Y, from.Z, to.X, to.Y, to.Z, boxInternal);
for (int i = 0; i < resultICall.Length / 7; i++)
{
int index = i * 7;
ShapeCastResult shapeCastResult = new()
{
ImpactPosition = new Vector3(resultICall[index + 0], resultICall[index + 1], resultICall[index + 2]),
ImpactNormal = new Vector3(resultICall[index + 3], resultICall[index + 4], resultICall[index + 5]),
Fraction = resultICall[index + 6]
};
result.Add(shapeCastResult);
}
}
return result;
}
public static List<ShapeCastResult> ShapeCast(Vector3 from, Vector3 to, Sphere sphere)
{
List<ShapeCastResult> result = [];
unsafe
{
NativeArray<float> resultICall = ShapeCastSphereIcall(from.X, from.Y, from.Z, to.X, to.Y, to.Z, sphere.Radius);
for (int i = 0; i < resultICall.Length / 7; i++)
{
int index = i * 7;
ShapeCastResult shapeCastResult = new()
{
ImpactPosition = new Vector3(resultICall[index + 0], resultICall[index + 1], resultICall[index + 2]),
ImpactNormal = new Vector3(resultICall[index + 3], resultICall[index + 4], resultICall[index + 5]),
Fraction = resultICall[index + 6]
};
result.Add(shapeCastResult);
}
}
return result;
}
public static List<ShapeCastResult> ShapeCast(Vector3 from, Vector3 to, Capsule capsule)
{
List<ShapeCastResult> result = new List<ShapeCastResult>();
CapsuleInternal capsuleInternal = new()
{
Radius = capsule.Radius,
Height = capsule.Height
};
unsafe
{
NativeArray<float> resultICall = ShapeCastCapsuleIcall(from.X, from.Y, from.Z, to.X, to.Y, to.Z, capsuleInternal);
for (int i = 0; i < resultICall.Length / 7; i++)
{
int index = i * 7;
ShapeCastResult shapeCastResult = new()
{
ImpactPosition = new Vector3(resultICall[index + 0], resultICall[index + 1], resultICall[index + 2]),
ImpactNormal = new Vector3(resultICall[index + 3], resultICall[index + 4], resultICall[index + 5]),
Fraction = resultICall[index + 6]
};
result.Add(shapeCastResult);
}
}
return result;
}
public static List<ShapeCastResult> ShapeCast(Vector3 from, Vector3 to, Cylinder cylinder)
{
List<ShapeCastResult> result = [];
CapsuleInternal cylinderInternal = new()
{
Radius = cylinder.Radius,
Height = cylinder.Height
};
unsafe
{
NativeArray<float> resultICall = ShapeCastCylinderIcall(from.X, from.Y, from.Z, to.X, to.Y, to.Z, cylinderInternal);
for (int i = 0; i < resultICall.Length / 7; i++)
{
int index = i * 7;
ShapeCastResult shapeCastResult = new()
{
ImpactPosition = new Vector3(resultICall[index + 0], resultICall[index + 1], resultICall[index + 2]),
ImpactNormal = new Vector3(resultICall[index + 3], resultICall[index + 4], resultICall[index + 5]),
Fraction = resultICall[index + 6]
};
result.Add(shapeCastResult);
}
}
return result;
}
}
}