forked from LeenkxTeam/LNXSDK
merge upstream
This commit is contained in:
commit
db6d786ee4
@ -49,9 +49,10 @@ class DebugDrawHelper {
|
|||||||
final fromScreenSpace = worldToScreenFast(new Vec4(from.x(), from.y(), from.z(), 1.0));
|
final fromScreenSpace = worldToScreenFast(new Vec4(from.x(), from.y(), from.z(), 1.0));
|
||||||
final toScreenSpace = worldToScreenFast(new Vec4(to.x(), to.y(), to.z(), 1.0));
|
final toScreenSpace = worldToScreenFast(new Vec4(to.x(), to.y(), to.z(), 1.0));
|
||||||
|
|
||||||
// For now don't draw lines if any point is outside of clip space z,
|
|
||||||
// investigate how to clamp lines to clip space borders
|
// investigate how to clamp lines to clip space borders
|
||||||
if (fromScreenSpace.w == 1 && toScreenSpace.w == 1) {
|
// If at least one point is within the Z clip space (w==1), attempt to draw.
|
||||||
|
// Note: This is not full clipping, line may still go off screen sides.
|
||||||
|
if (fromScreenSpace.w == 1 || toScreenSpace.w == 1) {
|
||||||
lines.push({
|
lines.push({
|
||||||
fromX: fromScreenSpace.x,
|
fromX: fromScreenSpace.x,
|
||||||
fromY: fromScreenSpace.y,
|
fromY: fromScreenSpace.y,
|
||||||
@ -62,6 +63,25 @@ class DebugDrawHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Draws raycast in its own function because
|
||||||
|
// something is conflicting with the btVector3 and JS pointer wrapping
|
||||||
|
public function drawRayCast(fx:FastFloat, fy:FastFloat, fz:FastFloat, tx:FastFloat, ty:FastFloat, tz:FastFloat, r:FastFloat, g:FastFloat, b:FastFloat) {
|
||||||
|
final fromScreenSpace = worldToScreenFast(new Vec4(fx, fy, fz, 1.0));
|
||||||
|
final toScreenSpace = worldToScreenFast(new Vec4(tx, ty, tz, 1.0));
|
||||||
|
|
||||||
|
// TO DO: May still go off screen sides.
|
||||||
|
if (fromScreenSpace.w == 1 || toScreenSpace.w == 1) {
|
||||||
|
final color = kha.Color.fromFloats(r, g, b, 1.0);
|
||||||
|
lines.push({
|
||||||
|
fromX: fromScreenSpace.x,
|
||||||
|
fromY: fromScreenSpace.y,
|
||||||
|
toX: toScreenSpace.x,
|
||||||
|
toY: toScreenSpace.y,
|
||||||
|
color: color
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function drawContactPoint(pointOnB: Vector3, normalOnB: Vector3, distance: kha.FastFloat, lifeTime: Int, color: Vector3) {
|
public function drawContactPoint(pointOnB: Vector3, normalOnB: Vector3, distance: kha.FastFloat, lifeTime: Int, color: Vector3) {
|
||||||
#if js
|
#if js
|
||||||
pointOnB = js.Syntax.code("Ammo.wrapPointer({0}, Ammo.btVector3)", pointOnB);
|
pointOnB = js.Syntax.code("Ammo.wrapPointer({0}, Ammo.btVector3)", pointOnB);
|
||||||
@ -106,7 +126,7 @@ class DebugDrawHelper {
|
|||||||
x: contactPointScreenSpace.x,
|
x: contactPointScreenSpace.x,
|
||||||
y: contactPointScreenSpace.y,
|
y: contactPointScreenSpace.y,
|
||||||
color: color,
|
color: color,
|
||||||
text: Std.string(lifeTime), // lifeTime: number of frames the contact point existed
|
text: Std.string(lifeTime),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +170,7 @@ class DebugDrawHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onRender(g: kha.graphics2.Graphics) {
|
function onRender(g: kha.graphics2.Graphics) {
|
||||||
if (getDebugMode() == NoDebug) {
|
if (getDebugMode() == NoDebug && !physicsWorld.drawRaycasts) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,8 +179,7 @@ class DebugDrawHelper {
|
|||||||
// will cause Bullet to call the btIDebugDraw callbacks), but this way
|
// will cause Bullet to call the btIDebugDraw callbacks), but this way
|
||||||
// we can ensure that--within a frame--the function will not be called
|
// we can ensure that--within a frame--the function will not be called
|
||||||
// before some user-specific physics update, which would result in a
|
// before some user-specific physics update, which would result in a
|
||||||
// one-frame drawing delay... Ideally we would ensure that debugDrawWorld()
|
// one-frame drawing delay...
|
||||||
// is called when all other (late) update callbacks are already executed...
|
|
||||||
physicsWorld.world.debugDrawWorld();
|
physicsWorld.world.debugDrawWorld();
|
||||||
|
|
||||||
g.opacity = 1.0;
|
g.opacity = 1.0;
|
||||||
|
@ -71,6 +71,7 @@ class PhysicsWorld extends Trait {
|
|||||||
public var convexHitPointWorld = new Vec4();
|
public var convexHitPointWorld = new Vec4();
|
||||||
public var convexHitNormalWorld = new Vec4();
|
public var convexHitNormalWorld = new Vec4();
|
||||||
var pairCache: Bool = false;
|
var pairCache: Bool = false;
|
||||||
|
public var drawRaycasts: Bool = false;
|
||||||
|
|
||||||
static var nullvec = true;
|
static var nullvec = true;
|
||||||
static var vec1: bullet.Bt.Vector3 = null;
|
static var vec1: bullet.Bt.Vector3 = null;
|
||||||
@ -101,7 +102,7 @@ class PhysicsWorld extends Trait {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function new(timeScale = 1.0, maxSteps = 10, solverIterations = 10, debugDrawMode: DebugDrawMode = NoDebug) {
|
public function new(timeScale = 1.0, maxSteps = 10, solverIterations = 10, debugDrawMode: DebugDrawMode = NoDebug, drawRaycasts: Bool = false) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
if (nullvec) {
|
if (nullvec) {
|
||||||
@ -120,6 +121,7 @@ class PhysicsWorld extends Trait {
|
|||||||
this.timeScale = timeScale;
|
this.timeScale = timeScale;
|
||||||
this.maxSteps = maxSteps;
|
this.maxSteps = maxSteps;
|
||||||
this.solverIterations = solverIterations;
|
this.solverIterations = solverIterations;
|
||||||
|
this.drawRaycasts = drawRaycasts;
|
||||||
|
|
||||||
// First scene
|
// First scene
|
||||||
if (active == null) {
|
if (active == null) {
|
||||||
@ -180,8 +182,8 @@ class PhysicsWorld extends Trait {
|
|||||||
#else
|
#else
|
||||||
world = new bullet.Bt.DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
|
world = new bullet.Bt.DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
|
||||||
#end
|
#end
|
||||||
// Set the solver iterations from Blender's rigid body world
|
// TO DO: Set the solver iterations from Blender's rigid body world
|
||||||
setSolverIterations(world, solverIterations);
|
// setSolverIterations(world, solverIterations);
|
||||||
setGravity(gravity);
|
setGravity(gravity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,6 +397,7 @@ class PhysicsWorld extends Trait {
|
|||||||
rayTo.setValue(to.x, to.y, to.z);
|
rayTo.setValue(to.x, to.y, to.z);
|
||||||
|
|
||||||
var rayCallback = new bullet.Bt.ClosestRayResultCallback(rayFrom, rayTo);
|
var rayCallback = new bullet.Bt.ClosestRayResultCallback(rayFrom, rayTo);
|
||||||
|
|
||||||
#if js
|
#if js
|
||||||
rayCallback.set_m_collisionFilterGroup(group);
|
rayCallback.set_m_collisionFilterGroup(group);
|
||||||
rayCallback.set_m_collisionFilterMask(mask);
|
rayCallback.set_m_collisionFilterMask(mask);
|
||||||
@ -404,6 +407,15 @@ class PhysicsWorld extends Trait {
|
|||||||
#end
|
#end
|
||||||
var worldDyn: bullet.Bt.DynamicsWorld = world;
|
var worldDyn: bullet.Bt.DynamicsWorld = world;
|
||||||
var worldCol: bullet.Bt.CollisionWorld = worldDyn;
|
var worldCol: bullet.Bt.CollisionWorld = worldDyn;
|
||||||
|
|
||||||
|
if (this.drawRaycasts && this.debugDrawHelper != null) {
|
||||||
|
this.debugDrawHelper.drawRayCast(
|
||||||
|
rayFrom.x(), rayFrom.y(), rayFrom.z(),
|
||||||
|
rayTo.x(), rayTo.y(), rayTo.z(),
|
||||||
|
0.73, 0.341, 1.0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
worldCol.rayTest(rayFrom, rayTo, rayCallback);
|
worldCol.rayTest(rayFrom, rayTo, rayCallback);
|
||||||
var rb: RigidBody = null;
|
var rb: RigidBody = null;
|
||||||
var hitInfo: Hit = null;
|
var hitInfo: Hit = null;
|
||||||
@ -507,14 +519,22 @@ class PhysicsWorld extends Trait {
|
|||||||
|
|
||||||
public function setDebugDrawMode(debugDrawMode: DebugDrawMode) {
|
public function setDebugDrawMode(debugDrawMode: DebugDrawMode) {
|
||||||
if (debugDrawHelper == null) {
|
if (debugDrawHelper == null) {
|
||||||
if (debugDrawMode == NoDebug) {
|
// Initialize if helper is null AND (standard debug mode is requested OR our custom raycast drawing is requested)
|
||||||
|
if (debugDrawMode != NoDebug || this.drawRaycasts) {
|
||||||
|
initDebugDrawing();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Helper is null and no debug drawing needed, so exit
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initDebugDrawing();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we reached here, the helper is initialized (or was already)
|
||||||
|
// Now set the standard Bullet debug mode on the actual drawer
|
||||||
#if js
|
#if js
|
||||||
world.getDebugDrawer().setDebugMode(debugDrawMode);
|
// Ensure drawer exists before setting mode (might have just been initialized)
|
||||||
|
var drawer = world.getDebugDrawer();
|
||||||
|
if (drawer != null) drawer.setDebugMode(debugDrawMode);
|
||||||
#elseif hl
|
#elseif hl
|
||||||
hlDebugDrawer_setDebugMode(debugDrawMode);
|
hlDebugDrawer_setDebugMode(debugDrawMode);
|
||||||
#end
|
#end
|
||||||
@ -661,10 +681,7 @@ enum abstract DebugDrawMode(Int) from Int to Int {
|
|||||||
// We could use it in the future to toggle depth testing for lines, i.e. draw actual 3D lines if not set and Kha's g2 lines if set.
|
// We could use it in the future to toggle depth testing for lines, i.e. draw actual 3D lines if not set and Kha's g2 lines if set.
|
||||||
var FastWireframe = 1 << 13;
|
var FastWireframe = 1 << 13;
|
||||||
|
|
||||||
/**
|
/** Draw the normal vectors of the triangles of the physics collider meshes. **/
|
||||||
Draw the normal vectors of the triangles of the physics collider meshes.
|
|
||||||
This only works for `Mesh` collision shapes.
|
|
||||||
**/
|
|
||||||
// Outside of Leenkx this works for a few more collision shapes
|
// Outside of Leenkx this works for a few more collision shapes
|
||||||
var DrawNormals = 1 << 14;
|
var DrawNormals = 1 << 14;
|
||||||
|
|
||||||
|
@ -3035,6 +3035,7 @@ Make sure the mesh only has tris/quads.""")
|
|||||||
debug_draw_mode |= 16384 if wrd.lnx_bullet_dbg_draw_normals else 0
|
debug_draw_mode |= 16384 if wrd.lnx_bullet_dbg_draw_normals else 0
|
||||||
debug_draw_mode |= 32768 if wrd.lnx_bullet_dbg_draw_axis_gizmo else 0
|
debug_draw_mode |= 32768 if wrd.lnx_bullet_dbg_draw_axis_gizmo else 0
|
||||||
out_trait['parameters'].append(str(debug_draw_mode))
|
out_trait['parameters'].append(str(debug_draw_mode))
|
||||||
|
out_trait['parameters'].append(str(wrd.lnx_bullet_dbg_draw_raycast).lower())
|
||||||
|
|
||||||
self.output['traits'].append(out_trait)
|
self.output['traits'].append(out_trait)
|
||||||
|
|
||||||
|
@ -132,6 +132,7 @@ def always() -> float:
|
|||||||
return 0.5
|
return 0.5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def poll_threads() -> float:
|
def poll_threads() -> float:
|
||||||
"""Polls the thread callback queue and if a thread has finished, it
|
"""Polls the thread callback queue and if a thread has finished, it
|
||||||
is joined with the main thread and the corresponding callback is
|
is joined with the main thread and the corresponding callback is
|
||||||
@ -141,21 +142,27 @@ def poll_threads() -> float:
|
|||||||
thread, callback = make.thread_callback_queue.get(block=False)
|
thread, callback = make.thread_callback_queue.get(block=False)
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
return 0.25
|
return 0.25
|
||||||
|
if thread.is_alive():
|
||||||
thread.join()
|
try:
|
||||||
|
make.thread_callback_queue.put((thread, callback), block=False)
|
||||||
try:
|
except queue.Full:
|
||||||
callback()
|
return 0.5
|
||||||
except Exception as e:
|
return 0.1
|
||||||
# If there is an exception, we can no longer return the time to
|
else:
|
||||||
# the next call to this polling function, so to keep it running
|
try:
|
||||||
# we re-register it and then raise the original exception.
|
thread.join()
|
||||||
bpy.app.timers.unregister(poll_threads)
|
callback()
|
||||||
bpy.app.timers.register(poll_threads, first_interval=0.01, persistent=True)
|
except Exception as e:
|
||||||
raise e
|
# If there is an exception, we can no longer return the time to
|
||||||
|
# the next call to this polling function, so to keep it running
|
||||||
# Quickly check if another thread has finished
|
# we re-register it and then raise the original exception.
|
||||||
return 0.01
|
try:
|
||||||
|
bpy.app.timers.unregister(poll_threads)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
bpy.app.timers.register(poll_threads, first_interval=0.01, persistent=True)
|
||||||
|
# Quickly check if another thread has finished
|
||||||
|
return 0.01
|
||||||
|
|
||||||
|
|
||||||
loaded_py_libraries: dict[str, types.ModuleType] = {}
|
loaded_py_libraries: dict[str, types.ModuleType] = {}
|
||||||
|
@ -201,6 +201,10 @@ def init_properties():
|
|||||||
name="Collider Wireframes", default=False,
|
name="Collider Wireframes", default=False,
|
||||||
description="Draw wireframes of the physics collider meshes and suspensions of raycast vehicle simulations"
|
description="Draw wireframes of the physics collider meshes and suspensions of raycast vehicle simulations"
|
||||||
)
|
)
|
||||||
|
bpy.types.World.lnx_bullet_dbg_draw_raycast = BoolProperty(
|
||||||
|
name="Trace Raycast", default=False,
|
||||||
|
description="Draw raycasts to trace the results"
|
||||||
|
)
|
||||||
bpy.types.World.lnx_bullet_dbg_draw_aabb = BoolProperty(
|
bpy.types.World.lnx_bullet_dbg_draw_aabb = BoolProperty(
|
||||||
name="Axis-aligned Minimum Bounding Boxes", default=False,
|
name="Axis-aligned Minimum Bounding Boxes", default=False,
|
||||||
description="Draw axis-aligned minimum bounding boxes (AABBs) of the physics collider meshes"
|
description="Draw axis-aligned minimum bounding boxes (AABBs) of the physics collider meshes"
|
||||||
|
@ -2756,6 +2756,7 @@ class LNX_PT_BulletDebugDrawingPanel(bpy.types.Panel):
|
|||||||
|
|
||||||
col = layout.column(align=False)
|
col = layout.column(align=False)
|
||||||
col.prop(wrd, "lnx_bullet_dbg_draw_wireframe")
|
col.prop(wrd, "lnx_bullet_dbg_draw_wireframe")
|
||||||
|
col.prop(wrd, "lnx_bullet_dbg_draw_raycast")
|
||||||
col.prop(wrd, "lnx_bullet_dbg_draw_aabb")
|
col.prop(wrd, "lnx_bullet_dbg_draw_aabb")
|
||||||
col.prop(wrd, "lnx_bullet_dbg_draw_contact_points")
|
col.prop(wrd, "lnx_bullet_dbg_draw_contact_points")
|
||||||
col.prop(wrd, "lnx_bullet_dbg_draw_constraints")
|
col.prop(wrd, "lnx_bullet_dbg_draw_constraints")
|
||||||
|
@ -579,6 +579,18 @@ HL_PRIM float HL_NAME(btVector3_length0)(_ref(btVector3)* _this) {
|
|||||||
}
|
}
|
||||||
DEFINE_PRIM(_F32, btVector3_length0, _IDL);
|
DEFINE_PRIM(_F32, btVector3_length0, _IDL);
|
||||||
|
|
||||||
|
HL_PRIM float* HL_NAME(btFloatArray_set_raw)( _ref(btFloatArray)* _this, float* value ) {
|
||||||
|
_unref(_this)->raw = (value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
DEFINE_PRIM(_BYTES,btFloatArray_set_raw,_IDL _BYTES);
|
||||||
|
|
||||||
|
HL_PRIM int* HL_NAME(btIntArray_set_raw)( _ref(btIntArray)* _this, int* value ) {
|
||||||
|
_unref(_this)->raw = (value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
DEFINE_PRIM(_BYTES,btIntArray_get_raw,_IDL);
|
||||||
|
|
||||||
HL_PRIM float HL_NAME(btVector3_x0)(_ref(btVector3)* _this) {
|
HL_PRIM float HL_NAME(btVector3_x0)(_ref(btVector3)* _this) {
|
||||||
return _unref(_this)->x();
|
return _unref(_this)->x();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user