refactor: DynamicUpdateTool

This commit is contained in:
ikpil 2023-09-12 00:06:12 +09:00
parent a4da8001e6
commit db6b222e25
5 changed files with 348 additions and 207 deletions

View File

@ -1,22 +1,106 @@
namespace DotRecast.Core namespace DotRecast.Core
{ {
public struct RcMatrix4x4 public struct RcMatrix4x4f
{ {
public float m11; private static readonly RcMatrix4x4f _identity = new RcMatrix4x4f
public float m12; (
public float m13; 1f, 0f, 0f, 0f,
public float m14; 0f, 1f, 0f, 0f,
public float m21; 0f, 0f, 1f, 0f,
public float m22; 0f, 0f, 0f, 1f
public float m23; );
public float m24;
public float m31; public float M11;
public float m32; public float M12;
public float m33; public float M13;
public float m34; public float M14;
public float m41; public float M21;
public float m42; public float M22;
public float m43; public float M23;
public float m44; public float M24;
public float M31;
public float M32;
public float M33;
public float M34;
public float M41;
public float M42;
public float M43;
public float M44;
public RcMatrix4x4f(
float m11, float m12, float m13, float m14,
float m21, float m22, float m23, float m24,
float m31, float m32, float m33, float m34,
float m41, float m42, float m43, float m44)
{
M11 = m11;
M12 = m12;
M13 = m13;
M14 = m14;
M21 = m21;
M22 = m22;
M23 = m23;
M24 = m24;
M31 = m31;
M32 = m32;
M33 = m33;
M34 = m34;
M41 = m41;
M42 = m42;
M43 = m43;
M44 = m44;
}
public static RcMatrix4x4f Identity => _identity;
public readonly bool IsIdentity =>
M11.Equals(1f) && M22.Equals(1f) && M33.Equals(1f) && M44.Equals(1f) &&
M12 == 0f && M13 == 0f && M14 == 0f &&
M21 == 0f && M23 == 0f && M24 == 0f &&
M31 == 0f && M32 == 0f && M34 == 0f &&
M41 == 0f && M42 == 0f && M43 == 0f;
public static RcMatrix4x4f Mul(RcMatrix4x4f left, RcMatrix4x4f right)
{
float m11 = left.M11 * right.M11 + left.M21 * right.M12 + left.M31 * right.M13 + left.M41 * right.M14;
float m12 = left.M12 * right.M11 + left.M22 * right.M12 + left.M32 * right.M13 + left.M42 * right.M14;
float m13 = left.M13 * right.M11 + left.M23 * right.M12 + left.M33 * right.M13 + left.M43 * right.M14;
float m14 = left.M14 * right.M11 + left.M24 * right.M12 + left.M34 * right.M13 + left.M44 * right.M14;
float m21 = left.M11 * right.M21 + left.M21 * right.M22 + left.M31 * right.M23 + left.M41 * right.M24;
float m22 = left.M12 * right.M21 + left.M22 * right.M22 + left.M32 * right.M23 + left.M42 * right.M24;
float m23 = left.M13 * right.M21 + left.M23 * right.M22 + left.M33 * right.M23 + left.M43 * right.M24;
float m24 = left.M14 * right.M21 + left.M24 * right.M22 + left.M34 * right.M23 + left.M44 * right.M24;
float m31 = left.M11 * right.M31 + left.M21 * right.M32 + left.M31 * right.M33 + left.M41 * right.M34;
float m32 = left.M12 * right.M31 + left.M22 * right.M32 + left.M32 * right.M33 + left.M42 * right.M34;
float m33 = left.M13 * right.M31 + left.M23 * right.M32 + left.M33 * right.M33 + left.M43 * right.M34;
float m34 = left.M14 * right.M31 + left.M24 * right.M32 + left.M34 * right.M33 + left.M44 * right.M34;
float m41 = left.M11 * right.M41 + left.M21 * right.M42 + left.M31 * right.M43 + left.M41 * right.M44;
float m42 = left.M12 * right.M41 + left.M22 * right.M42 + left.M32 * right.M43 + left.M42 * right.M44;
float m43 = left.M13 * right.M41 + left.M23 * right.M42 + left.M33 * right.M43 + left.M43 * right.M44;
float m44 = left.M14 * right.M41 + left.M24 * right.M42 + left.M34 * right.M43 + left.M44 * right.M44;
RcMatrix4x4f dest = new RcMatrix4x4f();
dest.M11 = m11;
dest.M12 = m12;
dest.M13 = m13;
dest.M14 = m14;
dest.M21 = m21;
dest.M22 = m22;
dest.M23 = m23;
dest.M24 = m24;
dest.M31 = m31;
dest.M32 = m32;
dest.M33 = m33;
dest.M34 = m34;
dest.M41 = m41;
dest.M42 = m42;
dest.M43 = m43;
dest.M44 = m44;
return dest;
}
} }
} }

View File

@ -83,10 +83,7 @@ public class DynamicUpdateSampleTool : ISampleTool
private DynamicNavMesh dynaMesh; private DynamicNavMesh dynaMesh;
private readonly TaskFactory executor; private readonly TaskFactory executor;
private readonly Dictionary<long, RcGizmo> colliderGizmos = new(); private readonly Dictionary<long, RcGizmo> colliderGizmos = new();
private readonly Random random = Random.Shared;
private readonly DemoInputGeomProvider bridgeGeom;
private readonly DemoInputGeomProvider houseGeom;
private readonly DemoInputGeomProvider convexGeom;
private bool sposSet; private bool sposSet;
private bool eposSet; private bool eposSet;
private RcVec3f spos; private RcVec3f spos;
@ -96,11 +93,11 @@ public class DynamicUpdateSampleTool : ISampleTool
public DynamicUpdateSampleTool() public DynamicUpdateSampleTool()
{ {
_tool = new(); var bridgeGeom = DemoObjImporter.Load(Loader.ToBytes("bridge.obj"));
var houseGeom = DemoObjImporter.Load(Loader.ToBytes("house.obj"));
var convexGeom = DemoObjImporter.Load(Loader.ToBytes("convex.obj"));
_tool = new(Random.Shared, bridgeGeom, houseGeom, convexGeom);
executor = Task.Factory; executor = Task.Factory;
bridgeGeom = DemoObjImporter.Load(Loader.ToBytes("bridge.obj"));
houseGeom = DemoObjImporter.Load(Loader.ToBytes("house.obj"));
convexGeom = DemoObjImporter.Load(Loader.ToBytes("convex.obj"));
} }
public void Layout() public void Layout()
@ -371,35 +368,35 @@ public class DynamicUpdateSampleTool : ISampleTool
{ {
if (colliderShape == DynamicColliderShape.SPHERE) if (colliderShape == DynamicColliderShape.SPHERE)
{ {
colliderWithGizmo = SphereCollider(p); colliderWithGizmo = _tool.SphereCollider(p, dynaMesh.config.walkableClimb);
} }
else if (colliderShape == DynamicColliderShape.CAPSULE) else if (colliderShape == DynamicColliderShape.CAPSULE)
{ {
colliderWithGizmo = CapsuleCollider(p); colliderWithGizmo = _tool.CapsuleCollider(p, dynaMesh.config.walkableClimb);
} }
else if (colliderShape == DynamicColliderShape.BOX) else if (colliderShape == DynamicColliderShape.BOX)
{ {
colliderWithGizmo = BoxCollider(p); colliderWithGizmo = _tool.BoxCollider(p, dynaMesh.config.walkableClimb);
} }
else if (colliderShape == DynamicColliderShape.CYLINDER) else if (colliderShape == DynamicColliderShape.CYLINDER)
{ {
colliderWithGizmo = CylinderCollider(p); colliderWithGizmo = _tool.CylinderCollider(p, dynaMesh.config.walkableClimb);
} }
else if (colliderShape == DynamicColliderShape.COMPOSITE) else if (colliderShape == DynamicColliderShape.COMPOSITE)
{ {
colliderWithGizmo = CompositeCollider(p); colliderWithGizmo = _tool.CompositeCollider(p, dynaMesh.config.walkableClimb);
} }
else if (colliderShape == DynamicColliderShape.TRIMESH_BRIDGE) else if (colliderShape == DynamicColliderShape.TRIMESH_BRIDGE)
{ {
colliderWithGizmo = TrimeshBridge(p); colliderWithGizmo = _tool.TrimeshBridge(p, dynaMesh.config.walkableClimb);
} }
else if (colliderShape == DynamicColliderShape.TRIMESH_HOUSE) else if (colliderShape == DynamicColliderShape.TRIMESH_HOUSE)
{ {
colliderWithGizmo = TrimeshHouse(p); colliderWithGizmo = _tool.TrimeshHouse(p, dynaMesh.config.walkableClimb);
} }
else if (colliderShape == DynamicColliderShape.CONVEX) else if (colliderShape == DynamicColliderShape.CONVEX)
{ {
colliderWithGizmo = ConvexTrimesh(p); colliderWithGizmo = _tool.ConvexTrimesh(p, dynaMesh.config.walkableClimb);
} }
} }
@ -440,177 +437,6 @@ public class DynamicUpdateSampleTool : ISampleTool
} }
} }
private RcGizmo SphereCollider(RcVec3f p)
{
float radius = 1 + (float)random.NextDouble() * 10;
var collider = new SphereCollider(p, radius, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, dynaMesh.config.walkableClimb);
var gizmo = GizmoFactory.Sphere(p, radius);
return new RcGizmo(collider, gizmo);
}
private RcGizmo CapsuleCollider(RcVec3f p)
{
float radius = 0.4f + (float)random.NextDouble() * 4f;
RcVec3f a = RcVec3f.Of(
(1f - 2 * (float)random.NextDouble()),
0.01f + (float)random.NextDouble(),
(1f - 2 * (float)random.NextDouble())
);
a.Normalize();
float len = 1f + (float)random.NextDouble() * 20f;
a.x *= len;
a.y *= len;
a.z *= len;
RcVec3f start = RcVec3f.Of(p.x, p.y, p.z);
RcVec3f end = RcVec3f.Of(p.x + a.x, p.y + a.y, p.z + a.z);
var collider = new CapsuleCollider(start, end, radius, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, dynaMesh.config.walkableClimb);
var gizmo = GizmoFactory.Capsule(start, end, radius);
return new RcGizmo(collider, gizmo);
}
private RcGizmo BoxCollider(RcVec3f p)
{
RcVec3f extent = RcVec3f.Of(
0.5f + (float)random.NextDouble() * 6f,
0.5f + (float)random.NextDouble() * 6f,
0.5f + (float)random.NextDouble() * 6f
);
RcVec3f forward = RcVec3f.Of((1f - 2 * (float)random.NextDouble()), 0, (1f - 2 * (float)random.NextDouble()));
RcVec3f up = RcVec3f.Of((1f - 2 * (float)random.NextDouble()), 0.01f + (float)random.NextDouble(), (1f - 2 * (float)random.NextDouble()));
RcVec3f[] halfEdges = Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(up, forward, extent);
var collider = new BoxCollider(p, halfEdges, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, dynaMesh.config.walkableClimb);
var gizmo = GizmoFactory.Box(p, halfEdges);
return new RcGizmo(collider, gizmo);
}
private RcGizmo CylinderCollider(RcVec3f p)
{
float radius = 0.7f + (float)random.NextDouble() * 4f;
RcVec3f a = RcVec3f.Of(1f - 2 * (float)random.NextDouble(), 0.01f + (float)random.NextDouble(), 1f - 2 * (float)random.NextDouble());
a.Normalize();
float len = 2f + (float)random.NextDouble() * 20f;
a[0] *= len;
a[1] *= len;
a[2] *= len;
RcVec3f start = RcVec3f.Of(p.x, p.y, p.z);
RcVec3f end = RcVec3f.Of(p.x + a.x, p.y + a.y, p.z + a.z);
var collider = new CylinderCollider(start, end, radius, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, dynaMesh.config.walkableClimb);
var gizmo = GizmoFactory.Cylinder(start, end, radius);
return new RcGizmo(collider, gizmo);
}
private RcGizmo CompositeCollider(RcVec3f p)
{
RcVec3f baseExtent = RcVec3f.Of(5, 3, 8);
RcVec3f baseCenter = RcVec3f.Of(p.x, p.y + 3, p.z);
RcVec3f baseUp = RcVec3f.Of(0, 1, 0);
RcVec3f forward = RcVec3f.Of((1f - 2 * (float)random.NextDouble()), 0, (1f - 2 * (float)random.NextDouble()));
forward.Normalize();
RcVec3f side = RcVec3f.Cross(forward, baseUp);
BoxCollider @base = new BoxCollider(baseCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(baseUp, forward, baseExtent),
SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD, dynaMesh.config.walkableClimb);
var roofUp = RcVec3f.Zero;
RcVec3f roofExtent = RcVec3f.Of(4.5f, 4.5f, 8f);
float[] rx = GLU.Build_4x4_rotation_matrix(45, forward.x, forward.y, forward.z);
roofUp = MulMatrixVector(ref roofUp, rx, baseUp);
RcVec3f roofCenter = RcVec3f.Of(p.x, p.y + 6, p.z);
BoxCollider roof = new BoxCollider(roofCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(roofUp, forward, roofExtent),
SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD, dynaMesh.config.walkableClimb);
RcVec3f trunkStart = RcVec3f.Of(
baseCenter.x - forward.x * 15 + side.x * 6,
p.y,
baseCenter.z - forward.z * 15 + side.z * 6
);
RcVec3f trunkEnd = RcVec3f.Of(trunkStart.x, trunkStart.y + 10, trunkStart.z);
CapsuleCollider trunk = new CapsuleCollider(trunkStart, trunkEnd, 0.5f, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD,
dynaMesh.config.walkableClimb);
RcVec3f crownCenter = RcVec3f.Of(
baseCenter.x - forward.x * 15 + side.x * 6, p.y + 10,
baseCenter.z - forward.z * 15 + side.z * 6
);
SphereCollider crown = new SphereCollider(crownCenter, 4f, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS,
dynaMesh.config.walkableClimb);
CompositeCollider collider = new CompositeCollider(@base, roof, trunk, crown);
IRcGizmoMeshFilter baseGizmo = GizmoFactory.Box(baseCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(baseUp, forward, baseExtent));
IRcGizmoMeshFilter roofGizmo = GizmoFactory.Box(roofCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(roofUp, forward, roofExtent));
IRcGizmoMeshFilter trunkGizmo = GizmoFactory.Capsule(trunkStart, trunkEnd, 0.5f);
IRcGizmoMeshFilter crownGizmo = GizmoFactory.Sphere(crownCenter, 4f);
IRcGizmoMeshFilter gizmo = GizmoFactory.Composite(baseGizmo, roofGizmo, trunkGizmo, crownGizmo);
return new RcGizmo(collider, gizmo);
}
private RcGizmo TrimeshBridge(RcVec3f p)
{
return TrimeshCollider(p, bridgeGeom);
}
private RcGizmo TrimeshHouse(RcVec3f p)
{
return TrimeshCollider(p, houseGeom);
}
private RcGizmo ConvexTrimesh(RcVec3f p)
{
float[] verts = TransformVertices(p, convexGeom, 360);
var collider = new ConvexTrimeshCollider(verts, convexGeom.faces,
SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD, dynaMesh.config.walkableClimb * 10);
var gizmo = GizmoFactory.Trimesh(verts, convexGeom.faces);
return new RcGizmo(collider, gizmo);
}
private RcGizmo TrimeshCollider(RcVec3f p, DemoInputGeomProvider geom)
{
float[] verts = TransformVertices(p, geom, 0);
var collider = new TrimeshCollider(verts, geom.faces, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD,
dynaMesh.config.walkableClimb * 10);
var gizmo = GizmoFactory.Trimesh(verts, geom.faces);
return new RcGizmo(collider, gizmo);
}
private float[] TransformVertices(RcVec3f p, DemoInputGeomProvider geom, float ax)
{
float[] rx = GLU.Build_4x4_rotation_matrix((float)random.NextDouble() * ax, 1, 0, 0);
float[] ry = GLU.Build_4x4_rotation_matrix((float)random.NextDouble() * 360, 0, 1, 0);
float[] m = GLU.Mul(rx, ry);
float[] verts = new float[geom.vertices.Length];
RcVec3f v = new RcVec3f();
RcVec3f vr = new RcVec3f();
for (int i = 0; i < geom.vertices.Length; i += 3)
{
v.x = geom.vertices[i];
v.y = geom.vertices[i + 1];
v.z = geom.vertices[i + 2];
MulMatrixVector(ref vr, m, v);
vr.x += p.x;
vr.y += p.y - 0.1f;
vr.z += p.z;
verts[i] = vr.x;
verts[i + 1] = vr.y;
verts[i + 2] = vr.z;
}
return verts;
}
private float[] MulMatrixVector(float[] resultvector, float[] matrix, float[] pvector)
{
resultvector[0] = matrix[0] * pvector[0] + matrix[4] * pvector[1] + matrix[8] * pvector[2];
resultvector[1] = matrix[1] * pvector[0] + matrix[5] * pvector[1] + matrix[9] * pvector[2];
resultvector[2] = matrix[2] * pvector[0] + matrix[6] * pvector[1] + matrix[10] * pvector[2];
return resultvector;
}
private RcVec3f MulMatrixVector(ref RcVec3f resultvector, float[] matrix, RcVec3f pvector)
{
resultvector.x = matrix[0] * pvector.x + matrix[4] * pvector.y + matrix[8] * pvector.z;
resultvector.y = matrix[1] * pvector.x + matrix[5] * pvector.y + matrix[9] * pvector.z;
resultvector.z = matrix[2] * pvector.x + matrix[6] * pvector.y + matrix[10] * pvector.z;
return resultvector;
}
public void HandleClickRay(RcVec3f start, RcVec3f dir, bool shift) public void HandleClickRay(RcVec3f start, RcVec3f dir, bool shift)
{ {

View File

@ -1,9 +1,10 @@
using System; using System;
using System.Numerics;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Numerics;
using ImGuiNET; using ImGuiNET;
using Serilog; using Serilog;

View File

@ -16,7 +16,7 @@ freely, subject to the following restrictions:
3. This notice may not be removed or altered from any source distribution. 3. This notice may not be removed or altered from any source distribution.
*/ */
using System.Numerics;
using ImGuiNET; using ImGuiNET;
using Serilog; using Serilog;
using Serilog.Core; using Serilog.Core;

View File

@ -1,11 +1,30 @@
using System.IO; using System;
using System.IO;
using DotRecast.Core; using DotRecast.Core;
using DotRecast.Detour.Dynamic.Colliders;
using DotRecast.Detour.Dynamic.Io; using DotRecast.Detour.Dynamic.Io;
using DotRecast.Recast.Toolset.Builder;
using DotRecast.Recast.Toolset.Geom;
using DotRecast.Recast.Toolset.Gizmos;
namespace DotRecast.Recast.Toolset.Tools namespace DotRecast.Recast.Toolset.Tools
{ {
public class RcDynamicUpdateTool : IRcToolable public class RcDynamicUpdateTool : IRcToolable
{ {
private readonly Random random;
private readonly DemoInputGeomProvider bridgeGeom;
private readonly DemoInputGeomProvider houseGeom;
private readonly DemoInputGeomProvider convexGeom;
public RcDynamicUpdateTool(Random rand, DemoInputGeomProvider bridgeGeom, DemoInputGeomProvider houseGeom, DemoInputGeomProvider convexGeom)
{
this.random = rand;
this.bridgeGeom = bridgeGeom;
this.houseGeom = houseGeom;
this.convexGeom = convexGeom;
}
public string GetName() public string GetName()
{ {
return "Dynamic Updates"; return "Dynamic Updates";
@ -28,5 +47,216 @@ namespace DotRecast.Recast.Toolset.Tools
VoxelFileWriter writer = new VoxelFileWriter(compressor); VoxelFileWriter writer = new VoxelFileWriter(compressor);
writer.Write(bw, voxelFile, compression); writer.Write(bw, voxelFile, compression);
} }
public RcGizmo SphereCollider(RcVec3f p, float walkableClimb)
{
float radius = 1 + (float)random.NextDouble() * 10;
var collider = new SphereCollider(p, radius, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, walkableClimb);
var gizmo = GizmoFactory.Sphere(p, radius);
return new RcGizmo(collider, gizmo);
}
public RcGizmo CapsuleCollider(RcVec3f p, float walkableClimb)
{
float radius = 0.4f + (float)random.NextDouble() * 4f;
RcVec3f a = RcVec3f.Of(
(1f - 2 * (float)random.NextDouble()),
0.01f + (float)random.NextDouble(),
(1f - 2 * (float)random.NextDouble())
);
a.Normalize();
float len = 1f + (float)random.NextDouble() * 20f;
a.x *= len;
a.y *= len;
a.z *= len;
RcVec3f start = RcVec3f.Of(p.x, p.y, p.z);
RcVec3f end = RcVec3f.Of(p.x + a.x, p.y + a.y, p.z + a.z);
var collider = new CapsuleCollider(start, end, radius, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, walkableClimb);
var gizmo = GizmoFactory.Capsule(start, end, radius);
return new RcGizmo(collider, gizmo);
}
public RcGizmo BoxCollider(RcVec3f p, float walkableClimb)
{
RcVec3f extent = RcVec3f.Of(
0.5f + (float)random.NextDouble() * 6f,
0.5f + (float)random.NextDouble() * 6f,
0.5f + (float)random.NextDouble() * 6f
);
RcVec3f forward = RcVec3f.Of((1f - 2 * (float)random.NextDouble()), 0, (1f - 2 * (float)random.NextDouble()));
RcVec3f up = RcVec3f.Of((1f - 2 * (float)random.NextDouble()), 0.01f + (float)random.NextDouble(), (1f - 2 * (float)random.NextDouble()));
RcVec3f[] halfEdges = Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(up, forward, extent);
var collider = new BoxCollider(p, halfEdges, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, walkableClimb);
var gizmo = GizmoFactory.Box(p, halfEdges);
return new RcGizmo(collider, gizmo);
}
public RcGizmo CylinderCollider(RcVec3f p, float walkableClimb)
{
float radius = 0.7f + (float)random.NextDouble() * 4f;
RcVec3f a = RcVec3f.Of(1f - 2 * (float)random.NextDouble(), 0.01f + (float)random.NextDouble(), 1f - 2 * (float)random.NextDouble());
a.Normalize();
float len = 2f + (float)random.NextDouble() * 20f;
a[0] *= len;
a[1] *= len;
a[2] *= len;
RcVec3f start = RcVec3f.Of(p.x, p.y, p.z);
RcVec3f end = RcVec3f.Of(p.x + a.x, p.y + a.y, p.z + a.z);
var collider = new CylinderCollider(start, end, radius, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_WATER, walkableClimb);
var gizmo = GizmoFactory.Cylinder(start, end, radius);
return new RcGizmo(collider, gizmo);
}
public RcGizmo CompositeCollider(RcVec3f p, float walkableClimb)
{
RcVec3f baseExtent = RcVec3f.Of(5, 3, 8);
RcVec3f baseCenter = RcVec3f.Of(p.x, p.y + 3, p.z);
RcVec3f baseUp = RcVec3f.Of(0, 1, 0);
RcVec3f forward = RcVec3f.Of((1f - 2 * (float)random.NextDouble()), 0, (1f - 2 * (float)random.NextDouble()));
forward.Normalize();
RcVec3f side = RcVec3f.Cross(forward, baseUp);
BoxCollider @base = new BoxCollider(baseCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(baseUp, forward, baseExtent),
SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD, walkableClimb);
var roofUp = RcVec3f.Zero;
RcVec3f roofExtent = RcVec3f.Of(4.5f, 4.5f, 8f);
var rx = Matrix(45, forward.x, forward.y, forward.z);
roofUp = MulMatrixVector(ref roofUp, rx, baseUp);
RcVec3f roofCenter = RcVec3f.Of(p.x, p.y + 6, p.z);
BoxCollider roof = new BoxCollider(roofCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(roofUp, forward, roofExtent),
SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD, walkableClimb);
RcVec3f trunkStart = RcVec3f.Of(
baseCenter.x - forward.x * 15 + side.x * 6,
p.y,
baseCenter.z - forward.z * 15 + side.z * 6
);
RcVec3f trunkEnd = RcVec3f.Of(trunkStart.x, trunkStart.y + 10, trunkStart.z);
CapsuleCollider trunk = new CapsuleCollider(trunkStart, trunkEnd, 0.5f, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD,
walkableClimb);
RcVec3f crownCenter = RcVec3f.Of(
baseCenter.x - forward.x * 15 + side.x * 6, p.y + 10,
baseCenter.z - forward.z * 15 + side.z * 6
);
SphereCollider crown = new SphereCollider(crownCenter, 4f, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_GRASS,
walkableClimb);
CompositeCollider collider = new CompositeCollider(@base, roof, trunk, crown);
IRcGizmoMeshFilter baseGizmo = GizmoFactory.Box(baseCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(baseUp, forward, baseExtent));
IRcGizmoMeshFilter roofGizmo = GizmoFactory.Box(roofCenter, Detour.Dynamic.Colliders.BoxCollider.GetHalfEdges(roofUp, forward, roofExtent));
IRcGizmoMeshFilter trunkGizmo = GizmoFactory.Capsule(trunkStart, trunkEnd, 0.5f);
IRcGizmoMeshFilter crownGizmo = GizmoFactory.Sphere(crownCenter, 4f);
IRcGizmoMeshFilter gizmo = GizmoFactory.Composite(baseGizmo, roofGizmo, trunkGizmo, crownGizmo);
return new RcGizmo(collider, gizmo);
}
public RcGizmo TrimeshBridge(RcVec3f p, float walkableClimb)
{
return TrimeshCollider(p, bridgeGeom, walkableClimb);
}
public RcGizmo TrimeshHouse(RcVec3f p, float walkableClimb)
{
return TrimeshCollider(p, houseGeom, walkableClimb);
}
public RcGizmo ConvexTrimesh(RcVec3f p, float walkableClimb)
{
float[] verts = TransformVertices(p, convexGeom, 360);
var collider = new ConvexTrimeshCollider(verts, convexGeom.faces,
SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD, walkableClimb * 10);
var gizmo = GizmoFactory.Trimesh(verts, convexGeom.faces);
return new RcGizmo(collider, gizmo);
}
private RcGizmo TrimeshCollider(RcVec3f p, DemoInputGeomProvider geom, float walkableClimb)
{
float[] verts = TransformVertices(p, geom, 0);
var collider = new TrimeshCollider(verts, geom.faces, SampleAreaModifications.SAMPLE_POLYAREA_TYPE_ROAD,
walkableClimb * 10);
var gizmo = GizmoFactory.Trimesh(verts, geom.faces);
return new RcGizmo(collider, gizmo);
}
private float[] TransformVertices(RcVec3f p, DemoInputGeomProvider geom, float ax)
{
var rx = Matrix((float)random.NextDouble() * ax, 1, 0, 0);
var ry = Matrix((float)random.NextDouble() * 360, 0, 1, 0);
var m = RcMatrix4x4f.Mul(rx, ry);
float[] verts = new float[geom.vertices.Length];
RcVec3f v = new RcVec3f();
RcVec3f vr = new RcVec3f();
for (int i = 0; i < geom.vertices.Length; i += 3)
{
v.x = geom.vertices[i];
v.y = geom.vertices[i + 1];
v.z = geom.vertices[i + 2];
MulMatrixVector(ref vr, m, v);
vr.x += p.x;
vr.y += p.y - 0.1f;
vr.z += p.z;
verts[i] = vr.x;
verts[i + 1] = vr.y;
verts[i + 2] = vr.z;
}
return verts;
}
private static float[] MulMatrixVector(float[] resultvector, float[] matrix, float[] pvector)
{
resultvector[0] = matrix[0] * pvector[0] + matrix[4] * pvector[1] + matrix[8] * pvector[2];
resultvector[1] = matrix[1] * pvector[0] + matrix[5] * pvector[1] + matrix[9] * pvector[2];
resultvector[2] = matrix[2] * pvector[0] + matrix[6] * pvector[1] + matrix[10] * pvector[2];
return resultvector;
}
private static RcVec3f MulMatrixVector(ref RcVec3f resultvector, RcMatrix4x4f matrix, RcVec3f pvector)
{
resultvector.x = matrix.M11 * pvector.x + matrix.M21 * pvector.y + matrix.M31 * pvector.z;
resultvector.y = matrix.M12 * pvector.x + matrix.M22 * pvector.y + matrix.M32 * pvector.z;
resultvector.z = matrix.M13 * pvector.x + matrix.M23 * pvector.y + matrix.M33 * pvector.z;
return resultvector;
}
public static RcMatrix4x4f Matrix(float a, float x, float y, float z)
{
var matrix = new RcMatrix4x4f();
a = (float)(a * Math.PI / 180.0); // convert to radians
float s = (float)Math.Sin(a);
float c = (float)Math.Cos(a);
float t = 1.0f - c;
float tx = t * x;
float ty = t * y;
float tz = t * z;
float sz = s * z;
float sy = s * y;
float sx = s * x;
matrix.M11 = tx * x + c;
matrix.M12 = tx * y + sz;
matrix.M13 = tx * z - sy;
matrix.M14 = 0;
matrix.M21 = tx * y - sz;
matrix.M22 = ty * y + c;
matrix.M23 = ty * z + sx;
matrix.M24 = 0;
matrix.M31 = tx * z + sy;
matrix.M32 = ty * z - sx;
matrix.M33 = tz * z + c;
matrix.M34 = 0;
matrix.M41 = 0;
matrix.M42 = 0;
matrix.M43 = 0;
matrix.M44 = 1;
return matrix;
}
} }
} }