Added shape sweeping in C#
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -11,4 +11,11 @@ namespace Nuake
|
||||
Vector3 WorldPosition;
|
||||
float Fraction;
|
||||
};
|
||||
|
||||
struct ShapeCastResult
|
||||
{
|
||||
Vector3 ImpactPosition;
|
||||
float Fraction;
|
||||
Vector3 ImpactNormal;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
234
NuakeNet/src/Physic.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user